cache mysql maison

Discussion dans 'Développement d'un site Web ou d'une appli mobile' créé par ortolojf, 18 Février 2019.

  1. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour

    J'ai MariaDB récente avec query_cache_size à zéro.

    J'ai fait une librairie ORM ( Object Relational Mapping) d'accès MySQL.

    Je compte implémenter un cache MySQL maison, tel que les requêtes les plus anciennes soient effacées d'abord.

    Mais comment identifier les requêtes MySQL dans le cache, pour les apparier avec celles exécutées dans les fichiers php ?

    D'après un hash code ?

    Celui de la requête MySQL alpĥabétique ?

    Merci beaucoup pour vos réponses.

    Amicalement.
     
  2. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Rebond

    Le problème ( me semble-t-il ) , serait de normaliser la rédaction des requêtes MySQL ( avec mon ORM ), pour que deux requêtes de fonctionnalité et paramètres identiques, aient le même hash code ( c'est-à-dire en théorie exactement la même requête alphabétique ).

    Comment faire celà
     
  3. colonies
    colonies WRInaute occasionnel
    Inscrit:
    10 Septembre 2006
    Messages:
    441
    J'aime reçus:
    36
    Pourquoi se lancer dans un truc pareil ? Tu n'arriveras jamais à optimiser aussi bien que MariaDB qui profite de plus de 20 ans d'optimisations et qui est écrit en C, C++.
    Si tu as un problème de perfs, c'est que tu devrais te pencher sur l'écriture des requêtes, les formats de tes colonnes, les index, ou éventuellement la configuration des caches de MariaDB (mais ça, c'est surtout quand on a une grosse base et du trafic).

    Bah c'est super simple, tu parses la requête, tu écris un optimiseur, et tu finis avec un résultat normalisé. N'oublie pas de tout optimiser, hein. Du genre un LIKE "Salut%", c'est identique à un LIKE "SALUT%" pour une colonne dont le type est insensible à la casse. Ou un WHERE colonnea > colonneb, c'est identique à colonneb < colonnea, ce genre de choses.
    Oh, et attention aux requêtes avec des fonctions, comme NOW(). Parce qu'un NOW() au moment de mettre en cache et de l'appel du cache, forcément, ça ne fonctionne plus. Mais bon, tu peux peut-être quand même faire un subset pour le reste de la requête.

    Ah oui, et ton idée d'effacer les requêtes les plus anciennes, c'est pas top. Ce qu'il faut faire c'est invalider les caches quand il y a une mise à jour des données (bien sûr), et garder en cache les requêtes les plus fréquentes et/ou les plus lourdes en priorité.
    Tu ne vas pas éliminer une requête qui est appelée sur chaque page et qui prend trois secondes si ta limite est de 40 requêtes, juste parce que le reste d'une page a nécessité 40 requêtes prenant 0,01 seconde chacune.

    En gros, pour être aussi performant, il faut que tu réécrives un bon gros bout de MariaDB, en suivant exactement sa logique, mais avec un overhead supérieur parce que ton code sera écrit en PHP.

    Après, si tu t'ennuies et que ça t'éclate, pourquoi pas, hein..
     
  4. spout
    spout WRInaute accro
    Inscrit:
    14 Mai 2003
    Messages:
    8 733
    J'aime reçus:
    233
    +1 @colonies
    Tu vas encore réinventer la roue... MySQL/MariaDB ont déjà un cache qui fait pareil.
    Lance une requête lourde 2 fois tu verras le temps d'exécution.
     
  5. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour colonies et spout

    Je croyais que MariaDB à partir de la version 10.1.7 désactivait le cache.

    C'est vrai qu'il suffit de mettre query_cache_size > 0 pour qu'il y ait un cache.

    Pour ce qui est de la priorité des requêtes à effacer, je voyais un mix des tailles et fréquences des requêtes, et du degré d'ancienneté.

    Pour la formule je ne sais pas.

    Le tout en RAM/fichier tmpfs. ( ou plusieurs fichiers suivant répertoire du script ).

    Comme j'ai fait cet ORM, je peux lui intégrer ce cache et faire l'optimiseur, vu que je parse déjà les instructions MySQL orientées objet.

    Je vais me pencher sur le problème de la fragmentation du/des fichiers cache.

    Merci beaucoup de votre aide.

    Amicalement.
     
  6. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Pardon

    Pour ce qui est de l'ordre dans lequel effacer les requêtes en cache, dans une première approche :

    - Ordre croissant : taille
    - Ordre croissant : ancienneté
    - Ordre croissant : fréquence

    Ou bien un ou deux indices composites de tri, calculés par une combinaison linéaire de type : indice_tri = a x + b y + c z / ( a + b + c ), et a, b et c progressivement ajustés par des mesures d'efficacité.

    Quelles mesures d'efficacité de timing ?

    Peut-être minorer les durées globales des requêtes ?

    Merci beaucoup pour vos réponses.

    Amicalement.
     
  7. spout
    spout WRInaute accro
    Inscrit:
    14 Mai 2003
    Messages:
    8 733
    J'aime reçus:
    233
     
  8. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour spout ;)

    Comme tout est affaire de pondération.

    J'ajusterais les a, b et c par recherches dichotomiques et/ou mesures ?

    Je vais faire tourner l'algorithme à la main.

    Merci beaucoup de ton aide.

    Amicalement.
     
  9. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Voili, voilou

    Donc : Fréquence et ancienneté, c'est la même chose.

    Effacement par :

    1) Durée réelles des requêtes avant cache,
    2) Fréquence/ancienneté.

    J'envisage de normaliser les coefficients a et b de la combinaison linéaire, avec les écarts-types et valeurs totales.

    De manière à ce que les écarts à la moyenne des composantes a x et b y soient à peu près similaires.

    Celà vous paraît-il viable ?

    Merci pour votre aide.

    Amicalement.
     
  10. rick38
    rick38 WRInaute passionné
    Inscrit:
    23 Février 2013
    Messages:
    1 062
    J'aime reçus:
    108
    Alors je ne comprends rien à ces histoires de math, mais si vous parlez de caches disque (et non mémoire), perso j'ai mis mes fichiers de cache dans des dossiers temporaires qui correspondent chacun à la table principale qui est attaquée par les requêtes (même nom en fait).
    Ensuite, quand une donnée est changée dans la table (ou dans une des tables secondaires de ces requêtes), je renomme le dossier (ce qui est instantané, quel que soit le nombre de fichiers), le recrée pour accueillir peu à peu à nouveau les résultats des requêtes.
    Et dans une commande shell en parallèle non blocante (mais ça pourrait être un script cron lancé n'importe quand), je supprime l'ancien dossier renommé. Comme ça, la suppression des caches est rapide ! Car supprimer des dizaines de fichiers à chaque changement de données, oui c'est assez lent si le disque est assez utilisé par ailleurs au même moment... Alors que renommer simplement le dossier, j'ai constaté que c'était la solution la plus rapide pour s'en débarrasser sans faire de blocage.
     
  11. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour rick38

    Et si tes fichiers étaient dans des dossiers tmpfs ?

    Merci beaucoup pour ton aide.

    Amicalement.
     
  12. rick38
    rick38 WRInaute passionné
    Inscrit:
    23 Février 2013
    Messages:
    1 062
    J'aime reçus:
    108
    Ah donc en mémoire, donc ce que j'ai dit ne compte pas.
    Eh bien je me moquerais pas mal de l'ordre ou du nombre de caches à supprimer, puisqu'en RAM c'est ultra-rapide, alors il faut bien faire quelques benches et tout tracer en log pour vérifier, mais si c'est pour gagner quelques millisecondes aucun intérêt de faire de la complexité pour des micro-optimisations. J'attends d'abord de rencontrer un problème de lenteur avant de réfléchir à des solutions :)
     
  13. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour rick38

    Merci beaucoup beaucoup pour ton aide. ;)

    Voici ce que je vais faire :

    Mes fichiers temporaires habituels quotidiens en tmpfs,

    Le reste comme tu dis, noms de fichiers : TABLE1(_TABLE2)?_date.txt en tmpfs, etc, suppression si nécessaire, du plus ancien au plus récent.

    Modification : Voir ci-dessous, plus besoin de dates, suppression dynamique des données.

    J'ajoute : 1 timestamp par requête, mis à jour à chaque utilisation cache, et lecture séquentielle des fichiers.

    Suppressions : Je pense faire par cron comme tu dis, mapping fichiers en variables indicées, écriture sur fichier intermédiaire tmpfs autre nom, puis renommer le fichier intermédiaire vers fichier départ. Celà en ne supprimant que les données anciennes.

    Génial, merci pour ton aide.

    Amicalement.
     
  14. spout
    spout WRInaute accro
    Inscrit:
    14 Mai 2003
    Messages:
    8 733
    J'aime reçus:
    233
    Je n'arrive toujours pas à imaginer la Rolls de site que tu aurais si tu passais tout ce temps à autre chose que des broutilles :p
     
    colonies apprécie ceci.
  15. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bon

    Je visualise sur mon ordi les ordres MySQL, qui sont très répétitifs.

    Je vais suivre l'avis de colonies, et grouper ces trucs.

    La fonctionnalité de mon orm maison est presque complète ( pratiquement toutes les instructions MySQL de type Data Manipulation Language ( pas administration ) sont prises en compte ).

    Une petite étape de groupage des instructions répétitives faite, je vérifierai la rectitude des codes produits, et après c'est le cache.

    Merci beaucoup pour votre aide.

    Amicalement.
     
  16. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour

    Est-ce que ceci est valide en MySQL/MariaDB ?

    SELECT COUNT(NUMJO) FROM `COURSES` WHERE `NUMJO` IN (5499, 283, 807, 10955, 253, 3677, 279, 11328) AND `NUMCRS`<'171225' AND `RANG`!='99' GROUP BY `NUMJO`

    Merci beaucoup.

    Amicalement.
     
  17. spout
    spout WRInaute accro
    Inscrit:
    14 Mai 2003
    Messages:
    8 733
    J'aime reçus:
    233
    C'est pas plus simple de demander ça directement à ton client SQL favori ?
     
  18. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Merci Spout

    Cà marche.

    Pardon.

    Amicalement.
     
  19. rollback
    rollback WRInaute occasionnel
    Inscrit:
    5 Novembre 2018
    Messages:
    415
    J'aime reçus:
    42
    SELECT COUNT(NUMJO) FROM `COURSES` WHERE `NUMJO` IN (5499, 283, 807, 10955, 253, 3677, 279, 11328) AND `NUMCRS`<'171225' AND `RANG`!='99' GROUP BY `NUMJO`

    alors en 2 mots, un moteur de bases de données, son rôle c'est de gérer les données. Donc le but c'est bien que ce ce soit lui qui s'emmerde a stocker les données, les trier, les mettre ou il veut, comme il veut et à optimiser son truc.
    Vu de l'utilisateur, en fonction du nombre du volume de données, des accès concurrentiels sur ces mêmes données (parce que quand même le but d'utiliser un moteur de base de données c'est souvent aussi parce que plusieurs personnes vont travailler sur les mêmes données), on a quelques paramètres sur lesquels agir.
    En gros beaucoup d'accès, peu de données qui varient pas. En mémoire, en cache autant que faire se peut.
    Du volume, on oublie la mémoire.. Il faut trouver la juste balance entre optimisation et brouettisations bug parce qu'on on rien compris.

    La requête, ok du sql level 0

    En gros ce qui va optimiser une BD, c'est la manière dont sont découpées les tables, les données.
    C'est impossible de dire si la requête est bonne sans avoir le schéma de la BD. On sent quand même a plein nez une grosse ftat table bien pourrie
    Et les BD relationnelles, elles sont très fortes et très rapides pour faire des jointures entre les tables
    Si on a 400 rows dans une flat table, OSEF la base de donnée, elle sert à rien
     
  20. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Docteur rollback

    Celà pourrait dépendre des index et clés étrangères ( FOREIGN KEY ) entre tables.

    Le pivots des équijointures sont des foreign keys ?

    Merci beaucoup de ton aide; ;)

    Amicalement.
     
  21. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Non pardon

    Je suis un peu fatiqué, couché ce matin à 0h45. ;)

    Amicalement.
     
  22. rollback
    rollback WRInaute occasionnel
    Inscrit:
    5 Novembre 2018
    Messages:
    415
    J'aime reçus:
    42
    ??????? je passe des journées entières à expliquer que l'informatique est simple et que toujours derrière les mots blablabla de toutes les technologies informatiques il y a toujours des notions super simples mais là je comprends rien. Et je ne suis pas docteur, c'est pas assez haut à la fac
     
  23. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour rollback

    Le fait est qu'au mieux les colonnes NUMJO et NUMCRS sont en index multiples, et quand on sait comment MySQL/MariaDB traite les index...

    Code:
    
    MariaDB [turf]> EXPLAIN SELECT COUNT(NUMJO) FROM `COURSES` WHERE `NUMJO` IN (5499, 283, 807, 10955, 253, 3677, 279, 11328) AND `NUMCRS`<'171225' AND `RANG`!='99' GROUP BY `NUMJO`; 
    +------+-------------+---------+-------+------------------------------------+----------+---------+------+-------+------------------------------------+
    | id   | select_type | table   | type  | possible_keys                      | key      | key_len | ref  | rows  | Extra                              |
    +------+-------------+---------+-------+------------------------------------+----------+---------+------+-------+------------------------------------+
    |    1 | SIMPLE      | COURSES | range | IX_NUMCRS_NUMCH,IX_NUMJO,IX_NUMCRS | IX_NUMJO | 8       | NULL | 43653 | Using index condition; Using where |
    +------+-------------+---------+-------+------------------------------------+----------+---------+------+-------+------------------------------------+
    1 row in set (1.004 sec)
    MariaDB [turf]> 
    
    
    Quel SGDBR tu me conseillerais ?

    PostgreSQL ou autre chose ?

    Merci beaucoup de ton aide. ;)

    Amicalement.
     
  24. colonies
    colonies WRInaute occasionnel
    Inscrit:
    10 Septembre 2006
    Messages:
    441
    J'aime reçus:
    36
    Moi je te conseillerais de faire confiance à ta DB. Je te l'ai déjà écrit plus haut : tu ne pourras jamais battre son niveau d'optimisation, et si c'est le cas, c'est que soit la structure de tes tables, soit ta config MySQL est en cause. Ou même les deux.
    Ce que tu essayes de faire est d'un niveau qui te dépasse. Si si, je t'assure. Et c'est pas une offense, tu t'attaques à un truc où pour faire mieux coté PHP que coté DB, il faudrait que tu sois 10x meilleur que les gens qui écrivent les DB. Toute la communauté. Avec des décennies d'expérience.

    Au fait, qu'est-ce qui se passe avec ton système de cache si je change la structure d'une table ?
    Bah c'est foireux, à moins de, pour chaque accès, vérifier la structure des tables de la query, en plus de la parser. Et si c'est bon, faire un accès au FS.
    Dans tous les cas, tu seras plus lent que MariaDB/MySQL.
    Je répète : DANS TOUS LES CAS.
    Laisse tomber.
     
    spout apprécie ceci.
  25. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Pardon

    Pour le 1 ) : Il n'y a plus de cache actif ( par défaut ) à partir de MariaDB 1.5.7.

    Pour le 2) : Mon cache en RAM, et remise à zéro facile dans ce cas ( rare ).

    Amicalement.
     
  26. colonies
    colonies WRInaute occasionnel
    Inscrit:
    10 Septembre 2006
    Messages:
    441
    J'aime reçus:
    36
    Aaaaah, ok. Sauf qu'il n'y a jamais eu de version 1.5.7 de MariaDB, et que ton affirmation est fausse.
    Il y a des caches dans MariaDB. Des tas et des tas de caches.

    Tu peux commencer par regarder ça :
    Code:
    SHOW VARIABLES LIKE '%cache%'
    Et puis ça :
    Code:
    SELECT  ENGINE,
            ROUND(SUM(data_length) /1024/1024, 1) AS "Data MB",
            ROUND(SUM(index_length)/1024/1024, 1) AS "Index MB",
            ROUND(SUM(data_length + index_length)/1024/1024, 1) AS "Total MB",
            COUNT(*) "Num Tables"
    FROM  INFORMATION_SCHEMA.TABLES
    WHERE  table_schema not in ("information_schema", "PERFORMANCE_SCHEMA", "SYS_SCHEMA", "ndbinfo")
    GROUP BY  ENGINE;
     
  27. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour colonies

    Vu sur le site de MariaDB :

    Code:
    
       To see if the cache is enabled, view the query_cache_type server variable. It is enabled by default in MariaDB versions up to 10.1.6, but disabled starting with MariaDB 10.1.7 - if needed enable it by setting query_cache_type to 1.
    
    
    Donc : 10.1.7 et non pas 1.5.7.

    On peut activer le cache.

    Le problème, est qu'un cache généraliste tout azimut est moins performant qu'un cache spécialisé.

    Amicalement.
     
  28. colonies
    colonies WRInaute occasionnel
    Inscrit:
    10 Septembre 2006
    Messages:
    441
    J'aime reçus:
    36
    Mais il y a un paquet d'autres caches dans MariaDB / MySQL. Le cache de queries n'a pas été désactivé par hasard, c'est parce qu'il peut facilement dégrader les perfs.
    https://haydenjames.io/mysql-query-cache-size-performance/

    Si tu fais un cache de toutes les queries d'une page d'accueil qui a largement plus d'accès que de mises à jour, et que tu peux invalider le cache manuellement, ça peut valoir le coup (ou même mettre en cache le HTML généré à partir de ces données). Mais pour des queries individuelles, tu vas avoir le même problème qui fait que ce cache a été désactivé : un overhead trop important.

    Mais bon... j'ai l'impression que quoi qu'on te dise, tu continueras, donc tu verras tout ça à la fin, en faisant des benchs.
     
  29. spout
    spout WRInaute accro
    Inscrit:
    14 Mai 2003
    Messages:
    8 733
    J'aime reçus:
    233
    @colonies "Il n'est pire sourd que celui qui ne veut pas entendre" :)
     
  30. rollback
    rollback WRInaute occasionnel
    Inscrit:
    5 Novembre 2018
    Messages:
    415
    J'aime reçus:
    42
    Je ne vais pas embourber le sujet, je ne suis pas spécialiste de mysql, un peu plus de trucs comme sqlserver ou la crémerie d'en face chez oracle (bien qu'il ont acheté mysql)
    Juste une idée d’optimisation, faire des procédures stockées, déjà ca évite de parser le sql a chaque fois...
    Et les db sont nulles pour parser le sql... A l'inverse elles aiment bien savoir à l'avance ce qu’elles doivent faire pour pondre un résultat qui peut êrte n'a pas changé, et est là dans une certaine zone pour quelques instants encore...
     
  31. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour

    J'ai besoin d'aide.

    J'obtiens ceci comme résultat de :

    SELECT IFNULL(MIN(NUMT),-1) AS TMP_NUMT FROM `TERRAINS` WHERE `NOMT`='Reunion:1:COURSE:1:SIMPLE:TRIO:COUPLES' LIMIT 1 :


    Array
    (
    [TMP_NUMT] => 6765
    )


    Et mon instruction orm de départ est :

    $row = $new_conn->TABLE('TERRAINS')->WHERE(['NOMT', SQLChaine($terrain)])->SELECT($new_conn->RAW('IFNULL(MIN(NUMT), -1) AS TMP_NUMT'))->FIRST();

    L'array ci-dessus ( correcte ) est affichée et rendue par FIRST(), mais il semble que $row soit booléen et non une array.

    Spout, dans quel ordre sont interprétée les fonctions TABLE, WHERE, SELECT, RAW et FIRST ?

    Je croyais que c'était de gauche à droite ?

    Merci beaucoup de ton aide.

    Respectueusement.
     
  32. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Je vous demande pardon

    C'est simple : La fonction de cache rendait true au lieu de la requête cachée.

    Bien amicalement.
     
  33. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Et voilà

    Pour la mise à jour de ma bdd ce soir :

    1705 requêtes SQL ( réelles ou cachées ),

    1219 dans le cache. ( SQL réelles seulement ).

    Donc : 1705 - 1219 = 486 lue sdans le cache.

    Des SELECT instantanés cependant, pour les requêtes rapides je peux ne pas faire de cache, en préfixant avec : CACHE(false)->

    Cà roule.

    Merci beaucoup de votre aide.
     
  34. spout
    spout WRInaute accro
    Inscrit:
    14 Mai 2003
    Messages:
    8 733
    J'aime reçus:
    233
  35. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Merci Spout ;)

    J'aurais besoin de savoir si mon site est accessible en ipv6 ?

    Je ne peux pas rediriger http vers https, car j'ai un certif Letsencrypt, avec renouvellement en http.

    Merci beaucoup.
     
  36. cthierry
    cthierry WRInaute passionné
    Inscrit:
    15 Janvier 2005
    Messages:
    2 187
    J'aime reçus:
    37
    Ortolojf, vu le nombre de messages, questions concernant ton site et surtout tes problèmes à implémenter des fonctionnalités sur ton serveur, il y a bien longtemps que je me serai tourné vers un système de gestion de serveur.

    Pour ma part qui suis une quiche en SSH ( si si le SSH ne m'aime pas :) ), certains du forum pourront en témoigner, je me sers d'une surcouche sur mes serveurs, surcouche qui s'appelle Plesk et qui me permet de gérer efficacement, rapidement et surtout avec compréhension mes serveurs et les sites qui sont dessus. Bon, les puristes te diront que cela rajoute encore une couche intermédiaire à Debian, mais pour ma part cela me permet de ne pas être obligé de me servir de SSH même s’il m'arrive de le faire pour des commandes précises.

    Bref, si tu patauges dans la semoule, si tu ne comprends pas trop comment tout cela fonctionne, sers-toi d'un gestionnaire de serveur comme Plesk ou autre, il y en a plusieurs. Et tu pourras par exemple implémenter Letsencrypt en 10 secondes chrono avec gestion des sous-domaines, prise en charge dans la messagerie, etc. Il en sera de même pour la gestion de tes bases de données, de tes abonnements, de tes droits, bref de toutes les questions que tu as posées jusqu'à aujourd'hui, souvent en n’écoutant pas les recommandations de personnes qualifiées soit dit en passant.
     
    ABCWEB apprécie ceci.
  37. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bon bon

    Je ne tiens pas à activer ma connexion ipv6 Free , par mesure de sécurité.

    Est-ce mon site est accessible en ipv6 ?

    Je te dirais le niveau de complexité de mes programmes PHP, tu frémirais d'horreur. ;)

    Pour l'admin je me débrouille.

    Amicalement.
     
  38. cthierry
    cthierry WRInaute passionné
    Inscrit:
    15 Janvier 2005
    Messages:
    2 187
    J'aime reçus:
    37
    Si c'est du même niveau que ta gestion des ipv6, Letsencrypt, gestion de mysql, gestion de tes abonnements :) il est sûr que je peux en frémir d'horreur. ;)
     
  39. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour Monsieur

    C'est une plaisanterie Belge ?

    Merci beaucoup.
     
  40. rollback
    rollback WRInaute occasionnel
    Inscrit:
    5 Novembre 2018
    Messages:
    415
    J'aime reçus:
    42
    c'est sur plesk c'est bien, un peu payant, les indiens aiment bien Cpanel........ gare aux failles mais il y en a moins que sur un serveur mal géré
     
  41. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bon bon...

    J'ai pratiquement terminé l'alpha du cache.

    L'algorithme est le suivant :

    Ouverture du ficher cache en lecture binaire ( "br" ),
    Lecture séquentielle,
    Fermeture fichier

    Hash requête existe ?
    Oui : rend le cache,
    Non : Lecture Bdd, cache produit,

    Ouverture fichier cache en append ( "a+" ),
    Ecriture avec fwrite.
    Fermeture fichier.
    Rend le cache,

    Je met aussi un timestamp dans l'enreg.

    Une question à propos de fwrite ( un fichier cache par script , fichier binaire ) :
    Est-ce que les écritures ( partition tmpfs ) avec fwrite sur un même fichier sont suffisamment instantanées, pour qu'il n'y ait pas de collisions ?

    Les fichiers seront binaires, vu la longueur des requêtes/enregs.

    Les data sont écrites une ligne ( virtuelle avec délimiteur ), à chaque mise en cache.

    Sinon, comment gérer les accès simultanés en écriture ?

    Des sémaphores rapides en mémoire ?

    Merci.
     
  42. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Rebond ;)

    Une autre question : Qu'est-ce qui est le plus rapide, texte ou binaire ?

    1) Lecture séquentielle,

    2) Ecriture en append.

    Merci beaucoup de vos réponses.

    Amicalement.
     
  43. colonies
    colonies WRInaute occasionnel
    Inscrit:
    10 Septembre 2006
    Messages:
    441
    J'aime reçus:
    36
    Ce qui est le plus rapide, c'est utiliser une base de donnée sans ton cache dont l'approche naïve ne peut que dégrader les perfs.
    Là tu commences tout juste à te poser la question du système de lock, tu as un fichier monolithique donc un verrou unique pour toutes les tables concernées par ton cache, tu charges toutes les données "au cas où elles pourraient servir", bref, tu perds ton temps et celui de ton serveur, alors qu'il suffisait que tu modifies le my.cnf ou que tu saisisses un
    SET GLOBAL query_cache_type = 'ON'
    dans phpMyAdmin pour retrouver un système ultra performant qui gère déjà tout ça de manière efficace et fiable, qui gère les transactions, la corruption de données, les insertions différées, et j'en passe.
     
  44. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour colonies

    J'ai autant de fichiers cache que de scripts.
    Environ une petite dizaine.

    Ce matin j'ai programmé le dégrossissage des fichiers cache, en effaçant les enregistrements plus ancien que 60 minutes. A lancer par cron.

    Je peux aussi utiliser un critère de grosseur de fichier, ou de nombre d'enregistrements.

    Sur mon ordi, le cache semble fonctionner.

    C'est sûr que je ne peux pas savoir à l'avance si le site sera accéléré ou non, mais les caches seront en RAM ( tmpfs ).

    Je teste encore sur l'ordinateur.

    J'ai déjà le cache de la Bdd à à 0.

    Merci beaucoup beaucoup pour ton aide.

    Amicalement.
     
  45. rollback
    rollback WRInaute occasionnel
    Inscrit:
    5 Novembre 2018
    Messages:
    415
    J'aime reçus:
    42
    une sorte de ramasse miette du cache. Je n'ai pas tout suivi, mais pour quoi un visiteur qui viendrait 60 minute plus tard devrait être plus lent sur une recherche ?Tant qu'il y a de la place en mémoire, on cache, ce n'est pas couteux de garder du cache s'il y a de la place de libre
     
  46. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Merci beaucoup.

    Je peux faire varier la constante de délai.

    Pour l'instant j'ai encore à adapter les fonctions agrégats ( mono ou multi colonnes ), qui doivent être triplement indexées par leur noms de colonnes, et valeurs des colonnes et des fonctions.

    C'est un problème purement d'orm, pas de cache.

    Facile à faire. ;)

    Après, je fait un audit du site, puis je teste.

    Merci beaucoup à tous pour votre aide. :)

    Amicalement.
     
  47. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Voili, voilou

    J'ai une question à poser, pour peaufiner mes fonctions d'agrégats à plusieurs colonnes :

    En syntaxe Eloquent version 2, quelle pourrait être la syntaxe d'un group by à deux ou plus colonnes ?

    Ceci, avec ou sans des where_in ?

    Merci beaucoup de vos réponses.

    Respectueusement.
     
  48. spout
    spout WRInaute accro
    Inscrit:
    14 Mai 2003
    Messages:
    8 733
    J'aime reçus:
    233
    La doc est très bien faite.
     
  49. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Merci Spout ;)

    En fait, c'était pour les fonctions agrégats à plusieurs colonnes.

    Celà est interdit par la norme SQL.

    Donc au pire, des group_by sur plusieurs colonnes, donc nécessairement plusieurs fonctions agrégats, donc une fonction select( $conn->raw($sql) )
    , avec $sql contenant les fonctions agrégats.

    Eventuellement avec un group_by($col1, $col2) avant.

    La fonction raw() est entièrement supportée par ma version de Eloquent v2, je vais tester.

    Merci beaucoup de ton aide.

    Amicalement.
     
  50. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Voilà c'est fait

    Le cache MySQL est enfin en place et fonctionnel, sa mise à jour ( pas à zéro ) a lieu une fois/heure suivant
    les timestamp, mais çà n'empêche pas le cache html de fonctionner.

    Mon site était down pendant une semaine.

    Maintenant le site fonctionne.

    Merci de votre aide.

    Amicalment.
     
  51. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Excusez-moi

    J'envisage de porter mon cache mysql maison sur mémoire partagée au lieu de fichiers en mode tmpfs.

    Cette version utilisera la fonction : shmop_open ( int $key , string $flags , int $mode , int $size )

    Mais comment générer une $key unique ?

    Habituellement, on utilise pour celà : ftok ( string $pathname , string $proj )

    Y a-t-il une autre solution que ftok() ?

    Un nombre integer suffisamment aléatoire ?

    Cette version ( j'ai fait l'algorithme hier soir ), utilisera ( par script php en amont ) :

    1) Un index de blocs de n lignes max chacun,
    2) 1 ... p blocs contenant les data.

    1 Index de blocs : Exemple de ligne :

    KEY_BLOC1 ( 64 octets ) | CACHE_HASH_1 ( 64 octets ) | CACHE_HASH_2 | ..etc...

    Séparateur fin de ligne : TOKEN_EOL

    Exemple de blocs :

    CACHE_HASH | TOKEN_CACHE | $timestamp | TOKEN_CACHE | SQL_CACHE | TOKEN_EOL

    C'est du séquentiel indexé.

    Merci beaucoup de vos avis.

    Amicalement.
     
  52. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Pardon

    Est-ce que random_int() pourrait être utilisé pour shmop_open ( int $key , string $flags , int $mode , int $size ) ?

    Code:
    
    $key = random_int (0 , PHP_INT_MAX);
    
    
     
  53. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour

    Pour l'ancienne version de mon cache mysql, je met en log toutes les 20 minutes.

    Le log est là : https://www.pronostics-courses.fr/cache_logs.txt

    NBRE = nbre de caches par fichier.

    AVG, MAX et MIN sont les tailles de chaque enreg/cache.

    J'ai besoin, pour allocater les index de fichiers ( et les blocs ) de savoir leurs tailles maximum.

    Merci beaucoup de votre aide.

    Code:
    
    -------------------------------------------------------------------------------------------------------------------------------------------------
    |                    CACHE                    |    NBRE    |    AVG    |    MAX    |    MIN    |
    -------------------------------------------------------------------------------------------------------------------------------------------------
    | /var/www/html/CACHE/cache_index.txt                                           |    13    |    194    |    535    |    7    |
    | /var/www/html/CACHE/cache_aplusbegalix.txt                                    |    151    |    397    |    5803    |    7    |
    | /var/www/html/CACHE/php/contact/cache_tmp_enreg.txt                           |    1    |    6    |    6    |    6    |
    | /var/www/html/CACHE/php/contact/cache_contact.txt                             |    1    |    6    |    6    |    6    |
    | /var/www/html/CACHE/php/stats/cache_affic_stats.txt                           |    1    |    6    |    6    |    6    |
    | /var/www/html/CACHE/php/stats/cache_tmp_enreg.txt                             |    1    |    6    |    6    |    6    |
    | /var/www/html/CACHE/php/stats/cache_derniers_gagnes.txt                       |    1    |    6    |    6    |    6    |
    | /var/www/html/CACHE/php/stats/cache_new_new_affic_stats.txt                   |    1    |    6    |    6    |    6    |
    | /var/www/html/CACHE/php/courses_actuelles/cache_statistiques_new_courses.txt  |    5    |    710    |    1083    |    7    |
    | /var/www/html/CACHE/php/courses_actuelles/cache_pronostics_new_courses.txt    |    67    |    742    |    6219    |    7    |
    | /var/www/html/CACHE/php/courses_actuelles/cache_new_courses.txt               |    2    |    445    |    882    |    7    |
    | /var/www/html/CACHE/php/courses_actuelles/cache_tmp_enreg.txt                 |    2    |    445    |    882    |    7    |
    | /var/www/html/CACHE/php/courses_nouvelles/cache_pronostics_new_courses.txt    |    16    |    142    |    883    |    7    |
    | /var/www/html/CACHE/php/courses_nouvelles/cache_tmp_enreg.txt                 |    2    |    445    |    882    |    7    |
    | /var/www/html/CACHE/php/courses_nouvelles/cache_new_courses.txt               |    2    |    445    |    882    |    7    |
    | /var/www/html/CACHE/php/courses_nouvelles/cache_statistiques_new_courses.txt  |    3    |    329    |    882    |    7    |
    | /var/www/html/CACHE/php/courses_anciennes/cache_old_historique.txt            |    1    |    6    |    6    |    6    |
    | /var/www/html/CACHE/php/courses_anciennes/cache_statistiques_old_courses.txt  |    1    |    6    |    6    |    6    |
    | /var/www/html/CACHE/php/courses_anciennes/cache_old_courses.txt               |    6    |    222    |    883    |    7    |
    | /var/www/html/CACHE/php/courses_anciennes/cache_tmp_enreg.txt                 |    2    |    445    |    882    |    7    |
    | /var/www/html/CACHE/php/courses_anciennes/cache_action_old_courses.txt        |    1374    |    257    |    9291    |    7    |
    | /var/www/html/CACHE/php/courses_anciennes/cache_pronostics_new_old_courses.txt|    48    |    5074    |    104627    |    7    |
    -------------------------------------------------------------------------------------------------------------------------------------------------
    
    
     
  54. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Rebonjour

    Voilà les paramètres du système de cache MySQL que je vais faire prochainement.
    Ils sont tirés de mes stats.

    Ce sont des nombre d'octets.

    NBRE_DIGIT_MAX = 343 = nbre de digits de PHP_INT_MAX ( Il y a une erreur )
    SIZEOF_CACHE_HASH = 64 = nbre de caractères d'un hash code sha256.

    NBRE_ENREGS_TOTAL = nbre de requêtes cachées différentes.Tiré de mes stats de cache.

    NBRE_ENREGS_BLOC = calculé à partir de NBRE_ENREGS_TOTAL par une fonction adaptant le nbre de blocs et le nbre d'enregs/bloc.

    SIZEOF_AVG_SQL_CACHE = 221 = Taille moyenne d'une requête SQL cachée; tiré de mes stats.

    BLOC_LENGTH_INDEX = 414 Taille d'un bloc ( = ligne ) d'index.
    NBRE_LIGNE_INDEX = 10 Nbre de lignes dans l'index.
    INDEX_LENGTH = 4140 Longueur totale de l'index.
    BLOC_LENGTH_MAX = 644 Longueur moyenne d'un bloc de data.

    Je suis obligé pour l'open de l'index ( ou des blocs ), de prévoir leur taille.

    Merci beaucoup de vos suggestions et avis.

    Respectueusement.


    Code:
    
    cache_index.txt
            NBRE_ENREGS_TOTAL = 10
            NBRE_ENREGS_BLOC = 1
            SIZEOF_AVG_SQL_CACHE = 221
            NBRE_DIGIT_MAX = 343
            SIZEOF_CACHE_HASH = 64
            BLOC_LENGTH_INDEX = 414
            NBRE_LIGNE_INDEX = 10
            INDEX_LENGTH = 4140
            BLOC_LENGTH_MAX = 644
            /**********************************************************/
    cache_aplusbegalix.txt
            NBRE_ENREGS_TOTAL = 151
            NBRE_ENREGS_BLOC = 20
            SIZEOF_AVG_SQL_CACHE = 397
            BLOC_LENGTH_INDEX = 1630
            NBRE_LIGNE_INDEX = 8
            INDEX_LENGTH = 13040
            BLOC_LENGTH_MAX = 8363
            /**********************************************************/
    php/contact/cache_tmp_enreg.txt
            NBRE_ENREGS_TOTAL = 1
            NBRE_ENREGS_BLOC = 1
            SIZEOF_AVG_SQL_CACHE = 6
            BLOC_LENGTH_INDEX = 414
            NBRE_LIGNE_INDEX = 1
            INDEX_LENGTH = 414
            BLOC_LENGTH_MAX = 429
            /**********************************************************/
    php/contact/cache_contact.txt
            NBRE_ENREGS_TOTAL = 1
            NBRE_ENREGS_BLOC = 1
            SIZEOF_AVG_SQL_CACHE = 6
            BLOC_LENGTH_INDEX = 414
            NBRE_LIGNE_INDEX = 1
            INDEX_LENGTH = 414
            BLOC_LENGTH_MAX = 429
            /**********************************************************/
    php/stats/cache_affic_stats.txt
            NBRE_ENREGS_TOTAL = 1
            NBRE_ENREGS_BLOC = 1
            SIZEOF_AVG_SQL_CACHE = 6
            BLOC_LENGTH_INDEX = 414
            NBRE_LIGNE_INDEX = 1
            INDEX_LENGTH = 414
            BLOC_LENGTH_MAX = 429
            /**********************************************************/
    php/stats/cache_tmp_enreg.txt
            NBRE_ENREGS_TOTAL = 1
            NBRE_ENREGS_BLOC = 1
            SIZEOF_AVG_SQL_CACHE = 6
            BLOC_LENGTH_INDEX = 414
            NBRE_LIGNE_INDEX = 1
            INDEX_LENGTH = 414
            BLOC_LENGTH_MAX = 429
            /**********************************************************/
    php/stats/cache_derniers_gagnes.txt
            NBRE_ENREGS_TOTAL = 282
            NBRE_ENREGS_BLOC = 20
            SIZEOF_AVG_SQL_CACHE = 371
            BLOC_LENGTH_INDEX = 1630
            NBRE_LIGNE_INDEX = 15
            INDEX_LENGTH = 24450
            BLOC_LENGTH_MAX = 7843
            /**********************************************************/
    php/stats/cache_new_new_affic_stats.txt
            NBRE_ENREGS_TOTAL = 1
            NBRE_ENREGS_BLOC = 1
            SIZEOF_AVG_SQL_CACHE = 6
            BLOC_LENGTH_INDEX = 414
            NBRE_LIGNE_INDEX = 1
            INDEX_LENGTH = 414
            BLOC_LENGTH_MAX = 429
            /**********************************************************/
    php/courses_actuelles/cache_statistiques_new_courses.txt
            NBRE_ENREGS_TOTAL = 10
            NBRE_ENREGS_BLOC = 1
            SIZEOF_AVG_SQL_CACHE = 939
            BLOC_LENGTH_INDEX = 414
            NBRE_LIGNE_INDEX = 10
            INDEX_LENGTH = 4140
            BLOC_LENGTH_MAX = 1362
            /**********************************************************/
    php/courses_actuelles/cache_pronostics_new_courses.txt
            NBRE_ENREGS_TOTAL = 33
            NBRE_ENREGS_BLOC = 20
            SIZEOF_AVG_SQL_CACHE = 523
            BLOC_LENGTH_INDEX = 1630
            NBRE_LIGNE_INDEX = 2
            INDEX_LENGTH = 3260
            BLOC_LENGTH_MAX = 10883
            /**********************************************************/
    php/courses_actuelles/cache_new_courses.txt
            NBRE_ENREGS_TOTAL = 2
            NBRE_ENREGS_BLOC = 1
            SIZEOF_AVG_SQL_CACHE = 445
            BLOC_LENGTH_INDEX = 414
            NBRE_LIGNE_INDEX = 2
            INDEX_LENGTH = 828
            BLOC_LENGTH_MAX = 868
            /**********************************************************/
    php/courses_actuelles/cache_tmp_enreg.txt
            NBRE_ENREGS_TOTAL = 2
            NBRE_ENREGS_BLOC = 1
            SIZEOF_AVG_SQL_CACHE = 445
            BLOC_LENGTH_INDEX = 414
            NBRE_LIGNE_INDEX = 2
            INDEX_LENGTH = 828
            BLOC_LENGTH_MAX = 868
            /**********************************************************/
    php/courses_nouvelles/cache_pronostics_new_courses.txt
            NBRE_ENREGS_TOTAL = 24
            NBRE_ENREGS_BLOC = 20
            SIZEOF_AVG_SQL_CACHE = 128
            BLOC_LENGTH_INDEX = 1630
            NBRE_LIGNE_INDEX = 2
            INDEX_LENGTH = 3260
            BLOC_LENGTH_MAX = 2983
            /**********************************************************/
    php/courses_nouvelles/cache_tmp_enreg.txt
            NBRE_ENREGS_TOTAL = 2
            NBRE_ENREGS_BLOC = 1
            SIZEOF_AVG_SQL_CACHE = 445
            BLOC_LENGTH_INDEX = 414
            NBRE_LIGNE_INDEX = 2
            INDEX_LENGTH = 828
            BLOC_LENGTH_MAX = 868
            /**********************************************************/
    php/courses_nouvelles/cache_new_courses.txt
            NBRE_ENREGS_TOTAL = 2
            NBRE_ENREGS_BLOC = 1
            SIZEOF_AVG_SQL_CACHE = 445
            BLOC_LENGTH_INDEX = 414
            NBRE_LIGNE_INDEX = 2
            INDEX_LENGTH = 828
            BLOC_LENGTH_MAX = 868
            /**********************************************************/
    php/courses_nouvelles/cache_statistiques_new_courses.txt
            NBRE_ENREGS_TOTAL = 4
            NBRE_ENREGS_BLOC = 1
            SIZEOF_AVG_SQL_CACHE = 272
            BLOC_LENGTH_INDEX = 414
            NBRE_LIGNE_INDEX = 4
            INDEX_LENGTH = 1656
            BLOC_LENGTH_MAX = 695
            /**********************************************************/
    php/courses_anciennes/cache_old_historique.txt
            NBRE_ENREGS_TOTAL = 1
            NBRE_ENREGS_BLOC = 1
            SIZEOF_AVG_SQL_CACHE = 6
            BLOC_LENGTH_INDEX = 414
            NBRE_LIGNE_INDEX = 1
            INDEX_LENGTH = 414
            BLOC_LENGTH_MAX = 429
            /**********************************************************/
    php/courses_anciennes/cache_statistiques_old_courses.txt
            NBRE_ENREGS_TOTAL = 1
            NBRE_ENREGS_BLOC = 1
            SIZEOF_AVG_SQL_CACHE = 6
            BLOC_LENGTH_INDEX = 414
            NBRE_LIGNE_INDEX = 1
            INDEX_LENGTH = 414
            BLOC_LENGTH_MAX = 429
            /**********************************************************/
    php/courses_anciennes/cache_old_courses.txt
            NBRE_ENREGS_TOTAL = 5
            NBRE_ENREGS_BLOC = 1
            SIZEOF_AVG_SQL_CACHE = 90
            BLOC_LENGTH_INDEX = 414
            NBRE_LIGNE_INDEX = 5
            INDEX_LENGTH = 2070
            BLOC_LENGTH_MAX = 513
            /**********************************************************/
    php/courses_anciennes/cache_tmp_enreg.txt
            NBRE_ENREGS_TOTAL = 1
            NBRE_ENREGS_BLOC = 1
            SIZEOF_AVG_SQL_CACHE = 6
            BLOC_LENGTH_INDEX = 414
            NBRE_LIGNE_INDEX = 1
            INDEX_LENGTH = 414
            BLOC_LENGTH_MAX = 429
            /**********************************************************/
    php/courses_anciennes/cache_action_old_courses.txt
            NBRE_ENREGS_TOTAL = 1311
            NBRE_ENREGS_BLOC = 40
            SIZEOF_AVG_SQL_CACHE = 256
            BLOC_LENGTH_INDEX = 2910
            NBRE_LIGNE_INDEX = 33
            INDEX_LENGTH = 96030
            BLOC_LENGTH_MAX = 10663
            /**********************************************************/
    php/courses_anciennes/cache_pronostics_new_old_courses.txt
            NBRE_ENREGS_TOTAL = 14
            NBRE_ENREGS_BLOC = 1
            SIZEOF_AVG_SQL_CACHE = 9062
            BLOC_LENGTH_INDEX = 414
            NBRE_LIGNE_INDEX = 14
            INDEX_LENGTH = 5796
            BLOC_LENGTH_MAX = 9485
            /**********************************************************/
    
    
     
    #54 ortolojf, 2 Juin 2019
    Dernière édition: 2 Juin 2019
  55. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour

    Besoin d'une info php sur la fonction :

    shmop_open ( int $key , string $flags , int $mode , int $size )

    Si $flags = "a" ( lecture seule ), deux questions :

    - Si le shm n'existe pas la fonction rend false ?

    - Le $mode (peut/doit)-il être à 0 comme le dit le PHP Manual ?

    Ajouté :

    La valeur $size ( taille allocatée du shm ), peut-elle être augmentée par un shmop_open( int $key, "w", $mode, $size) ?

    Merci beaucoup.

    Amicalement.
     
    #55 ortolojf, 9 Juin 2019
    Dernière édition: 9 Juin 2019
  56. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour

    J'ai pratiquement mis au point une version alpha sans régulation automatique des tailles des allocations des blocs et index.

    Je bute sur le problème de la taille trop élevée des caches des requêtes MySQL.

    Ces caches sont sérialisées.

    Sous PHP, y a-t-il des fonctions de compression / décompression pour chaînes de caractères ?

    Merci.

    Respectueusement.
     
  57. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour Spout ;)

    Qu'est-ce qui est mieux :

    gzdeflate() ou gzcompress()

    et

    gzinflate() ou gzcompress()

    Merci beaucoup. ;)

    Amicalement.
     
  58. spout
    spout WRInaute accro
    Inscrit:
    14 Mai 2003
    Messages:
    8 733
    J'aime reçus:
    233
    No idea, il faut faire des benchs.
     
  59. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour spout

    Comment faire une écriture en append dans un SHM déjà partiellement rempli ?

    Ceci, sans avoir à garder trace des tailles des remplissages précédents ?

    Le flag "w" de shmop_open() semble convenir, mais comment faire un append ?

    Merci beaucoup.

    Amicalement.
     
  60. spout
    spout WRInaute accro
    Inscrit:
    14 Mai 2003
    Messages:
    8 733
    J'aime reçus:
    233
    Il n'y a pas d'append, alors read + write.
     
  61. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour spout

    J'ai une petite librairie de shared memory avec shmop_open() etc... et j'aimerais synchroniser les processus avec des sémaphores.

    Y a-t-il des inconvénients à utiliser sem_get() et shmop_open() en même temps avec la même key ?

    Sinon, j'essaierai de générer les clés pour sem_get() de manière bijective.

    Merci beaucoup spout. ;)

    Amicalement.
     
  62. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour

    A partir d'une classe lecture/écriture shmop sur le PHP Manual, j'ai fait ceci ci-dessous :

    Celà présente l'intérêt d'allocater automatiquement la mémoire quand la taille des blocs augmente.

    Et puis la fonction append().

    Comment abstractiser plus l'objet $this->shmId ( ou $this->shmReadId pour les lectures ) ?

    De manière à ce qu'il n'y ait plus besoin de séparer shmId et shmReadId ?

    Merci beaucoup de votre aide.

    Amicalement.


    PHP:


    <?php
    ########################
    # shmop.class.php
    ########################
    class SHMOP
    {
            const 
    MAXINT 65536 65536 1;
        private 
    $shmId        null;
        private 
    $shmReadId    null;
        public 
    $shmKEY        null;
        public 
    $shmKey        null;
        private 
    $shmMode    null;
        private 
    $shmFlags    null;
        private 
    $shmHeaderSize    null;
        private 
    $shmHeaderOffset    null;
        private 
    $shmBlockSize        null;
        private 
    $shmMaxBlockSize    null;
        private 
    $shmLimitBlockSize    null;
        
    /**
        * C'est un singleton
        * par clés $this->shmKey.
        **/
        
    protected static $instance// Instance de la classe.
        
    protected function __clone() { } // Méthode de clonage en privé.
        
    public static function getInstance($key)
        {
            
    /**   
            * Si on n'a pas 
            * encore instancié 
            * notre classe
            * pour cette $this->shmKey.
            **/
            
    if (!isset(self::$instance[$key])) 
            {
                
    self::$instance[$key] = new  self($key); // On s'instancie nous-mêmes. :)
            
    }
            return 
    self::$instance[$key];
        }
        protected function 
    __construct(int $key)
        {
            
    $this->shmKey $key;
            
    $this->shmMode 0;
            
    $this->shmFlags "a";
            
    $size 2048;
            
    $this->shmHeaderSize strlen($size);
            
    $PHP_MAX = (string)self::MAXINT;
            
    $this->shmHeaderOffset strlen($PHP_MAX) + 1;
            
    $this->shmMaxBlockSize $size;
            
    $this->shmBlockSize $size $this->shmHeaderOffset 1;
            
    /**
            * Surplus
            * pour dépassements
            * peu fréquents.
            **/
            
    $this->shmLimitBlockSize 4096 * (ceil(1.5 $this->shmBlockSize 4096.0));
            return 
    $this;
        }
        public function 
    update_size(int $size)
        {
            if((empty(
    $this->shmKey))||
                (empty(
    $this->shmId)))
            {
                return 
    false;
            }
            @
    shmop_close($this->shmId);
            
    /**
            * Le SHM
            * doit exister.
            **/
            
    $shm = @shmop_open($this->shmKey"a"00);
            if(
    $shm === false)
            {
                return 
    false;
            }
            
    // Get Header
            
    $enreg = @shmop_read($shm1$this->shmHeaderOffset);
            
    $pos strpos($enreg"\0");
            if(
    $pos !== false)
            {
                
    $dataSize = (int)substr($enreg0$pos);
            }
            else
            {
                throw new 
    Exception("Erreur lecture avant update taille enreg.");
                return 
    false;
            }
            
    $len shmop_size($shm) - $this->shmHeaderOffset;
            
    /**
            * Précédent
            * $enreg
            * avant update.
            **/
            
    unset($enreg);
    //        $enreg = @shmop_read($shm, $this->shmHeaderOffset, $dataSize);
            
    $enreg = @shmop_read($shm$this->shmHeaderOffset$len);
            unset(
    $pos);
            
    $pos strpos($enreg"\0");
            if(
    $pos !== false)
            {
                
    $preced_enreg = (int)substr($enreg0$pos);
            }
            else
            {
                throw new 
    Exception("Erreur lecture avant update taille enreg.");
                return 
    false;
            }
            
    $preced_enreg .= "\0";
            @
    shmop_delete($shm);
            
    $this->ALLOCATE($size);
            
    $shm = @shmop_open($this->shmKey"n"$this->shmMode$this->shmLimitBlockSize);
            if(
    $shm === false)
            {
                throw new 
    Exception("Erreur création update SHM.");
                return 
    false;
            }
            
    // pack very slow use kludge
            
    $dataSize strlen($preced_enreg);
            
    $dataSize .= "\0";
            
    // Write Header
            
    @shmop_write($shm$dataSize1);
            
    $enreg .= "\0";
            if(@
    shmop_write($shm$preced_enreg$this->shmHeaderOffset) === false)
            {
                throw new 
    Exception("Erreur écriture update SHM.");
                return 
    false;
            }
            
    $this->shmId $shm;
            unset(
    $shm);
            return 
    true;
        }
        function 
    EXIST()
        {
            
    /**
            * Tester
            *
            * $this->shmId
            * !== false
            * et* !== null
            **/
            /**
            * SHM existe.
            **/
            
    $shm = @shmop_open($this->shmKey"a"00);
            if(
    $shm !== false)
            {
                
    $this->shmReadId $shm;
                return 
    $this;
            }
            return 
    false;
        }
        function 
    ALLOCATE(int $size)
        {
            if((
    $this->shmHeaderSize <= strlen($size))||
            (
    $this->shmMaxBlockSize <= $size)||
            (
    $this->shmBlockSize <= ($size $this->shmHeaderOffset 1))||
            (
    $this->shmLimitBlockSize <= (4096 * (ceil(1.5 $this->shmBlockSize 4096.0)))))
            {
                
    $this->shmHeaderSize strlen($size);
                
    $this->shmMaxBlockSize $size;
                
    $this->shmBlockSize $size $this->shmHeaderOffset 1;
                
    /**
                * Surplus
                * pour dépassements
                * peu fréquents.
                **/
                
    $this->shmLimitBlockSize 4096 * (ceil(1.5 $this->shmBlockSize 4096.0));
            }
            return 
    true;
        }
        function 
    OPEN(string $flagsint $modeint $size)
        {
            if(
    in_array($flags, array("a""w"), true))
            {
                
    $shm = @shmop_open($this->shmKey$flags00);
                if(
    $shm === false)
                {
                    return 
    false;
                }
                switch (
    $flags) {
                case 
    "a" :
                    
    $this->shmReadId $shm;
                    break;
                case
    "w" :
                    
    $this->shmId $shm;
                    break;
                default :
                    break;
                }
                
    /**
                * Il faudrait
                * abstractiser
                * plus le maniement
                * des objets.
                **/
                
    return $this;
            }
            switch (
    $flags) {
            
    /**
            * Pour créer
            * un nouveau bloc
            * même s'il existe.
            **/
            
    case "n" :
                
    $this->shmMode $mode;
                
    $this->shmFlags $flags;
                
    /**
                * Le SHM
                * ne doit
                * pas exister.
                **/
                
    $shm = @shmop_open($this->shmKey"a"00);
                if(
    $shm !== false)
                {
                    @
    shmop_delete($shm);
                }
                unset(
    $shm);
                
    $this->ALLOCATE($size);
                
    /**
                * Delete 
                * instantané ?
                **/
                
    $shm = @shmop_open($this->shmKey$this->shmFlags$this->shmMode$this->shmLimitBlockSize);
                if(
    $shm === false)
                {
                    unset(
    $shm);
                    throw new 
    Exception("Erreur création SHM. en mode : " $this->shmFlags);
                    return 
    false;
                }
                
    $this->shmId $shm;
                unset(
    $shm);
                
    /**
                * SHM créé
                **/
                // release spinlock
                
    shmop_write($this->shmId"\0"0);
                return 
    $this;
                break;
            
    /**
            * Pour créer
            * un bloc
            * s'il n'existe pas,
            * ou l'ouvrir
            * en lecture/écriture
            * s'il existe.
            **/
            
    case "c" :
                
    /**
                * SHM existe,
                * ouvert
                * en lecture/écriture.
                **/
                
    $shm = @shmop_open($this->shmKey"a"00);
                if(
    $shm !== false)
                {
                    @
    shmop_close($shm);
                    unset(
    $shm);
                    
    $shm = @shmop_open($this->shmKey"w"00);
                    if(
    $shm === false)
                    {
                        throw new 
    Exception("Erreur ouverture/création SHM. en mode : " $flags);
                        return 
    false;
                    }
           
                    
    $this->shmId $shm;
                    
    /**
                    * Il faudrait
                    * abstractiser
                    * plus le maniement
                    * des objets.
                    **/
                    
    return $this;
                }
                
    /**
                * SHM n'existe pas,
                * il est créé.
                **/
                
    else
                {
                    unset(
    $shm);
                    
    $this->shmMode $mode;
                    
    $this->shmFlags $flags;
                    
    $this->ALLOCATE($size);
                    
    /**
                    * Faut-il
                    * un $this->shmFlags = "n" ?
                    **/
                    
    $shm = @shmop_open($this->shmKey$this->shmFlags$this->shmMode$this->shmLimitBlockSize);
                    if(
    $shm === false)
                    {
                        throw new 
    Exception("Erreur création SHM. en mode : " $this->shmFlags);
                        return 
    false;
                    }
                    
    $this->shmId $shm;
                    unset(
    $shm);
                    
    // release spinlock
                    
    shmop_write($this->shmId"\0"0);
                    return 
    $this;
                }
                break;
            default :
                break;
            }
            return 
    false;
        }
        function 
    __destruct()
        {
            
    self::$instance[$this->shmKey] = null;
            @
    shmop_close($this->shmId);
            return 
    true;
        }
        public function 
    read()
        {
            
    // Check SpinLock
            
    if(@shmop_read($this->shmReadId01) !== "\0")
            {
                return 
    false;
            }
            
    //
            // Get Header
            
    $enreg shmop_read($this->shmReadId1$this->shmHeaderOffset);
            
    $pos strpos($enreg"\0");
            if(
    $pos !== false)
            {
                
    $dataSize = (int)substr($enreg0$pos);
            }
            else
            {
                throw new 
    Exception("Erreur lecture taille enreg.");
                return 
    false;
            }
            
    $len shmop_size($this->shmReadId) - $this->shmHeaderOffset;
            
    $data = @shmop_read($this->shmReadId$this->shmHeaderOffset$len);
            
    $pos strpos($data"\0");
            if(
    $pos !== false)
            {
                
    $data = (int)substr($data0$pos);
            }
            else
            {
                throw new 
    Exception("Erreur lecture avant update taille enreg.");
                return 
    false;
            }
            return 
    $data;
        }
        
    /**
        * Nombre d'octets
        * allocatés
        * pour la $data.
        **/
        
    public function ALLOCATED_SIZE()
        {
            
    $size $this->shmLimitBlockSize $this->shmHeaderOffset -1;
            return 
    $size;
        }
        public function 
    append(string $data)
        {
            
    // Check SpinLock
            
    if(@shmop_read($this->shmId01) !== "\0")
            {
                return 
    false;
            }
            
    // Write spinlock
            
    @shmop_write($this->shmId"\1"0);
            
    $dataSize strlen($data);
            if(
    $dataSize 1)
            {
                
    // release spinlock
                
    @shmop_write($this->shmId"\0"0);
                throw new 
    Exception('dataSize < 1');
            }
            
    //
            // Get Header
            
    $enreg shmop_read($this->shmId1$this->shmHeaderOffset);
            
    $pos strpos($enreg"\0");
            if(
    $pos !== false)
            {
                
    $dataSize = (int)substr($enreg0$pos);
            }
            else
            {
                throw new 
    Exception("Erreur lecture taille enreg.");
                return 
    false;
            }
            
    $len shmop_size($this->shmId) - $this->shmHeaderOffset;
            
    /**
            * Précédent
            * $enreg
            * avant update.
            **/
            
    unset($enreg);
    //        $enreg = @shmop_read($this->shmId, $this->shmHeaderOffset, $dataSize);
            
    $enreg = @shmop_read($this->shmId$this->shmHeaderOffset$len);
            unset(
    $pos);
            
    $pos strpos($enreg"\0");
            if(
    $pos !== false)
            {
                
    $preced_enreg = (int)substr($enreg0$pos);
            }
            else
            {
                throw new 
    Exception("Erreur lecture avant update taille enreg.");
                return 
    false;
            }
            
    /**
            * Append.
            **/
            
    $preced_enreg .= $data;
            
    $preced_enreg .= "\0";
            
    $dataSize strlen($preced_enreg);
            
    /**
            * Adaptation
            * de la taille
            * du SHM.
            **/
            
    if($this->ALLOCATED_SIZE() < $dataSize)
            {
                if(
    $this->update_size($dataSize) !== true)
                {
                    
    // release spinlock
                    
    @shmop_write($this->shmId"\0"0);
                    return 
    false;
                }
            }
               
            
    // pack very slow use kludge
            
    $dataSize .= "\0";
            
    /**
            * $this->shmId
            * a probablement changé.
            **/
            // Write Header
            
    @shmop_write($this->shmId$dataSize1);
            
    // Write Data
            
    @shmop_write($this->shmId$preced_enreg$this->shmHeaderOffset);
            
    // release spinlock
            
    @shmop_write($this->shmId"\0"0);
            return 
    $this;
        }
        public function 
    write(string $data)
        {
            
    // Check SpinLock
            
    if(@shmop_read($this->shmId01) !== "\0")
            {
                return 
    false;
            }
            
    // Write spinlock
            
    @shmop_write($this->shmId"\1"0);
            
    $data .= "\0";
            
    $dataSize strlen($data);
            if(
    $dataSize 1)
            {
                
    // release spinlock
                
    @shmop_write($this->shmId"\0"0);
                throw new 
    Exception('dataSize < 1');
            }
            
    /**
            * Adaptation
            * de la taille
            * du SHM.
            **/
            
    if($this->ALLOCATED_SIZE() < $dataSize)
            {
                if(
    $this->update_size($dataSize) !== true)
                {
                    
    // release spinlock
                    
    @shmop_write($this->shmId"\0"0);
                    return 
    false;
                }
            }
               
            
    // pack very slow use kludge
            
    $dataSize .= "\0";
            
    /**
            * $this->shmId
            * a probablement changé.
            **/
            // Write Header
            
    @shmop_write($this->shmId$dataSize1);
            
    // Write Data
            
    @shmop_write($this->shmId$data$this->shmHeaderOffset);
            
    // release spinlock
            
    @shmop_write($this->shmId"\0"0);
            return 
    $this;
        }
        public function 
    eof()
        {
            return (@
    shmop_read($this->shmId01) === "\2") ? true false;
        }
        public function 
    sendeof()
        {
            
    // Check SpinLock
            
    if(@shmop_read($this->shmId01) !== "\0")
            {
                return 
    false;
            }
            @
    shmop_write($this->shmId"\2"0);
            return 
    true;
        }
        public function 
    canWrite()
        {
            
    // Check SpinLock
            
    return (@shmop_read($this->shmId01) === "\0") ? true false;
        }
        public function 
    close($flags)
        {
            switch (
    $flags) {
            case 
    "a" :
                return @
    shmop_close($this->shmReadId);
           
                break;
            case 
    "c" :
            case 
    "w" :
            case 
    "n" :
                return @
    shmop_close($this->shmId);
           
                break;
            default :
                break;
            }
            return 
    false;
        }
        public function 
    delete($flags)
        {
            switch (
    $flags) {
            case 
    "a" :
                
    $del = @shmop_delete($this->shmId);
                break;
            case 
    "c" :
            case 
    "w" :
            case 
    "n" :
                
    $del = @shmop_delete($this->shmId);
                break;
            default :
                break;
            }
            if(
    $del === false)
            {
                return 
    false;
            }
            return 
    $this;
        }
        public function 
    SHMOP_WRITE(string $data)
        {
            while(
    true)
            {
                if(
    $this->write($data) !== false)
                {
                    break;
                }
            }
            return 
    true;
        }
        public function 
    SHMOP_READ()
        {
            
    /**
            * Mettre
            * un délai.
            **/
            
    while(true)
            {
                if((
    $data $this->read()) !== false)
                {
                    return 
    $data;
                }
            }
        }
        public function 
    SHMOP_DELETE($flags)
        {
            return 
    $this->delete($flags);
        }
        public function 
    SHMOP_CLOSE($flags)
        {
            return 
    $this->close($flags);
        }
        public function 
    RELEASE_LOCK()
        {
            
    // release spinlock
            // for writing.
            
    @shmop_write($this->shmId"\0"0);
            return 
    true;
        }
        public function 
    SET_LOCK()
        {
            
    // Write spinlock
            // for reading.
            
    @shmop_write($this->shmId"\1"0);
            return 
    true;
        }
    }
    ?>

     
  63. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Je vous demande pardon ;)

    J'ai la réponse à la question.

    Pas besoin de séparer $this->shmReadId de $this->shmId , c'est l'ident du shm.

    Celà parce que deux open en lecture ou en écriture sur le même shm
    sont séquentiels avec les close.

    Dans ma classe SHMOP, je met le $this->hmId à null dans close().

    Pour l'instant, je n'arrive pas à lire des requêtes SQL enregistrées dans des shm.

    Elles ne sont pas reconnues par leur sql_cash

    Je vais tracer.

    Amicalement.
     
  64. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Excusez-moi

    J'ai une question à poser.

    Est-ce que la fonction serialize() peut produire en sortie des octets "\0" ( null ) ?

    J'ai une très bonne version même pas alpha de ma librairie de cache MySQL avec des shared memory ( fonctions shmop_ ), mais c'est un problème théorique et pratique, enregistrement/lecture des données.

    Merci beaucoup.

    Amicalement.
     
  65. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Rebonjour

    Comment faites-vous pour allocater de manière dynamique les tailles des shmop_open() ?

    Est-ce que c'est possible de réécrire sur le même shm ( même clé ) en faisant un shmop_remove() puis shmop_open() ?

    C'est- à-dire : Un shmop_remove() a-t-il un effet immédiat ?

    Merci beaucoup de votre aide.

    Respectueusement.
     
  66. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour

    J'ai fait une classe sémaphore normale et une classe singleton/key d'enregistrement/lecture en shared memory ( fonctions shmop_*() )

    Cette approche est-elle correcte en POO PHP ?

    C'est pour ma librairie de cache MySQL qui est déjà valide ( précédente version fichiers plats en partition tmpfs ).

    Merci beaucoup de vos avis et suggestions.

    Amicalement.


    PHP:

    <?php
    #########################
    #     SEM.php        #
    #########################
    class SEM
    {
        private 
    $semKey        null;        // Clé de SEM.
        
    private $semId        null;        // Id de SEM.
        
    private $semIsLocked    null;        // IsLocked de SEM.
        
    protected function __construct(int $key)
        {
            
    $this->semKey crc32($key);
            return 
    $this;
        }
        protected function 
    LOCK()
        {
            while(
    true)
            {
                if((
    $this->semId sem_get ($this->semKey06661)) !== false)
                {
                    break;
                }
            }
            if(
    sem_acquire($this->semIdfalse) === false)
            {
                return 
    false;
            }
            
    $this->semIsLocked true;
            return 
    true;
        }
        protected function 
    UNLOCK()
        {
            if(
    is_resource($this->semId))
            {
                
    sem_release($this->semId);
            }
            
    $this->semIsLocked false;
            return 
    true;
        }
        protected function 
    IS_LOCKED()
        {
            return 
    $this->semIsLocked;
        }
    }
    ?>

    <?php

    require(__DIR__ '/SEM.php');
    #########################
    #     SHMOP.php    #
    #########################
    class SHMOP extends SEM
    {
        private 
    $shmId        null;        // Id de SHM.
        
    public $shmKey        null;        // Clé de SHM.
        /**
        * C'est un singleton
        * par clés $this->shmKey.
        **/
        
    protected static $instance = array(); // Instance de la classe.
        
    protected function __clone() { } // Méthode de clonage en privé.
        
    protected static function getInstance($key)
        {
            
    /**   
            * Si on n'a pas 
            * encore instancié 
            * notre classe
            * pour cette $this->shmKey.
            **/
            
    if (!isset(self::$instance[$key])) 
            {
                
    self::$instance[$key] = new  self($key); // On s'instancie nous-mêmes. :)
            
    }
            return 
    self::$instance[$key];
        }
        protected function 
    __construct(int $key)
        {
            
    $this->shmKey $key;
            
    parent::__construct($this->shmKey);
            return 
    $this;
        }
        
    /**
        * Format type
        * string conpressée
        * après linearisation
        * en amont.
        **/
        
    private function SHMOP_DEFLATE($value)
        {
            
    /**
            * VALUE => SERIALIZE => COMPRESS => BASE64_ENCODE => STR
            **/
            
    $str base64_encode(gzcompress(serialize($value)));
            
    /**
            * On ajoute un "\0".
            **/
            
    return $this->str_to_nts($str); 
        }
        
    /**
        * Format type
        * string déconpressée
        * destiné à
        * être délinéarisé.
        **/
        
    private function SHMOP_INFLATE($value)
        {
            
    /**
            * On enlève le "\0".
            **/
            
    $str $this->str_from_mem($value);
            
    /*
            * STR => BASE64_DECODE => UNCOMPRESS => UNSERIALIZE.
            */
            
    return unserialize(gzuncompress(base64_decode($str)));
        }
        private function 
    str_from_mem(&$value) {
            
    $i strpos($value"\0");
            if (
    $i === false) {
                return 
    $value;
            }
            
    $result =  substr($value0$i);
            return 
    $result;
        }
        private function 
    str_to_nts($value) {
            return 
    "$value\0";
        }
        function 
    EXIST()
        {
            
    /**
            * SHM existe.
            **/
            
    $shm = @shmop_open($this->shmKey"a"00);
            if(
    $shm !== false)
            {
                
    shmop_close($shm);
                return 
    true;
            }
            return 
    false;
        }
        public function 
    perso_remove()
        {
            
    $this->LOCK();
            
    $shm = @shmop_open($this->shmKey"a"00);
            if(
    $shm === false)
            {
                return 
    false;
            }
            
    shmop_delete($shm);
            
    shmop_close($shm);
            
    $this->UNLOCK();
            return 
    $this;
        }
        public function 
    perso_read()
        {
            
    $this->LOCK();
            
    $shm = @shmop_open($this->shmKey"a"00);
            if(
    $shm === false)
            {
                
    $this->UNLOCK();
                return 
    false;
            }
            
    $length shmop_size ($shm);
            
    $value shmop_read ($shm0$length);
            
    shmop_close($shm);
            
    $this->UNLOCK();
            
    $data $this->SHMOP_INFLATE($value);
            return 
    $data;
        }
        public function 
    perso_write(string $value)
        {
            
    $this->LOCK();
            
    $data $this->SHMOP_DEFLATE($value);
            
    $value_length strlen ($data);
            if((
    $shm = @shmop_open($this->shmKey"a"00)) !== false)
            {
                
    shmop_delete($shm);
                
    shmop_close($shm);
                   
                
    $shm false;
            }
            
    $shm = @shmop_open($this->shmKey"n"0644$value_length);
            if (
    $shm === false)
            {
                
    $this->UNLOCK();
                return 
    false;
            }
            
    // Write Data
            
    shmop_write($shm$data0);
            
    // Libération du segment de mémoire
            
    shmop_close($shm);
            
    $this->UNLOCK();
            return 
    $this;
        }
        public function 
    REMOVE()
        {
            while(
    true)
            {
                if(
    $this->perso_remove() !== false)
                {
                    break;
                }
            }
            return 
    $this;
        }
        public function 
    READ()
        {
            while(
    true)
            {
                if((
    $data $this->perso_read()) !== false)
                {
                    break;
                }
            }
            return 
    $data;
        }
        public function 
    WRITE(string $value)
        {
            while(
    true)
            {
                if(
    $this->perso_write($value) !== false)
                {
                    break;
                }
            }
            return 
    $this;
        }
    }
    ?>

     
  67. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour

    Voici le type d'indexation vaguement séquentiel indexé que j'ai choisi pour l'allocation de mes shared memories :

    CACHE_HASH = hash('sha256', $SQL);
    KEY_BLOC = clé SMHOP du bloc
    SQL_CACHE = le résultat de la requête $SQL, après sérialisation,
    $timestamp = time().

    TOKEN_CACHE = séparateur de champ,
    SEPA = séparateur de champ,
    TOKEN_EOL = séparateur de ligne.

    Mon problème :

    Jusqu'à présent, il y avait un index par script php utilisant la librairie de cache MySQL.

    Je ne m'étais pas aperçu, que les SQL_CACHE d'autres scripts n'étaient pas accessibles.

    Mais, comment indexer en séquentiel indexé, un seul index englobant tous les index, à moins de rajouter un niveau d'indirection dans les recherches , ( il y en a déjà deux ) ?

    Et si oui, comment ?

    Pour chercher le SQL_CACHE d'un CASH_HASH, on le cherche le KEY_BLOC dans l'index, puis on lit le bloc.

    Merci beaucoup beaucoup de votre aide.


    Code:
    
    INDEX
    *****
    // KEY_BLOC_1 | SEPA | CACHE_HASH_1_1 | SEPA | CACHE_HASH_1_2 | SEPA | CACHE_HASH_1_3 | SEPA | ... | TOKEN_EOL
    BLOC
    ****
    // CACHE_HASH | TOKEN_CACHE | $timestamp | TOKEN_CACHE  | SQL_CACHE | TOKEN_CACHE | ...  | TOKEN_EOL
    
    [code]
     
  68. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour

    Il me semble avoir une autre solution pour l'indexation de mes blocs.

    Avec un hashing search :

    PHP:

    /**
     * Fonction de hashing :
     */
    function hash(string $key)
    {
       
    $M // un nombre premier
       
    $len strlen($key);
       for(
    $h 0$i =0$i $len$i++)
            
    $h = (64 $h ord(substr($key$i1) - 32) % $M;
       return 
    $h;
    }
     
    INDEX :
    ******
      
    $CLE_HASH hash($CACHE_HASH);

    // CLE_HASH | SEPA | CACHE_HASH1 | SEPA | KEY_BLOC1 | SEPA | CACHE_HASH2 | SEPA | KEY_BLOC2 | etc..

    KEY_BLOC :
    ********
    // CACHE_HASH1 | TOKEN_CACHE | $timestamp1 | TOKEN_CACHE  | SQL_CACHE1 | TOKEN_CACHE | CACHE_HASH2 | TOKEN_CACHE | $timestamp2 | TOKEN_CACHE |SQL_CACHE2 | [...] | TOKEN_EOL

    Ainsi, je pourrais mettre plus de CACHE_HASHn par ligne, et puis la lecture de l'index se ferait en accès direct.

    Qu'en pensez-vous ?

    Y a-t-il déjà des librairies de pseudo fichiers en shared memory, avec lecture/écriture rapide ?

    Merci.
     
  69. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Rebonjour

    Je crois avoir trouvé la solution au problème.

    Avec des accès quasi directs.

    La fonction de hash ci-dessous :

    PHP:

    /**
     * Fonction de hashing :
     */
    function hash(string $key)
    {
       
    $M 101// un nombre premier
       
    $len strlen($key);
       for(
    $h 0$i =0$i $len$i++)
            
    $h = (64 $h ord(substr($key$i1) - 47) % $M;
       return 
    $h;
    }

    // Format des BLOC :
    *********************
      
    CLE_HASH hashCACHE_HASH à arranger pour être une clé du shm_open() de ce bloc.

    CLE_HASH SEPA CACHE_HASH_1SEPA SQL_CACHE_1 SEPA CACHE_HASH_2 SEPA SQL_CACHE_2 | [...] 

    Vous comprenez, je calcule en fonction de CASH_HASH avec hash() la clé hashée CLE_HASH du bloc devant contenir CASH_HASH et SQL_CACHE, et puis vogue la galère : Pour retrouver SQL_CACHE, je lit le bloc CLE_HASH, et le SQL_CACHE est indexé dedans.

    Le livre : "Algorihms in C" de Robert Sedgewick dit que pour la fonction hash(), $M nombre premier juste au dessus de nbre_total_enregs/10 peut convenir.

    48 est le code ascii de 0, donc j'enlève 47 au code ascii.

    Pour obtenir une clé valide du bloc correct, je me propose de multiplier le résultat de hash() par une constante pour élargir les valeurs des clés.

    Direct => array interprétable.

    Correct ?

    Merci beaucoup de votre aide.

    Amicalement.
     
  70. indigene
    indigene WRInaute accro
    Inscrit:
    7 Septembre 2003
    Messages:
    3 629
    J'aime reçus:
    66
    Intéressant ton système de cache. Si je m'ennuyais je n'hésiterais pas une seconde à l'implémenter.

    Pour l'instant mon système maison est beaucoup plus rudimentaire :

    Code:
    $CACHEACTIF = "ON";      // à mettre dans un fichier séquentiel de paramétrage
    
    
    IF ($CACHEACTIF != "ON") {
    $listecache = array();
    } else {
    $listecache = array(220, 96, 103, 124, 88, 365, 72, 1, 86, 7, 34, 102, 76, 428, 87, 2, 3, 17, 65, 77, 146, 153, 170, 172, 173, 174, 176, 177, 199, 462, 19, 121, 206, 214, 256, 267, 268, 316, 320, 326, 330, 338, 339, 345, 362, 98, 363, 364, 367, 371, 374, 379, 405, 410, 413, 414, 415, 420, 421, 92, 433, 437, 448, 453, 458, 461, 175, 464, 478, 479, 480, 481, 482, 487, 488, 489, 490, 517, 518, 520, 521, 522, 534, 553, 559, 566, 582, 583, 586, 594, 601, 620, 631, 696, 730, 810, 651);
    }
    if ( (($numart > 48) AND ($numart < 57) AND ($numart != 50))
         or (in_array ($numart, $listecache))
         )
        {
        include ($URI);                       // on affiche la page HTML sans passer par la génération php 
    }  else {
                          // traitement normal
    .....          
     
  71. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Voilà

    Suite à une visite sur Wikipedia Semaphore, voici la classe faite par mes soins, implémentant l'algorithme lecteur/rédacteur.

    Maintenant, ma classe de cache MySQL semble fonctionner sans blocage.

    Je vais mettre au point l'ensemble, puis le mettre sur le site.

    Super Wikipedia !

    Bien à vous.

    Amicalement.



    PHP:

    <?php
    class Semaphore
    {
        protected 
    $KeyM_Lect null;
        protected 
    $KeyM_Red null;
        protected 
    $Key_Red null;
        protected 
    $M_Lect null;    // Sémaphore mutex en lecture.
        
    protected $M_Red null;    // Sémaphore mutex en écriture.
        
    protected $Red null;    // Sémaphore bloquant les écritures.
        
    protected $Lect null;    // Variable protégée par $Red.
        
    protected $is_locked_M_Lect null;
        protected 
    $is_locked_M_Red null;
        protected 
    $is_locked_Red null;
        protected function 
    __construct(int $key)
        {
            
    /**
            * Il faut que
            * les clés paramètres
            * possibles
            * soient séparées
            * par plus que 20000.
            **/
            
    $this->KeyM_Lect $key;
            
    $this->KeyM_Red$key 10000;
            
    $this->Key_Red$key 20000;
            
    $this->Lect 0;
            if (!(
    $this->M_Lect sem_get($this->KeyM_Lect10666))) {
                throw new 
    RuntimeException("Cannot get $key semaphore identifier");
            }
            if (!(
    $this->M_Red sem_get($this->KeyM_Red10666))) {
                throw new 
    RuntimeException("Cannot get $key semaphore identifier");
            }
            if (!(
    $this->Red sem_get($this->Key_Red10666))) {
                throw new 
    RuntimeException("Cannot get $key semaphore identifier");
            }
            return 
    $this;
        }
        public function 
    __destruct()
        {
            if((
    is_resource($this->M_Lect))&&(!$this->is_locked_M_Lect))
                
    sem_remove($this->M_Lect);
            if((
    is_resource($this->Red))&&(!$this->is_locked_Red))
                
    sem_remove($this->Red);
            if((
    is_resource($this->M_Red))&&(!$this->is_locked_M_Red))
                
    sem_remove($this->M_Red);
            return 
    true;
        }
        protected function 
    BEGIN_READ()
        {
            if(
    sem_acquire($this->M_Lect) === false)
                return 
    false;
            
    $this->is_locked_M_Lect true;
            
    $this->Lect++;
            if(
    $this->Lect == 1)
            {
                if(
    sem_acquire($this->Red) === false)
                    return 
    false;
                
    $this->is_locked_Red true;
            }
            if(
    $this->is_locked_M_Lect)
                
    sem_release($this->M_Lect);
            return 
    true;
        }
        protected function 
    END_READ()
        {
            if(
    sem_acquire($this->M_Lect) === false)
                return 
    false;
            
    $this->is_locked_M_Lect true;
            
    $this->Lect--;
            if(
    $this->Lect == 0)
            {
                if(
    $this->is_locked_Red)
                    
    sem_release($this->Red);
            }
            if(
    $this->is_locked_M_Lect)
                
    sem_release($this->M_Lect);
            return 
    true;
        }
        protected function 
    BEGIN_WRITE()
        {
            if(
    sem_acquire($this->M_Red) === false)
                return 
    false;
            
    $this->is_locked_M_Red true;
            if(
    sem_acquire($this->Red) === false)
                return 
    false;
            
    $this->is_locked_Red true;
            return 
    true;
        }
        protected function 
    END_WRITE()
        {
            if(
    $this->is_locked_Red)
                
    sem_release($this->Red);
            if(
    $this->is_locked_M_Red)
                
    sem_release($this->M_Red);
            return 
    true;
        }
    }
    ?>


     
  72. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Voili, voilou

    Je dispose des clés des blocs et de leur contenus, de la forme :

    Code:
                    
    BLOC de clé : CLE_HASH :
    **********************
    // CACHE_HASH_1 | SEPA | FREQ | SEPA | $timestamp | SEPA  | SQL_CACHE_1 | SEPA | CACHE_HASH_2 | SEPA | FREQ | SEPA | $timestamp | SEPA | SQL_CACHE_2 | SEPA |
    
    
    FREQ est le nombre de cas ou le cache a été lu pour ce CACHE_HASH_i/SQL_CACHE_i.

    Ce nombre est incrémenté à chaque fois que la requête MySQL est lue dans le cache plutôt que dans la BDD.

    D'autre part, chaque bloc de clé CLE_HASH, a une taille en octets facilement lisible avec : $SHM->SIZE().

    Pour ne pas exagérer en ressources RAM, je dois effacer des blocs trop grands, les enregs trop anciens en gardant de préférence les FREQ élevés, donc plus fréquemment lus.

    Last but not least, je dois éventuellement garder les SQL_CACHEi les plus longs, car gourmands en délai lecture BDD.

    Comment quantifier toute ces contraintes, quel algorithme formaliser pour repérer
    les champs à effacer des blocs ?

    Merci beaucoup pour votre aide.

    Respectueusement.
     
  73. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Rebonjour

    Voilà, j'ai quatre variables statistiques représentatives de l'ordre souhaitable d"effacement des enregs des blocs.

    Les _MAX et _MIN s'entendent non pas par bloc, mais pour tous les blocs.


    - BLOC_SIZE en octets,

    - ( TIMESTAMP_i - TIMESTAMP_MIN ) / TIMESTAMP_MAX - TIMESTAMP_MIN ),

    - ( FREQ_i- FREQ_MIN ) / ( FREQ_MAX - FREQ_MIN ),

    - ( SQL_CACHE_SIZE_i - SQL_CACHE_SIZE_MIN ) / ( SQL_CACHE_SIZE_MAX - SQL_CACHE_MIN )

    Ma question est : Comment calculer une fonction d'ordre pondérant ces 4 variables, pour fixer l'enreg à effacer ( l'enreg correspondant à l'indice -i ) ?

    Merci beaucoup de vos suggestions.

    Respect.
     
  74. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Rebond.

    Pour donner suite, l'ordre d'effacement serait :

    1) Ordre croissant : SQL_CACHE_SIZE_i,

    2) Ordre croissant : TIMESTAMP_i

    3) Ordre croissant : FREQ_i

    Je n'ai plus qu'à fixer les facteurs de ma combinaison linéaire.

    Le BLOC_SIZE n'a pas d'importance.

    A+.
     
  75. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour

    Voilà j'ai mis mon cache MySQL en ligne.

    J'ai également désactivé le cache html, pour tester le cache MySQL.

    J'ai prévu un cache maximum de 1 Go, ce maximum n'est jamais atteint car dès qu'il est à moitié rempli, des champs de blocs sont libérés automatiquement, ce qui divise par deux environ l'espace RAM occupé. ( Donc 1 Go / 2 / 2 = 256 Mo en théorie ).

    Je visualiserai les variables en cours demain matin.

    Merci de tester au : https://www.pronostics-courses.fr

    Voilà.

    Bien amicalement.
     
  76. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour

    J'ai actuellement quatre programmes :

    1) Accès à ma bdd style orm Eloquent version 2,
    2) 1 classe de cache MySQL avec mémoires partagées,
    3) 1 classe d'accès écriture/lecture à la mémoire partagée,
    4) 1 classe de synchronisation des accès, implémentant l'algorithme lecteur/rédacteur, et l'algorithme exclusion mutuelle.

    Le problème, est que le cache MySQL allocate des blocs de mémoires partagée, dont le nombre paramètre peut être entre 101 blocs pour 128 Ko max de RAM occupée, à 601 blocs pour 7 Mo de RAM max occupée.

    Pour chaque blocs de mémoire partagée, il y a 3 sémaphores assurant l'algorithme lecteur/rédacteur et 2 sémaphores pour l'exclusion mutuelle.

    Quand la RAM globale allocatée dépasse la moitié du max de RAM occupée, une fonction libère une fraction de cette RAM, en utilisant l'exclusion mutuelle pour éviter 2 lancements simultanés de cette fonction.

    Le blème, est qu'l y a trop de sémaphores, et leur nombre semble empêcher leur propre instanciation.

    Vous, comment assurez-vous la synchronisation de vos accès aux mémoires partagées ?

    Ceci, dans le cas où il y a un certain nombre de blocs allocatés ?

    Merci beaucoup de vos réponses.

    Respectueusement.
     
  77. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour

    J'ai fait une classe SHMOP d'accès à de la mémoire partagée en lecture/écriture, avec synchronisation incorporée par sémaphore virtuel consistant en le caractère en début de la shmop :

    "0" non locké, accès libre pour lecture et écriture,
    "1" locké, accès refusé pour lecture et écriture,
    "3" eof.

    Le "1" n'est positionné que au début d'une écriture, et mis à "0" après l'écriture.

    C'est une classe singleton pour chaque clés de chaque shmop.

    Merci de me donner vos avis par rapport à cette implémentation.

    Amicalement.


    PHP:

    <?php
    ########################
    # shmop.class.php
    ########################
    class SHMOP
    {
        const 
    MAXINT 65536 65536 1;
        
    /********************************/
        /*    VARIABLES MUTEX        */
        /********************************/
        /**
        * @access private
        * @var int
        */
        
    private $writers 0;
        
    /********************************/
        /*    VARIABLES SHMOP        */
        /********************************/
        
    private $shmKEY        null;
        private 
    $shmId        null;
        private 
    $shmMode    null;
        private 
    $shmFlags    null;
        private 
    $shmHeaderOffset    null;
        private 
    $shmBlockSize        null;
        private 
    $shmMaxBlockSize    null;
        private 
    $shmLimitBlockSize    null;
        
    /**
        * C'est un singleton
        * par clés $this->shmKey.
        **/
        
    protected static $instance// Instance de la classe.
        
    protected function __clone() { } // Méthode de clonage en privé.
        
    public static function getInstance(int $key)
        {
            
    /**   
            * Si on n'a pas 
            * encore instancié 
            * notre classe
            * pour cette $this->shmKey.
            **/
            
    if (!isset(self::$instance[$key])) 
            {
                
    self::$instance[$key] = new  self($key); // On s'instancie nous-mêmes. :)
            
    }
            return 
    self::$instance[$key];
        }
        protected function 
    __construct(int $key)
        {
            
    $this->shmKey $key;
            
    $this->shmMode 0;
            
    $this->shmFlags "a";
            
    $size 2048;
            
    $CHAR_MAX "A";
            
    $this->shmHeaderOffset strlen($CHAR_MAX) + 1;
            
    $this->shmMaxBlockSize $size;
            
    $this->shmBlockSize $size $this->shmHeaderOffset 1;
            
    /**
            * Surplus
            * pour dépassements
            * peu fréquents.
            **/
            
    $this->shmLimitBlockSize 4096 * (ceil(1.5 $this->shmBlockSize 4096.0));
            return 
    $this;
        }
        function 
    __destruct()
        {
            @
    shmop_close($this->shmId);
            
    self::$instance[$this->shmKey] = null;
            return 
    true;
        }
        
    /**
        * Format type
        * string conpressée
        * après linearisation.
        **/
        
    private function SHMOP_DEFLATE(string $value)
        {
            
    /**
            * On ajoute un "\0".
            **/
            
    $data $this->str_to_nts($value); 
            
    /**
            * VALUE => SERIALIZE => COMPRESS => BASE64_ENCODE => STR
            **/
            
    return base64_encode(gzcompress(serialize($data)));
        }
        
    /**
        * Format type
        * string déconpressée
        * et délinéarisée.
        **/
        
    private function SHMOP_INFLATE($value)
        {
            
    /**
            * On enlève le "\0".
            **/
            
    $data $this->str_from_mem($value);
            
    /*
            * STR => BASE64_DECODE => UNCOMPRESS => UNSERIALIZE.
            */
            
    return unserialize(gzuncompress(base64_decode($data)));
        }
        private function 
    str_from_mem(string &$value) {
            
    $i strpos($value"\0");
            if (
    $i === false) {
                
    $result $value;
            }
            else {
                
    $result =  substr($value0$i);
            }
            return 
    $result;
        }
        private function 
    str_to_nts(string $value) {
            return 
    "$value\0";
        }
        private function 
    wrapper_shmop_open(int $keystring $flagsint $perm 0666int $size 0)
        {
            
    /**
            * USER root,
            * specific threatment
            * for opening
            * the SHM as nginx.
            **/
            
    if(posix_getuid() == 0)
            {
                switch(
    $flags) {
                case 
    "n" :
                case 
    "c" :
                    
    /**
                    * Creation
                    * comme user
                    * nginx.
                    **/
                    
    exec("sudo -u nginx php -r 'shmop_open(" $key ", " $flags ", " $perm ", " $size ");'"); //Create Shared Memory segment as USER nginx
                    
    break;
                default :
                    break;
                }
            }
            return @
    shmop_open($this->shmKey$flags$perm$size);
        }
        function 
    OPEN(string $flagsint $modeint $size)
        {
            
    $this->shmMode $mode;
            
    $this->shmFlags $flags;
            if(
    in_array($this->shmFlags, array("a""w"), true))
            {
                
    $shm = @$this->wrapper_shmop_open($this->shmKey$this->shmFlags$this->shmMode0);
                if(
    $shm === false)
                {
                    return 
    false;
                }
                
    $this->shmId $shm;
                
    /**
                * Il faudrait
                * abstractiser
                * plus le maniement
                * des objets.
                **/
                
    return $this;
            }
            switch (
    $this->shmFlags) {
                
    /**
                * Pour créer
                * un nouveau bloc
                * même s'il existe.
                **/
            
    case "n" :
                
    /**
                * Le SHM
                * ne doit
                * pas exister.
                **/
                
    $shm = @$this->wrapper_shmop_open($this->shmKey"a"$this->shmMode0);
                if(
    $shm !== false)
                {
                    @
    shmop_delete($shm);
                    
    shmop_close($shm);
                }
                unset(
    $shm);
                
    $this->ALLOCATE($size);
                
    /**
                * Delete 
                * instantané ?
                **/
                
    $shm = @$this->wrapper_shmop_open($this->shmKey$this->shmFlags$this->shmMode$this->shmLimitBlockSize);
                if(
    $shm === false)
                {
                    unset(
    $shm);
                    throw new 
    RuntimeException("Erreur création SHM. en mode : " $this->shmFlags);
                    return 
    false;
                }
                
    $this->shmId $shm;
                
    /**
                * SHM créé
                **/
                // release spinlock
                
    @shmop_write($this->shmId"0"0);
                
    shmop_write($this->shmId$this->SHM_DEFLATE(""), 1);
                break;
                
    /**
                * Pour créer
                * un bloc
                * s'il n'existe pas,
                * ou l'ouvrir
                * en lecture/écriture
                * s'il existe.
                **/
            
    case "c" :
                
    /**
                * SHM existe,
                * ouvert
                * en lecture/création/écriture.
                **/
                
    $shm = @$this->wrapper_shmop_open($this->shmKey"c"$this->shmMode$this->shmLimitBlockSize);
                if(
    $shm === false)
                {
                    throw new 
    RuntimeException("Erreur création/écriture SHM.");
                    return 
    false;
                }
                
    $drapeau_exist false;
                
    /**
                * Limite inférieure
                * à déterminer.
                **/
                
    if(shmop_size($shm) > 0)
                {
                    
    $drapeau_exist true;
                    
    $this->shmId $shm;
                    
    $data shmop_read($shm0shmop_size($shm));
                    
    $writers = (int)substr($data01);
                    
    $enreg substr($data1);
                }
                else
                {
                    
    $writers 0;
                    
    $enreg  $this->SHMOP_DEFLATE("");
                }
                if(
    $this->ALLOCATE($size))
                {
                    
    shmop_delete($shm);
                    
    shmop_close($shm);
                    
    /**
                    * Delete 
                    * instantané ?
                    **/
                    
    $shm = @$this->wrapper_shmop_open($this->shmKey"n"$this->shmMode$this->shmLimitBlockSize);
                    if(
    $shm === false)
                    {
                        unset(
    $shm);
                        throw new 
    RuntimeException("Erreur création SHM.");
                        return 
    false;
                    }
                    
    $this->shmId $shm;
                    
    /**
                    * SHM créé
                    **/
                    
    $value $writers $enreg;
                    
    shmop_write($this->shmId$value0);
                }
                else
                {
                    
    $this->shmId $shm;
                    if(
    $drapeau_exist === false)
                    {
                        
    /**
                        * SHM initialisé
                        **/
                        
    $value $writers $enreg;
                        
    shmop_write($this->shmId$value0);
                    }
                }
                break;
            default :
                break;
            }
            return 
    $this;
        }
        function 
    EXIST()
        {
            
    /**
            * SHM existe.
            **/
            
    if($this->OPEN("a"06660) !== false)
            {
                
    shmop_close($this->shmId);
                return 
    true;
            }
            return 
    false;
        }
        function 
    ALLOCATE(int $size)
        {
            
    $BlockSize $size $this->shmHeaderOffset 1;
            if((
    $this->shmMaxBlockSize <= $size)||
                (
    $this->shmBlockSize <= $BlockSize)||
                (
    $this->shmLimitBlockSize <= (4096 * (ceil(1.5 $BlockSize 4096.0)))))
            {
                
    $this->shmMaxBlockSize $size;
                
    $this->shmBlockSize $size $this->shmHeaderOffset 1;
                
    /**
                * Surplus
                * pour dépassements
                * peu fréquents.
                **/
                
    $this->shmLimitBlockSize 4096 * (ceil(1.5 $this->shmBlockSize 4096.0));
                return 
    true;
            }
            return 
    false;
        }
        private function 
    tmp_read(bool $block false)
        {
            if(
    $this->OPEN("w"06660) === false)
            {
                return 
    false;
            }
            
    // Check SpinLock
            
    if(@shmop_read($this->shmId01) !== "0")
            {
                return 
    false;
            }
            if((
    $enreg = @shmop_read($this->shmId1, @shmop_size($this->shmId) - 1)) === false)
            {
                throw new 
    RuntimeException("Erreur lecture SHM.");
                return 
    false;
            }
            if(
    $block === true)
            {
                
    // Write spinlock
                // for update.
                
    @shmop_write($this->shmId"2"0);
            }
            
    shmop_close($this->shmId);
            return 
    $this->SHMOP_INFLATE($enreg);
        }
        private function 
    tmp_write(string $databool $block false)
        {
            
    $size strlen($this->SHMOP_DEFLATE($data)) + 256;
            if(
    $this->OPEN("c"0666$size) === false)
            {
                return 
    false;
            }
            if(
    $block === false)
            {
                
    // Check SpinLock
                
    if(@shmop_read($this->shmId01) !== "0")
                {
                    return 
    false;
                }
            }
            else
            {
                
    // Check SpinLock
                
    if(@shmop_read($this->shmId01) !== "2")
                {
                    return 
    false;
                }
            }
            
    // Write spinlock
            
    @shmop_write($this->shmId"1"0);
            if((
    $enreg = @shmop_read($this->shmId1, @shmop_size($this->shmId) - 1)) === false)
            {
                throw new 
    RuntimeException("Erreur écriture SHM.");
                return 
    false;
            }
            if(
    strlen($data) < 1)
            {
                @
    shmop_write($this->shmId"0"1);
                throw new 
    RuntimeException('dataSize < 1');
                return 
    false;
            }
            
    // Write Data
            
    @shmop_write($this->shmId$this->SHMOP_DEFLATE($data), 1);
            
    // release spinlock
            
    @shmop_write($this->shmId"0"0);
            
    shmop_close($this->shmId);
            return 
    true;
        }
        protected function 
    READ(bool $block false)
        {
            
    /**
            * Mettre
            * un délai.
            **/
            
    while(true)
            {
                if((
    $data $this->tmp_read($block)) !== false)
                {
                    return 
    $data;
                }
            }
        }
        protected function 
    WRITE(string $databool $block false)
        {
            
    /**
            * Mettre
            * un délai.
            **/
            
    while(true)
            {
                if(
    $this->tmp_write($data$block) !== false)
                {
                    break;
                }
            }
            return 
    $this;
        }
        protected function 
    APPEND(string $data)
        {
            
    $enreg $this->READ(true);
            
    $str $this->SHMOP_DEFLATE($enreg) . $data;
            return 
    $this->WRITE($str true);
        }
        protected function 
    CLOSE()
        {
            return @
    shmop_close($this->shmId);
        }
        protected function 
    DELETE()
        {
            return @
    shmop_delete($this->shmId);
        }
        protected function 
    EOF()
        {
            if(
    $this->OPEN("a"06660) === false)
            {
                return 
    false;
            }
            
    $res =  (@shmop_read($this->shmId01) === "3") ? true false;
            
    shmop_close($this->shmId);
            return 
    $res;
        }
        protected function 
    SEND_EOF()
        {
            if(
    $this->OPEN("w"06660) === false)
            {
                return 
    false;
            }
            
    // Check SpinLock
            
    if(@shmop_read($this->shmId01) !== "0")
            {
                
    shmop_close($this->shmId);
                return 
    false;
            }
            @
    shmop_write($this->shmId"3"0);
            
    shmop_close($this->shmId);
            return 
    true;
        }
        protected function 
    IS_LOCKED()
        {
            if(
    $this->OPEN("a"06660) === false)
            {
                return 
    false;
            }
            
    // Check SpinLock
            
    $res =  (@shmop_read($this->shmId01) === "1") ? true false;
            
    shmop_close($this->shmId);
            return 
    $res;
        }
        protected function 
    RELEASE_LOCK()
        {
            if(
    $this->OPEN("w"06660) === false)
            {
                return 
    false;
            }
            
    // release spinlock
            // for writing.
            
    @shmop_write($this->shmId"0"0);
            
    shmop_close($this->shmId);
            return 
    true;
        }
        protected function 
    SET_LOCK()
        {
            if(
    $this->OPEN("w"06660) === false)
            {
                return 
    false;
            }
            
    // Write spinlock
            
    @shmop_write($this->shmId"1"0);
            
    shmop_close($this->shmId);
            return 
    true;
        }
        protected function 
    SIZE()
        {
            
    $str $this->READ();
            if(
    $str === false)
            {
                return 
    false;
            }
            return 
    strlen($this->SHMOP_DEFLATE($str));
        }
    }
    ?>


     
  78. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour

    J'ai un problème.

    Je peux faire un shmop_delete($shmId) correct ( il rend 1 ), mais pas le shmop_close($shmid) après 10ms ( rend rien ).

    Comment se fait-il que le $shmId ne soit plus valide après le shmop_delete() ?

    Par ailleurs, je n'arrive pas à ouvrir le même SHM en mode "n" ou "c", après l'avoir détruit avec ces deux fonctions.

    Sinon tout baigne, je teste pour l'instant 4 requêtes MySQL qui semblent être correctement cachées.

    Merci beaucoup beaucoup de votre aide.
     
  79. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Pardon

    shmop_close() est de type void, donc normal qu'il ne rende rien.

    Mais pourquoi ( sous Linux Fedora 30 ) :

    PHP:

      shmop_delete
    ($shmId); // Correct, rend 1
      
    shmop_close($shmId);  // void

       
    usleep(10000);

      
    $shm open($same_key"n"0666$new_size);

      if(empty(
    $shm))
      {
          echo 
    "Erreur open SHM en mode création.\n\n";

         return 
    false;
      }

      
    $shmId $shm;

      
    Le message d'erreur est toujours affiché.

    Pourquoi ?

    Merci beaucoup.
     
  80. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour

    Ma question est plus générale.

    Mettons des ressources ( shmop ) par clés $key et une classe singleton par clé.

    Pour l'accès à la ressource de clé $key , j'ai besoin d 'un verrou.

    Est-ce qu'une variable array par clé static mise à zéro une fois dans le constructeur pourrait faire office de verrou ?

    C'est-à-dire : Atomicité suffisante pour les accès concurrents ?

    Si oui, comment çà se fait que je n'ai pas vu d'implémentation sur le net ?

    C'est beaucoup plus rapide d'incrémenter/décrémenter une variable qu'un bout de shmop ?

    Merci beaucoup de vos réponses.

    Amicalement.
     
  81. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Je vous demande pardon

    Ma stupide précédente question est absurde, les variables static ne sont pas partagées entre processus.

    Je dois augmenter la taille d'un SHM.

    Comment faire celà ?

    Le paramètre "n" de shmop_open($key, "n", 0777, $size) a ce commentaire dans le PHP Manual :

    • "n" crée un nouveau segment de mémoire partagée (utilise IPC_CREATE|IPC_EXCL). Utilisez cette option lorsque vous voulez créer un nouveau segment de mémoire partagée sauf s'il en existe déjà un corrompu avec la même option. Ceci est très pratique pour des raisons de sécurité, pour éviter des trous de sécurité qui exploiteraient la course aux ressources.

    Le problème est : Est-on obligé de ne strictement jamais augmenter la taille
    d'un SHM à l'ouverture en écriture ?


    Comment faire si s'est le cas ?

    Le processus qui l'a créé est-il le seul à pouvoir le deleter ?

    Merci beaucoup pour votre aide.

    Respectueusement.
     
  82. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour

    Avec le même algorithme lecteur/rédacteur, je peux faire en sorte que les ouvertures de blocs ne soient jamais simultanées.

    La variable "Lect" de nombre de rédacteurs est partagée car mise au début de chaque bloc.

    Dans ce cas ( ouvertures non simultanées ) , j'arrive bien ( semble-t-il ), à deleter et recréer les blocs en en augmentant la taille si besoin.

    Le problème est dans l'évaluation et le choix de la taille, qui ne peut être fait que par bloc.

    Mais celà m'occasionne souvent des updates de tailles.

    D'un autre côté, comment rendre atomistique les cycles READ() ->WRITE() ?

    Voici le soft :

    Merci beaucoup.



    Code:
    
    <?php
    
    ########################
    class SHMOP
    {
        /********************************/
        /*    VARIABLES MUTEX        */
        /********************************/
        /*    3 SEMAPHORES        */
        /********************************/
        /*         CLES        */
        /********************************/
        private $shmLect_1    = null;
        private $shmRed_1    = null;
        private $shmRed        = null;
        /********************************/
        /*        SEM_ID        */
        /********************************/
        private $semLect_1    = array();
        private $semRed_1    = array();
        private $semRed        = array();
      
        /********************************/
        /*    VARIABLE NBRE LECTEURS    */
        /********************************/
        private $shmLect    = array();
        /********************************/
        /*    VARIABLES SHMOP        */
        /********************************/
        private $shmKEY        = null;
        private $shmId        = null;
        private $shmMode    = null;
        private $shmFlags    = null;
        private $shmOffsetEnreg        = array();
        private $shmBlockSize        = array();
        private $shmLimitBlockSize    = array();
        /**
        * C'est un singleton
        * par clés $this->shmKey.
        **/
        protected static $instance    = array(); // Instance de la classe.
        protected function __clone() { } // Méthode de clonage en privé.
        public static function getInstance(int $key)
        {
            /**  
            * Si on n'a pas
            * encore instancié
            * notre classe
            * pour cette $this->shmKey.
            **/
            if (!isset(self::$instance[$key]))
            {
                self::$instance[$key] = new  self($key); // On s'instancie nous-mêmes. :)
            }
            return self::$instance[$key];
        }
        protected function __construct(int $key)
        {
            $this->shmKey = $key;
            $this->shmMode = 0;
            $this->shmFlags = "a";
            /**
            mutex Lect_1 = 1     => protège variable Lect
            mutex Red_1 = 1        => bloque les rédactions
            sémaphore Red = 1     => bloque lectures si Rédaction en cours.
            variable Lect        = nombre de Lecteurs
            **/
            $this->shmLect[$this->shmKey] = $this->shmKey;
            $this->shmLect_1[$this->shmKey] = $this->shmKey + 1000;
            $this->shmRed_1[$this->shmKey] = $this->shmKey + 2000;
            $this->shmRed[$this->shmKey] = $this->shmKey + 3000;
            $size = 1024;
            $this->shmOffsetEnreg[$this->shmKey] = strlen($size);
            $this->shmBlockSize[$this->shmKey] = $this->shmOffsetEnreg[$this->shmKey] + $size + 1;
            /**
            * Surplus
            * pour dépassements[$this->shmKey]
            * peu fréquents.
            **/
            /**
            * Valeur courante.
            **/
            $this->shmLimitBlockSize[$this->shmKey] = 2048 * ceil($this->shmBlockSize[$this->shmKey] / 2048.0);
    //        error_reporting(true);
            return $this;
        }
        function __destruct()
        {
            /**
            sem_remove($this->semLect_1[$this->shmKey]);
            sem_remove($this->semRed_1[$this->shmKey]);
            sem_remove($this->semRed[$this->shmKey]);
            **/
            self::$instance[$this->shmKey] = null;
            return true;
        }
        private function Init_Mutex()
        {
            /************************/
            /* INSTANCIATION MUTEX    */
            /************************/
            if(($this->semLect_1[$this->shmKey] = sem_get($this->shmLect_1[$this->shmKey])) === false)
                return false;
            if(($this->semRed_1[$this->shmKey] = sem_get($this->shmRed_1[$this->shmKey])) === false)
                return false;
            if(($this->semRed[$this->shmKey] = sem_get($this->shmRed[$this->shmKey])) === false)
                return false;
            /************************/
            /* INIIALISATION LECT    */
            /************************/
            if(!$this->wrapper_shmop_write($this->shmId, $this->SHMOP_DEFLATE("0"), 0))
                return false;
            return true;
        }
        private function BEGIN_READ()
        {
            /**
            P(M_Lect)
                Lect++
            si Lect==1 alors
                P(Red)
            FIN SI
            V(M_Lect)
            **/
            /************************/
            /*   Commencer_Lire    */
            /************************/
            if((!isset($this->semLect_1[$this->shmKey]))
                &&(!isset($this->semRed_1[$this->shmKey]))
                &&(!isset($this->semRed[$this->shmKey])))
            {
                $this->Init_Mutex();
            }
            sem_acquire($this->semLect_1[$this->shmKey]);
            if($this->wrapper_shmop_write($this->shmId, $this->SHMOP_DEFLATE((string)((int)$this->SHMOP_INFLATE($this->wrapper_shmop_read($this->shmId, 0, $this->shmOffsetEnreg[$this->shmKey]))) + 1), 0) === false)
            {
                sem_release($this->semLect_1[$this->shmKey]);
                return false;
            }
            if((int)$this->SHMOP_INFLATE($this->wrapper_shmop_read($this->shmId, 0, $this->shmOffsetEnreg[$this->shmKey])) == 1)
                sem_acquire($this->semRed[$this->shmKey]);
            sem_release($this->semLect_1[$this->shmKey]);
            return true;
        }
        private function END_READ()
        {
            /**
            P(M_Lect)
            Lect--
            SI Lect==0 ALORS
            V(Red)
            FIN SI
            V(M_Lect)
            **/
            if((!isset($this->semLect_1[$this->shmKey]))
                &&(!isset($this->semRed_1[$this->shmKey]))
                &&(!isset($this->semRed[$this->shmKey])))
            {
                $this->Init_Mutex();
            }
            /************************/
            /*    Finir_Lire    */
            /************************/
            sem_acquire($this->semLect_1[$this->shmKey]);
            if($this->wrapper_shmop_write($this->shmId, $this->SHMOP_DEFLATE((string)((int)$this->SHMOP_INFLATE($this->wrapper_shmop_read($this->shmId, 0, $this->shmOffsetEnreg[$this->shmKey]))) - 1), 0) === false)
            {
                sem_release($this->semLect_1[$this->shmKey]);
                return false;
            }
            if((int)$this->SHMOP_INFLATE($this->wrapper_shmop_read($this->shmId, 0, $this->shmOffsetEnreg[$this->shmKey])) == 0)
                sem_release($this->semRed[$this->shmKey]);
            sem_release($this->semLect_1[$this->shmKey]);
            return true;
        }
        private function BEGIN_WRITE()
        {
            /**
            P(M_Red)
            P(Red)
            **/
            /************************/
            /*   Commencer_Ecrire    */
            /************************/
          
            if((!isset($this->semLect_1[$this->shmKey]))
                &&(!isset($this->semRed_1[$this->shmKey]))
                &&(!isset($this->semRed[$this->shmKey])))
            {
                $this->Init_Mutex();
            }
            sem_acquire($this->semRed_1[$this->shmKey]);
            sem_acquire($this->semRed[$this->shmKey]);
            return true;
        }
        protected function END_WRITE()
        {
            /**
            V(Red)
            V(M_Red)
            **/
            if((!isset($this->semLect_1[$this->shmKey]))
                &&(!isset($this->semRed_1[$this->shmKey]))
                &&(!isset($this->semRed[$this->shmKey])))
            {
                $this->Init_Mutex();
            }
            /************************/
            /*   Finir_Ecrire    */
            /************************/
            sem_release($this->semRed[$this->shmKey]);
            sem_release($this->semRed_1[$this->shmKey]);
            return true;
        }
            protected function millisecond()
            {
                    return floor(microtime(true)/0.001 + 0.5);
            }
        /**
        * Pour les
        * ID de SHMOP.
        **/
            private function SHM_ID($str)
            {
            return '"' . $str . '"';
            }
        /**
        * Format type
        * string conpressée
        * après linearisation.
        **/
        private function SHMOP_DEFLATE(string $value)
        {
            /**
            * On ajoute un '\0'.
            **/
            return $this->str_to_nts($value);
            /**
            * VALUE => COMPRESS => BASE64_ENCODE => STR
            **/
            $str = base64_encode($value);
            $str =  base64_encode(gzcompress($value));
        }
        /**
        * Format type
        * string déconpressée
        * et délinéarisée.
        **/
        private function SHMOP_INFLATE($value)
        {
            /**
            * On enlève le '\0'.
            **/
            $data =  $this->str_from_mem($value);
            return $data;
            /*
            * STR => BASE64_DECODE => UNCOMPRESS.
            */
            return base64_decode($data);
            return gzuncompress(base64_decode($data));
        }
        private function str_from_mem(string &$value) {
            $i = strpos($value, chr(0));
            if ($i !== false) {
                return substr($value, 0, $i);
            }
            return $value;
        }
        private function str_to_nts(string $value) {
            return $value.chr(0);
        }
        private function wrapper_shmop_open(int $key, string $flags, int $perm = 0777, int $size = 0)
        {
            /**
            * USER root,
            * specific threatment
            * for opening
            * the SHM as nginx.
            **/
            if(posix_geteuid() == 0)
            {
                switch($flags) {
                case "n" :
                    /**
                    * Creation
                    * comme user
                    * nginx.
                    **/
                    exec("sudo -u nginx php -r 'shmop_open(" . $key . ", \"" . $flags . "\", " . $perm . ", " . $size . ");'"); //Create Shared Memory segment as USER nginx
                    /**
                    ob_start();
                    passthru("/usr/bin/sudo -u nginx -g nginx /usr/bin/php -r '@shmop_open(" . $key . ", \"" . $flags . "\", " . $perm . ", " . $size . ");'", $result); //Create Shared Memory segment as USER nginx
                    $output = ob_get_contents();
                    ob_end_clean();
                    **/
                    $flags = "w";
                    return shmop_open($key, $flags, $perm, $size);
                    break;
                case "c" :
                    /**
                    * Creation
                    * comme user
                    * nginx.
                    **/
                    exec("sudo -u nginx php -r 'shmop_open(" . $key . ", \"" . $flags . "\", " . $perm . ", " . $size . ");'"); //Create Shared Memory segment as USER nginx
                    /**
                    ob_start();
                    passthru("/usr/bin/sudo -u nginx -g nginx /usr/bin/php -r '@shmop_open(" . $key . ", \"" . $flags . "\", " . $perm . ", " . $size . ");'", $result); //Create Shared Memory segment as USER nginx
                    $output = ob_get_contents();
                    ob_end_clean();
                    **/
                    $flags = "w";
                    break;
                default :
                    break;
                }
            }
            return @shmop_open($key, $flags, $perm, $size);
        }
        private function wrapper_shmop_delete($shmId)
        {
            /**
            * USER root,
            * maybe
            * specific threatment
            * for deleting
            * the SHM as nginx.
            **/
            /**
            if(posix_geteuid() == 0)
            {
                echo "DELETE<br />\n\n";
                **/
                /**
                * Delete
                * comme user
                * nginx.
                **/
    //            exec("sudo -u nginx php -r 'shmop_delete(" . $this->SHM_ID($shmId) . ");'"); //Create Shared Memory segment as USER nginx
    //            exec("sudo -u nginx php -r '@shmop_delete(\"" . $shmId . "\");'", $output, $result); //Create Shared Memory segment as USER nginx
                /**
                ob_start();
                passthru("/usr/bin/sudo -u nginx -g nginx /usr/bin/php -r '@shmop_delete(" . $this->SHM_ID($shmId) . ");'", $result); //Create Shared Memory segment as USER nginx
                ob_end_clean();
                **/
                /**
                if(empty($result))
                    $result = false;
                    **/
    /**
                    echo "\t\t\tRESULTAT DELETE = ";
                    if(is_array($output))
                    {
                        print_r($output);
                    }
                    else
                    {
                        echo $output;
                    }
                    echo "<br /><br />\n";
                echo "\t\t\tRESULT DELETE = " . $result . "<br /><br />\n";
                    return $result;
            }
            **/
            $result = shmop_delete($shmId);
    //        echo "RESULTAT DELETE = " . $result . "<br />\n\n";
            return $result;
        }
        private function wrapper_shmop_size($shmId)
        {
            /**
            * USER root,
            * maybe
            * specific threatment
            * for closing
            * the SHM as nginx.
            **/
            /**
            if(posix_geteuid() == 0)
            {
                echo "SHMOP_SIZE<br />\n\n";
                **/
                /**
                * Delete
                * comme user
                * nginx.
                **/
    //            exec("sudo -u nginx -g nginx php -r '@shmop_size(" . $this->SHM_ID($shmId) . ");'", $output, $result); //Create Shared Memory segment as USER nginx
    //            exec("sudo -u nginx -g nginx php -r '@shmop_size(\"" . $shmId . "\");'", $output, $result); //Create Shared Memory segment as USER nginx
            //            ob_start();
            /**
                passthru("/usr/bin/sudo -u nginx -g nginx /usr/bin/php -r '@shmop_size(" . $this->SHM_ID($shmId) . ");'", $result); //Create Shared Memory segment as USER nginx
                $output = ob_get_contents();
    //            ob_end_clean();
                return $output;
                return $result;
            }
            **/
            return shmop_size($shmId);
        }
        private function wrapper_shmop_close($shmId)
        {
            /**
            * USER root,
            * maybe
            * specific threatment
            * for closing
            * the SHM as nginx.
            **/
            /**
            if(posix_geteuid() == 0)
            {
                echo "CLOSE<br />\n\n";
                **/
                /**
                * Delete
                * comme user
                * nginx.
                **/
            /**
                exec("sudo -u nginx php -r '@shmop_close(" . $this->SHM_ID($shmId) . ");'"); //Create Shared Memory segment as USER nginx
    //            exec("sudo -u nginx -g nginx php -r '@shmop_close(\"" . $shmId . "\");'", $output, $result); //Create Shared Memory segment as USER nginx
                ob_start();
                passthru("/usr/bin/sudo -u nginx -g nginx /usr/bin/php -r '@shmop_close(" . $this->SHM_ID($shmId) . ");'", $result); //Create Shared Memory segment as USER nginx
                ob_end_clean();
                return;
            }
        **/
            return shmop_close($shmId);
        }
        private function wrapper_shmop_read($shmId, $offset, $tmp_count)
        {
            /**
            * USER root,
            * maybe
            * specific threatment
            * for reading
            * the SHM as nginx.
            **/
            /**
            if(posix_geteuid() == 0)
            {
            **/
                /**
                * Delete
                * comme user
                * nginx.
                **/
    //            return exec("sudo -u nginx -g nginx php -r '@shmop_read(" . $this->SHM_ID($shmId) . ", " . $offset . ", " . $tmp_count . ");'", $output, $result); //Create Shared Memory segment as USER nginx
    /**
                ob_start();
                passthru("/usr/bin/sudo -u nginx -g nginx /usr/bin/php -r '@shmop_read(" . $this->SHM_ID($shmId) . ", " . $offset . ", " . $tmp_count . ");'", $result); //Create Shared Memory segment as USER nginx
                $output = ob_get_contents();
                ob_end_clean();
                return $output;
            }
            **/
            return shmop_read($shmId, $offset, $tmp_count);
        }
        private function wrapper_shmop_write($shmId, $value, $offset)
        {
            /**
            * USER root,
            * maybe
            * specific threatment
            * for writing
            * the SHM as nginx.
            **/
            /**
            if(posix_geteuid() == 0)
            {
                if(strlen($value) < 3)
                {
                    $value = $this->SHM_ID($value);
                }
                echo "WRITE<br />\n\n";
                **/
                /**
                * Delete
                * comme user
                * nginx.
                **/
                //    exec("sudo -u nginx -g nginx php -r '@shmop_write(" . $this->SHM_ID($shmId) . ", \"" . $value . "\", " . $offset . ");'", $output, $result); //Create Shared Memory segment as USER nginx
    /**
          
                ob_start();
                passthru("/usr/bin/sudo -u nginx -g nginx /usr/bin/php -r '@shmop_write(" . $this->SHM_ID($shmId) . ", " . $value . ", " . $offset . ");'", $result); //Create Shared Memory segment as USER nginx
                ob_end_clean();
                return $result;
            }
            **/
            return shmop_write($shmId, $value, $offset);
        }
        private function OPEN(string $flags, int $mode, int $size)
        {
            $this->shmMode = $mode;
            $this->shmFlags = $flags;
            $this->shmId = false;
            if(in_array($this->shmFlags, array("a", "w")))
            {
                if($size == 0)
                {
                    $shm = $this->wrapper_shmop_open($this->shmKey, $this->shmFlags, 0777, 0);
                }
                else
                {
                    $shm = $this->wrapper_shmop_open($this->shmKey, $this->shmFlags, 0777, $this->shmLimitBlockSize[$this->shmKey]);
                }
                if($shm === false)
                {
                    return false;
                }
                $this->shmId = $shm;
                return true;
            }
            switch ($this->shmFlags) {
            case "n" :
                /**
                * On update
                * si besoin
                * les paramètres
                * d'allocation
                * mémoire.
                **/
                $this->ALLOCATE($size);
                $shm = $this->wrapper_shmop_open($this->shmKey, $this->shmFlags, 0777, $this->shmLimitBlockSize[$this->shmKey]);
                /**
                * Le SHM
                * ne doit
                * pas exister.
                **/
                if($shm === false)
                {
                    echo "\t\t" . 'Erreur création : Le SHM existe déjà.' . "<br />\n\n";
                    return false;
                }
              
                $this->shmId = $shm;
                return true;
                break;
                /**
                * Pour créer
                * un bloc
                * s'il n'existe pas,
                * ou l'ouvrir
                * en lecture/écriture
                * s'il existe.
                **/
            case "c" :
                /**
                * On vérifie
                * si le SHM
                * existe.
                **/
                $shm = $this->wrapper_shmop_open($this->shmKey, "w", 0777, $this->shmLimitBlockSize[$this->shmKey]);
                /**
                * Le SHM existe.
                *
                * On ne peut
                * l'effacer
                * puis le recréer
                * que si le sémaaphore
                * est libre.
                **/
                if($shm !== false)
                {
                    /**
                    * Pour le BEGIN_WRITE().
                    **/
                    $this->shmId = $shm;
                    $this->BEGIN_WRITE();
                    /**
                    * On update
                    * si besoin
                    * les paramètres
                    * d'allocation
                    * mémoire.
                    **/
                    if($this->ALLOCATE($size))
                    {
                        if($this->wrapper_shmop_delete($shm) == false)
                        {
                            $this->END_WRITE();
                            $this->shmId = false;
                            return false;
                        }
                        $this->wrapper_shmop_close($shm);
                        $this->shmId = false;
                        if(($shm = $this->wrapper_shmop_open($this->shmKey, "n", 0777, $this->shmLimitBlockSize[$this->shmKey])) === false)
                        {
                            echo "\t\t" . 'Erreur création : Le SHM existait déjà.' . "<br />\n\n";
                            return false;
                        }
                        $this->shmId = $shm;
                        $this->END_WRITE();
                    }
                    else
                    {
                        $this->END_WRITE();
                    }
                }
                /**
                * Le SHM n'existe pas,
                * on peut
                * mettre à jour
                * sa dimension.
                **/
                else
                {
                    /**
                    * On update
                    * si besoin
                    * les paramètres
                    * d'allocation
                    * mémoire.
                    **/
                    $this->ALLOCATE($size);
                    if(($shm = $this->wrapper_shmop_open($this->shmKey, "n", 0777, $this->shmLimitBlockSize[$this->shmKey])) === false)
                    {
                        echo "\t\t" . 'Erreur création : Le SHM existe déjà.' . "<br />\n\n";
                        return false;
                    }
                    $this->shmId = $shm;
                }
              
                return true;
                break;
            default :
                            throw new RuntimeException("Paramètre SHM faux = " . $this->shmFlags);
                            return false;
                            break;
                    }
            return true;
        }
        private function ALLOCATE(int $size)
        {
            $BlockSize = $this->shmOffsetEnreg[$this->shmKey] + $size + 1;
            if(($this->shmBlockSize[$this->shmKey] < $BlockSize)||
                ($this->shmLimitBlockSize[$this->shmKey] < (2048 * ceil($BlockSize[$this->shmKey] / 2048.0))))
            {
                $this->shmBlockSize[$this->shmKey] = $this->shmOffsetEnreg[$this->shmKey] + $size + 1;
                /**
                * Surplus
                * pour dépassements[$this->shmKey]
                * peu fréquents.
                **/
                $this->shmLimitBlockSize[$this->shmKey] = 2048 * ceil($this->shmBlockSize[$this->shmKey] / 2048.0);
                return true;
            }
            return false;
        }
        protected function EXIST()
        {
            /**
            * SHM existe.
            **/
            if($this->OPEN("a", 0777, 0) !== false)
            {
                $this->wrapper_shmop_close($this->shmId);
                return true;
            }
            return false;
        }
        protected function READ(bool $block = false)
        {
            if($this->OPEN("w", 0, 0) === false)
            {
                echo "\t\t" . 'OPEN("w", 0, ' . 0 . ') = false' . "<br />\n\n";
                return false;
            }
            if($block)
            {
                $this->BEGIN_WRITE();
            }
            else
            {
                $this->BEGIN_READ();
            }
            $len = $this->wrapper_shmop_size($this->shmId) - $this->shmOffsetEnreg[$this->shmKey];
            $enreg = $this->wrapper_shmop_read($this->shmId, $this->shmOffsetEnreg[$this->shmKey], $len);
            if(strlen($enreg) != $len)
            {
                echo "\t\t\t" . 'TAILLE ENREG LU = ' . strlen($enreg) . ' <> TAILLE SHMOP = ' . $len . "<br /><br />\n";
                if(!$block)
                {
                    $this->END_READ();
                }
                else
                {
                    $this->END_WRITE();
                }
                $this->wrapper_shmop_close($this->shmId);
                return false;
            }
            if(!$block)
            {
                $this->END_READ($this->shmId);
                $this->wrapper_shmop_close($this->shmId);
            }
    //        $this->wrapper_shmop_close($this->shmId);
          
    //        echo "\t\t" . 'DATA READ = ' . $enreg . "<br /><br />\n";
            return $this->SHMOP_INFLATE($enreg);
        }
        protected function WRITE(string $data, bool $block = false)
        {
            $str = $this->SHMOP_DEFLATE($data);
            $size = strlen($str) + 1024;
    //        echo "\t\t" . 'DATA WRITE = ' . $str . "<br /><br />\n";
    //        echo "\t\t" . 'SIZE = ' . $size . "<br /><br />\n";
            /**
            if($size < $this->shmLimitBlockSize[$this->shmKey])
            {
                $size = $this->shmLimitBlockSize[$this->shmKey];
            }
            **/
            if($this->OPEN("c", 0777, $size) === false)
            {
                echo "\t\t" . 'OPEN("c", 0777, ' . $size . ') = false' . "<br />\n\n";
                return false;
            }
            /**
            * Si true,
            * sémaphore déjà posé
            * en écriture
            * par le READ().
            **/
            if(!$block)
            {
                $this->BEGIN_WRITE();
            }
            if(strlen($str) < 1)
            {
                $this->END_WRITE();
                $this->wrapper_shmop_close($this->shmId);
                echo "\t\t\tDATASIZE < 1.<br /><br />\n";
                return false;
            }
            // Write Data
            $this->wrapper_shmop_write($this->shmId, $str, $this->shmOffsetEnreg[$this->shmKey]);
            $this->END_WRITE();
            $this->wrapper_shmop_close($this->shmId);
            return true;
        }
        protected function APPEND(string $data)
        {
            if($this->OPEN("w", 0777, 0) === false)
            {
                return false;
            }
            $enreg = $this->READ(true);
            if($enreg === false)
            {
                $this->END_WRITE();
                return false;
            }
            $str = $this->SHMOP_DEFLATE($enreg) . $data;
            $res = $this->WRITE($str , true);
            $this->wrapper_shmop_close($this->shmId);
            return $res;
        }
        protected function RELEASE_LOCK()
        {
            if($this->OPEN("w", 0777, 0) === false)
            {
                return false;
            }
            $this->END_WRITE();
            $this->wrapper_shmop_close($this->shmId);
            return true;
        }
        protected function SIZE()
        {
            if($this->OPEN("a", 0777, 0) === false)
            {
                return false;
            }
            $res = $this->wrapper_shmop_size($this->shmId);
            $this->wrapper_shmop_close($this->shmId);
            return $res;
        }
    }
    ?>
    
    
    
     
  83. spout
    spout WRInaute accro
    Inscrit:
    14 Mai 2003
    Messages:
    8 733
    J'aime reçus:
    233
    [​IMG]
     
    Furtif apprécie ceci.
  84. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour Spout

    Voici l'algorithme Lecteur/Rédacteur sur lequel je m'arrache les cheveux.

    L'algo est à gauche, à droite c'est une traduction visible.

    P() et V() sont les acquire et release des mutex.

    Il me semble que le else terminal des fonctions : "Commencer_Lire" et "Finir_Ecrire" devrait bloquer dans certain cas, car le mutex semWait de début de fonction n'est jamais désactivé.

    Je n'arrive pas à "faire tourner l'algorithme à la main".

    $okw_semNbWait et $okr_semNbWait sont théoriquement les nombres des rédacteurs et lecteurs, du moins les nombres d'occurences des FIFO.

    L'algorithme provient de l'url :
    www.montefiore.ulg.ac.be/~pw/cours/psfiles/struct-cours8.pdf


    Merci beaucoup de votre aide.

    Amicalement et respectueusement.



    Code:
    
    
        /*********************************************************************/
            /************************/
            /*   Commencer_Lire    */
            /************************/
            /*                    *
            * P(semWait)                           *    Pose Mutex        <--
            * if (($shm_writing == true)||        *    IF ((Rédacteur == true)      |
            * ($okw_semNbWait > 0))          *    OU (FIFO Rédacteur > 0))  |
            * { V(semWait)                           *     => Enlève Mutex        <--
            *   P($okr_semWait)                 *    ET  Pose SEM Lecteur
            * }                    *
            * $shm_readers++;            *    Nbre Lecteurs++;
            * if($okr_semNbWait > 0)        *    (FIFO Lecteur > 0)
            *   V($okr_semWait)            *    => Enlève SEM Lecteur
            * else V(semWait)            *    ELSE Enlève Mutex
            **/                    *
        /*********************************************************************/
            /************************/
            /*    Finir_Lire    */
            /************************/
            /**                    *
            * P(semWait)                *    Pose Mutex
            * $shm_readers--;            *    Nbre Lecteurs--;
            * if (($shm_readers == 0)&&        *    IF ((Nbre Lecteurs == 0)
            * ($okw_semNbWait > 0))        *    ET ( FIFO Rédacteurs > 0))
            *   V($okw_semWait)            *    Enlève SEM Rédacteur
            * else                    *    SINON
            * V(semWait)                *    Enlève Mutex
            **/                    *
        /*********************************************************************/
            /************************/
            /*   Commencer_Ecrire    */
            /************************/
         
            /**                    *
            * P(semWait)                *    Pose Mutex
            * if (($shm_readers != 0)||        *    IF ((Nbre Lecteurs != 0)
            * ($shm_writing))            *    OU (Rédacteur == true))
            * { V(semWait)                *    => Enlève Mutex
            *   P($okw_semWait)            *    ET  Pose SEM Rédacteur
            * }                    *
            * $shm_writing = true            *    Rédacteur = true
            * V(semWait)                *    Enlève Mutex
            **/                    *
        /*********************************************************************/
            /************************/
            /*   Finir_Ecrire    */
            /************************/
            /**                    *
            * P(semWait)                *    Pose Mutex
            * $shm_writing = false;        *    Rédacteur = false
            * if($okr_semNbWait > 0)        *    if (FIFO Lecteur > 0)
            *   V($okr_semWait)            *    => Enlève SEM Lecteur
            * else                    *    SINON
            * if($okw_semNbWait > 0))        *    IF (FIFO Rédacteur > 0)
            *   V($okw_semWait)            *    Enlève SEM Rédacteur
            * else V(semWait)            *    SINON Enlève Mutex
            **/                    *
    
    
    
     
  85. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour

    Dans Wikipedia il y a l'indication d'utilisation de moniteurs informatiques pour la synchronisation de processus.

    Voici ci-dessous le code de Wikipedia mis en PHP.

    Pourriez-vous m'indiquer des urls sur le sujet de la théorie et des applications des moniteurs ?

    Merci beaucoup.



    PHP:

    <?php
     
    class EchangeMessage {
        private 
    $l = array();
        function 
    __construct()
        {
        }
        public function 
    enfiler($o) {
            
    $l[count($l)] = $o;
            if(
    count($l) == 1)
            {
                try {
                    
    sem_release($id);
                } catch (
    Exception $e) {};
            }
        }
        public function 
    defiler() {
            if(
    count($l)==0)
            {
                try {
                    
    sem_acquire($id);
                } catch (
    Exception $e){}
            }
            
    $o $l[0];
            
    array_shift($l);
            return 
    $o;
        }
    }
    ?>




     
  86. passion
    passion WRInaute accro
    Inscrit:
    6 Janvier 2006
    Messages:
    3 514
    J'aime reçus:
    85
    Allez prochaine étape, je craque l'algo de google ! :p
     
  87. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour Monsieur

    Voici ci-dessous new_SHMOP.php mon implémentation du deuxième ( pas mon dernier message ) algorithme "Lecteur/Rédacteur" avec l'interface SHMOP.

    J'ai testé à l'instant le cache MySQL avec 4 requêtes faciles.

    Premier coup çà bloque à la fin du script.

    Deuxième coup çà marche, les requêtes ont l'air d'être cachées.

    Le blocage avant est probablement du à la complexité de mysq_cache.php , le script contenant le code du cache.

    Sur le plan théorique, j'ai fait "tourner l'algorithme à la main" ( dans ma tête ), et normalement il ne devrait pas y avoir de blocages.

    Cependant merci pour vos avis.

    Amicalement.


    PHP:

    <?php
    class SHMOP
    {
        
    /********************************/
        /*    VARIABLES MUTEX        */
        /********************************/
        /*    3 SEMAPHORES        */
        /********************************/
        /*         CLES        */
        /********************************/
        
    private $shmWaitKey    null;        // mutex principal.
        
    private $okr_shmWaitKey    null;
        private 
    $okw_shmWaitKey    null;
        
    /********************************/
        /*        SEM_ID        */
        /********************************/
        
    private $semWait    = array();
        private 
    $okr_semWait    = array();
        private 
    $okw_semWait    = array();
        
    /********************************/
        /*  SHARED VAR ( PSEUDO FIFO )    */
        /********************************/
        
    private $okr_semNbWait    = array();
        private 
    $okw_semNbWait    = array();
       
        
    /********************************/
        /*   NBRE LECTEURS/REDACTEURS    */
        /********************************/
        /*      ( SHARED VAR )    */
        /********************************/
        
    private $shm_readers    = array();
        private 
    $shm_writing    = array();
        
    /********************************/
        /*       RECORD OFFSET    */
        /********************************/
        
    private $shmOffsetEnreg        = array();
        private 
    $shmOkrOffset        null;
        private 
    $shmOkwOffset        null;
        private 
    $shm_readersOffset    null;
        private 
    $shm_writingOffset    null;
        
    /********************************/
        /*      RECORD LENGTH        */
        /********************************/
        
    private $shmOkrLength        null;
        private 
    $shmOkwLength        null;
        private 
    $shm_readersLength    null;
        private 
    $shm_writingLength    null;
        
    /********************************/
        /*    VARIABLES SHMOP        */
        /********************************/
        
    private $shmId            = array();
        private 
    $shmMode        = array();
        private 
    $shmFlags        = array();
        private 
    $shmBlockSize        = array();
        private 
    $shmLimitBlockSize    = array();
        
    /**
        * C'est un singleton
        * par clés $this->shmKey.
        **/
        
    protected static $instance    = array(); // Instance de la classe.
        
    protected function __clone() { } // Méthode de clonage en privé.
        
    public static function getInstance(int $key)
        {
            
    /**   
            * Si on n'a pas 
            * encore instancié 
            * notre classe
            * pour cette $this->shmKey.
            **/
            
    if (!isset(self::$instance[$key])) 
            {
                
    self::$instance[$key] = new  self($key); // On s'instancie nous-mêmes. :)
            
    }
            return 
    self::$instance[$key];
        }
        protected function 
    __construct(int $key)
        {
            
    $this->shmKey $key;
            
    $this->shmMode[$this->shmKey] = 0;
            
    $this->shmFlags[$this->shmKey] = "a";
            
    $this->shmWaitKey[$this->shmKey]    = $this->shmKey 1000;
            
    $this->okr_shmWaitKey[$this->shmKey]    = $this->shmKey 2000;
            
    $this->okw_shmWaitKey[$this->shmKey]    = $this->shmKey 3000;
            
    $size 1024;
            
    // Offset
            
    $this->shmOkrOffset        0;    // Offset FIFO Lecteurs.
            
    $this->shmOkwOffset        64;    // Offset FIFO Rédacteurs.
            
    $this->shm_readersOffset    128;    // Offset Nbre Lecteurs.
            
    $this->shm_writingOffset    192;    // Offset Nbre Rédacteurs.
           
            
    $this->shmOffsetEnreg        256;    // Offset Enregistrement.
            // Length
            
    $this->shmOkrLength        $this->shmOkwOffset $this->shmOkrOffset;        // FIFO Lecteurs
            
    $this->shmOkwLength        $this->shm_readersOffset $this->shmOkwOffset;    // FIFO Rédacteurs
               
            
    $this->shm_readersLength    $this->shm_writingOffset $this->shm_readersOffset;    // Nbre Lecteurs
            
    $this->shm_writingLength    $this->shmOffsetEnreg $this->shm_writingOffset;    // Nbre Rédacteurs
           
            
    $this->shmBlockSize[$this->shmKey] = $this->shmOffsetEnreg[$this->shmKey] + $size 1;
            
    /**
            * Longueur totale shared memory.
            **/
            
    $this->shmLimitBlockSize[$this->shmKey] = 2048 ceil($this->shmBlockSize[$this->shmKey] / 2048.0);
            
    error_reporting(true);
            return 
    $this;
        }
        function 
    __destruct()
        {
            
    /**
            sem_remove($this->okr_semWait[$this->shmKey]);
            sem_remove($this->semWait[$this->shmKey]);
            sem_remove($this->okw_semWait[$this->shmKey]);
            **/
            
    self::$instance[$this->shmKey] = null;
            return 
    true;
        }
        private function 
    INIT_MUTEX()
        {
            
    /************************/
            /* INSTANCIATION MUTEX    */
            /************************/
            
    if(($this->semWait[$this->shmKey] = sem_get($this->shmWaitKey[$this->shmKey])) === false)        // ID Mutex
                
    return false;
            if((
    $this->okr_semWait[$this->shmKey] = sem_get($this->okr_shmWaitKey[$this->shmKey])) === false)    // ID SEM Lecteur
                
    return false;
            if((
    $this->okw_semWait[$this->shmKey] = sem_get($this->okw_shmWaitKey[$this->shmKey])) === false)    // ID SEM Rédacteur
                
    return false;
            
    /************************/
            /*  INIIALISATION VAR    */
            /************************/
       
            /**
            * Init à zéro
            * de $this->shm_readers.
            **/
            
    if($this->wrapper_shmop_write($this->shmId[$this->shmKey], $this->SHMOP_DEFLATE("0"), $this->shm_readersOffset) === false)    // $readers = 0.
                
    return false;
            
    /**
            * Init à false/zéro
            * de $this->shm_writing.
            **/
            
    if($this->wrapper_shmop_write($this->shmId[$this->shmKey], $this->SHMOP_DEFLATE("0"), $this->shm_writingOffset) === false)    // $writing = false.
                
    return false;
            
    /**
            * Init à zéro
            * de $this->okr_semNbWait.
            **/
            
    if($this->wrapper_shmop_write($this->shmId[$this->shmKey], $this->SHMOP_DEFLATE("0"), $this->shmOkrOffset) === false)    // FIFO Lecteur vide;
                
    return false;
            
    /**
            * Init à zéro
            * de $this->okw_semNbWait.
            **/
            
    if($this->wrapper_shmop_write($this->shmId[$this->shmKey], $this->SHMOP_DEFLATE("0"), $this->shmOkwOffset) === false)    // FIFO Rédacteur vide.
                
    return false;
            return 
    true;
        }
        private function 
    RELEASE_MUTEX()
        {
            if(
    is_resource($this->okr_semWait[$this->shmKey]))
            {
                
    sem_release($this->okr_semWait[$this->shmKey]);
                
    sem_remove($this->okr_semWait[$this->shmKey]);
            }
            if(
    is_resource($this->okw_semWait[$this->shmKey]))
            {
                
    sem_release($this->okw_semWait[$this->shmKey]);
                
    sem_remove($this->okw_semWait[$this->shmKey]);
            }
            if(
    is_resource($this->semWait[$this->shmKey]))
            {
                
    sem_release($this->semWait[$this->shmKey]);
                
    sem_remove($this->semWait[$this->shmKey]);
            }
            return 
    true;
        }
        private function 
    BEGIN_READ()
        {
            
    /**
            P(M_Lect)
                Lect++
            si Lect==1 alors
                P(_okw_Mutex)
            FIN SI
            V(M_Lect)
            **/
            /**
            * P(semWait)
            * if (($shm_writing == true)||
            * ($okw_semNbWait > 0))
            * { V(semWait)
            *   P($okr_semWait)
            * }
            * $shm_readers++;
            * if($okr_semNbWait > 0)
            *   V($okr_semWait)
            * else V(semWait)
            **/
            /************************/
            /*   Commencer_Lire    */
            /************************/
            
    if((!is_resource($this->semWait[$this->shmKey]))
                &&(!
    is_resource($this->okr_semWait[$this->shmKey]))
                &&(!
    is_resource($this->okw_semWait[$this->shmKey])))
                
    $this->INIT_MUTEX();
            
    // SET THE MUTEX.
            
    sem_acquire($this->semWait[$this->shmKey]);
            
    // IF((WRITING == true)||(FIFO Rédacteur > 0))
            
    if(($this->SHMOP_INFLATE($this->wrapper_shmop_read($this->shmId[$this->shmKey], $this->shm_writingOffset$this->shm_writingLength)) == "1")||((int)$this->SHMOP_INFLATE($this->wrapper_shmop_read($this->shmId[$this->shmKey], $this->shmOkwOffset$this->shmOkwLength)) > 0))
            {
                
    // RELEASE THE MUTEX.
                
    sem_release($this->semWait[$this->shmKey]);
                
    // add FIFO Lecteurs
                
    if($this->wrapper_shmop_write($this->shmId[$this->shmKey], $this->SHMOP_DEFLATE((string)((int)$this->SHMOP_INFLATE($this->wrapper_shmop_read($this->shmId[$this->shmKey], $this->shmOkrOffset$this->shmOkrLength)) + 1)), $this->shmOkrOffset) === false)
                {
                    
    $this->RELEASE_MUTEX();
                    return 
    false;
                }
                
    // RELEASE THE Lecteurs SEM.
                
    sem_acquire($this->okr_semWait[$this->shmKey]);
            }
            
    // INCREMENT READERS.
            
    if($this->wrapper_shmop_write($this->shmId[$this->shmKey], $this->SHMOP_DEFLATE((string)((int)$this->SHMOP_INFLATE($this->wrapper_shmop_read($this->shmId[$this->shmKey], $this->shm_readersOffset$this->shm_readersLength)) + 1)), $this->shm_readersOffset) === false)
            {
                
    $this->RELEASE_MUTEX();
                return 
    false;
            }
            
    // IF(FIFO Lecteurs > 0)
            
    if((int)$this->SHMOP_INFLATE($this->wrapper_shmop_read($this->shmId[$this->shmKey], $this->shmOkrOffset$this->shmOkrLength)) > 0)
            {
                
    // DECREMENT FIFO Lecteurs.
                
    if($this->wrapper_shmop_write($this->shmId[$this->shmKey], $this->SHMOP_DEFLATE((string)((int)$this->SHMOP_INFLATE($this->wrapper_shmop_read($this->shmId[$this->shmKey], $this->shmOkrOffset$this->shm_readersLength)) - 1)), $this->shmOkrOffset) === false)
                {
                    
    $this->RELEASE_MUTEX();
                    return 
    false;
                }
                
    // RELEASE THE Lecteurs SEM.
                
    sem_release($this->okr_semWait[$this->shmKey]);
            }
            else
                
    // RELEASE THE MUTEX.
                
    sem_release($this->semWait[$this->shmKey]);
            return 
    true;
        }
        private function 
    END_READ()
        {
            
    /**
            P(M_Lect)
            Lect--
            SI Lect==0 ALORS
            V(_okw_Mutex)
            FIN SI
            V(M_Lect)
            **/
            /**
            * P(semWait)
            * $shm_readers--;
            * if (($shm_readers == 0)&&
            * ($okw_semNbWait > 0))
            *   V($okw_semWait)
            * else
            * V(semWait)
            **/
            /************************/
            /*    Finir_Lire    */
            /************************/
            // SET THE MUTEX.
            
    sem_acquire($this->semWait[$this->shmKey]);
            
    // DECREMENT READERS.
            
    if($this->wrapper_shmop_write($this->shmId[$this->shmKey], $this->SHMOP_DEFLATE((string)((int)$this->SHMOP_INFLATE($this->wrapper_shmop_read($this->shmId[$this->shmKey], $this->shm_readersOffset$this->shm_readersLength)) - 1)), $this->shm_readersOffset) === false)
            {
                
    $this->RELEASE_MUTEX();
                return 
    false;
            }
            
    // IF((READERS == 0)&&(FIFO Rédacteur > 0))
            
    if(((int)$this->SHMOP_INFLATE($this->wrapper_shmop_read($this->shmId[$this->shmKey], $this->shm_readersOffset$this->shm_readersLength)) == 0)&&((int)$this->SHMOP_INFLATE($this->wrapper_shmop_read($this->shmId[$this->shmKey], $this->shmOkwOffset$this->shmOkwLength)) > 0))
            {
                
    // DECREMENT FIFO Rédacteurs.
                
    if($this->wrapper_shmop_write($this->shmId[$this->shmKey], $this->SHMOP_DEFLATE((string)((int)$this->SHMOP_INFLATE($this->wrapper_shmop_read($this->shmId[$this->shmKey], $this->shm_OkwOffset$this->shm_OkwLength)) - 1)), $this->shm_OkwOffset) === false)
                {
                    
    $this->RELEASE_MUTEX();
                    return 
    false;
                }
                
    // RELEASE THE Rédacteurs SEM.
                
    sem_release($this->okw_semWait[$this->shmKey]);
            }
            else
                
    // RELEASE THE MUTEX.
                
    sem_release($this->semWait[$this->shmKey]);
            return 
    true;
        }
        private function 
    BEGIN_WRITE()
        {
            
    /**
            P(M__okw_Mutex)
            P(_okw_Mutex)
            **/
            /**
            * P(semWait)
            * if (($shm_readers != 0)||
            * ($shm_writing))
            * { V(semWait)
            *   P($okw_semWait)
            * }
            * $shm_writing = true
            * V(semWait)
            **/
            /************************/
            /*   Commencer_Ecrire    */
            /************************/
            
    if((!is_resource($this->semWait[$this->shmKey]))
                &&(!
    is_resource($this->okr_semWait[$this->shmKey]))
                &&(!
    is_resource($this->okw_semWait[$this->shmKey])))
                
    $this->INIT_MUTEX();
            
    // SET THE MUTEX.
            
    sem_acquire($this->semWait[$this->shmKey]);
            
    // IF((READERS != 0)||(WRITING == true))
            
    if(((int)$this->SHMOP_INFLATE($this->wrapper_shmop_read($this->shmId[$this->shmKey], $this->shm_readersOffset$this->shm_readersLength)) != 0)||((int)$this->SHMOP_INFLATE($this->wrapper_shmop_read($this->shmId[$this->shmKey], $this->shm_writingOffset$this->shm_writingLength)) == 1))
            {
                
    // RELEASE THE MUTEX.
                
    sem_release($this->semWait[$this->shmKey]);
                
    // INCREMENT FIFO Rédacteurs.
                
    if($this->wrapper_shmop_write($this->shmId[$this->shmKey], $this->SHMOP_DEFLATE((string)((int)$this->SHMOP_INFLATE($this->wrapper_shmop_read($this->shmId[$this->shmKey], $this->shm_OkwOffset$this->shm_OkwLength)) + 1)), $this->shm_OkwOffset) === false)
                {
                    
    $this->RELEASE_MUTEX();
                    return 
    false;
                }
                
    // SET THE Rédacteurs SEM.
                
    sem_acquire($this->okw_semWait[$this->shmKey]);
            }
            
    // WRITING = true.
            
    if($this->wrapper_shmop_write($this->shmId[$this->shmKey], $this->SHMOP_DEFLATE("1"),$this->shm_writingOffset) === false)
            {
                
    $this->RELEASE_MUTEX();
                return 
    false;
            }
            
    // RELEASE THE MUTEX.
            
    sem_release($this->semWait[$this->shmKey]);
            return 
    true;
        }
        protected function 
    END_WRITE()
        {
            
    /**
            V(_okw_Mutex)
            V(M__okw_Mutex)
            **/
            /**
            * P(semWait)
            * $shm_writing = false;
            * if($okr_semNbWait > 0))
            *   V($okr_semWait)
            * else
            * if($okw_semNbWait > 0))
            *   V($okw_semWait)
            * else V(semWait)
            **/
            /************************/
            /*   Finir_Ecrire    */
            /************************/
            // SET THE MUTEX.
            
    sem_acquire($this->semWait[$this->shmKey]);
            
    // WRITING = false.
            
    if($this->wrapper_shmop_write($this->shmId[$this->shmKey], $this->SHMOP_DEFLATE("0"),$this->shm_writingOffset) === false)
            {
                
    $this->RELEASE_MUTEX();
                return 
    false;
            }
            
    // IF(FIFO Lecteur > 0)
            
    if((int)$this->SHMOP_INFLATE($this->wrapper_shmop_read($this->shmId[$this->shmKey], $this->shmOkrOffset$this->shmOkrLength)) > 0)
            {
                
    // DECREMENT FIFO Lecteurs.
                
    if($this->wrapper_shmop_write($this->shmId[$this->shmKey], $this->SHMOP_DEFLATE((string)((int)$this->SHMOP_INFLATE($this->wrapper_shmop_read($this->shmId[$this->shmKey], $this->shm_OkwOffset$this->shm_OkwLength)) + 1)), $this->shm_OkwOffset) === false)
                {
                    
    $this->RELEASE_MUTEX();
                    return 
    false;
                }
                
    sem_release($this->okr_semWait[$this->shmKey]);
            }
            
    // IF(FIFO Rédacteur > 0)
            
    elseif((int)$this->SHMOP_INFLATE($this->wrapper_shmop_read($this->shmId[$this->shmKey], $this->shmOkwOffset$this->shmOkwLength)) > 0)
            {
                
    // DECREMENT FIFO Rédacteurs.
                
    if($this->wrapper_shmop_write($this->shmId[$this->shmKey], $this->SHMOP_DEFLATE((string)((int)$this->SHMOP_INFLATE($this->wrapper_shmop_read($this->shmId[$this->shmKey], $this->shm_OkwOffset$this->shm_OkwLength)) + 1)), $this->shm_OkwOffset) === false)
                {
                    
    $this->RELEASE_MUTEX();
                    return 
    false;
                }
                
    sem_release($this->okw_semWait[$this->shmKey]);
            }
            else
            {
                
    // RELEASE THE MUTEX.
                
    sem_release($this->semWait[$this->shmKey]);
            }
            return 
    true;
        }
            protected function 
    millisecond()
            {
                    return 
    floor(microtime(true)/0.001 0.5);
            }
        
    /**
        * Pour les
        * ID de SHMOP.
        **/
            
    private function SHM_ID($str)
            {
            return 
    '"' $str '"';
            }
        
    /**
        * Format type
        * string conpressée
        * après linearisation.
        **/
        
    private function SHMOP_DEFLATE(string $value)
        {
            
    /**
            * On ajoute un '\0'.
            **/
            
    return $this->str_to_nts($value);
            
    /**
            * VALUE => COMPRESS => BASE64_ENCODE => STR
            **/
            
    $str base64_encode($value);
            
    $str =  base64_encode(gzcompress($value));
        }
        
    /**
        * Format type
        * string déconpressée
        * et délinéarisée.
        **/
        
    private function SHMOP_INFLATE($value)
        {
            
    /**
            * On enlève le '\0'.
            **/
            
    $data =  $this->str_from_mem($value);
            return 
    $data;
            
    /*
            * STR => BASE64_DECODE => UNCOMPRESS.
            */
            
    return base64_decode($data);
            return 
    gzuncompress(base64_decode($data));
        }
        private function 
    str_from_mem(string &$value) {
            
    $i strpos($valuechr(0));
            if (
    $i !== false) {
                return 
    substr($value0$i);
            }
            return 
    $value;
        }
        private function 
    str_to_nts(string $value) {
            return 
    $value.chr(0);
        }
        private function 
    wrapper_shmop_open(int $keystring $flagsint $perm 0777int $size 0)
        {
            
    /**
            * USER root,
            * specific threatment
            * for opening
            * the SHM as nginx.
            **/
            
    if(posix_geteuid() == 0)
            {
                switch(
    $flags) {
                case 
    "n" :
                case 
    "c" :
                    
    /**
                    * Creation
                    * comme user
                    * nginx.
                    **/
                    
    exec("sudo -u nginx php -r 'shmop_open(" $key ", \"" $flags "\", " $perm ", " $size ");'"); //Create Shared Memory segment as USER nginx
                    
    $flags "w";
                    break;
                default :
                    break;
                }
            }
            return @
    shmop_open($key$flags$perm$size);
        }
        private function 
    wrapper_shmop_delete($shmId)
        {
            
    $result shmop_delete($shmId);
            echo 
    "RESULTAT DELETE = " $result "<br />\n\n";
            return 
    $result;
        }
        private function 
    wrapper_shmop_size($shmId)
        {
            return 
    shmop_size($shmId);
        }
        private function 
    wrapper_shmop_close($shmId)
        {
            return 
    shmop_close($shmId);
        }
        private function 
    wrapper_shmop_read($shmId$offset$tmp_count)
        {
            return 
    shmop_read($shmId$offset$tmp_count);
        }
        private function 
    wrapper_shmop_write($shmId$value$offset)
        {
            return 
    shmop_write($shmId$value$offset);
        }
        private function 
    OPEN(string $flagsint $modeint $size)
        {
            
    $this->shmMode[$this->shmKey] = $mode;
            
    $this->shmFlags[$this->shmKey] = $flags;
            
    $this->shmId[$this->shmKey] = false;
            if(
    in_array($this->shmFlags[$this->shmKey], array("a""w")))
            {
                if(
    $size == 0)
                {
                    
    $shm $this->wrapper_shmop_open($this->shmKey$this->shmFlags[$this->shmKey], 07770);
                }
                else
                {
                    
    $shm $this->wrapper_shmop_open($this->shmKey$this->shmFlags[$this->shmKey], 0777$this->shmLimitBlockSize[$this->shmKey]);
                }
                if(
    $shm === false)
                {
                    return 
    false;
                }
                
    $this->shmId[$this->shmKey] = $shm;
                return 
    true;
            }
            switch (
    $this->shmFlags[$this->shmKey]) {
            case 
    "n" :
                
    /**
                * On update
                * si besoin
                * les paramètres
                * d'allocation
                * mémoire.
                **/
                
    $this->ALLOCATE($size);
                
    $shm $this->wrapper_shmop_open($this->shmKey$this->shmFlags[$this->shmKey], 0777$this->shmLimitBlockSize[$this->shmKey]);
                
    /**
                * Le SHM
                * ne doit
                * pas exister.
                **/
                
    if($shm === false)
                {
                    echo 
    "\t\t" 'Erreur création : Le SHM existe déjà.' "<br />\n\n";
                    return 
    false;
                }
               
                
    $this->shmId[$this->shmKey] = $shm;
                return 
    true;
                break;
                
    /**
                * Pour créer
                * un bloc
                * s'il n'existe pas,
                * ou l'ouvrir
                * en lecture/écriture
                * s'il existe.
                **/
            
    case "c" :
                
    /**
                * On vérifie
                * si le SHM
                * existe.
                **/
                
    $shm $this->wrapper_shmop_open($this->shmKey"w"0777$this->shmLimitBlockSize[$this->shmKey]);
                
    /**
                * Le SHM existe.
                *
                * On ne peut
                * l'effacer
                * puis le recréer
                * que si le sémaaphore
                * est libre.
                **/
                
    if($shm !== false)
                {
                    
    /**
                    * Pour le BEGIN_WRITE().
                    **/
                    
    $this->shmId[$this->shmKey] = $shm;
                    
    $this->BEGIN_WRITE();
                    
    /**
                    * On update
                    * si besoin
                    * les paramètres
                    * d'allocation
                    * mémoire.
                    **/
                    
    if($this->ALLOCATE($size))
                    {
                        if(
    $this->wrapper_shmop_delete($shm) == false)
                        {
                            
    $this->END_WRITE();
                            
    $this->shmId[$this->shmKey] = false;
                            return 
    false;
                        }
                        
    $this->wrapper_shmop_close($shm);
                        
    $this->shmId[$this->shmKey] = false;
                        if((
    $shm $this->wrapper_shmop_open($this->shmKey"n"0777$this->shmLimitBlockSize[$this->shmKey])) === false)
                        {
                            echo 
    "\t\t" 'Erreur création : Le SHM existait déjà.' "<br />\n\n";
                            return 
    false;
                        }
                        
    $this->shmId[$this->shmKey] = $shm;
                        
    $this->END_WRITE();
                    }
                    else
                    {
                        
    $this->END_WRITE();
                    }
                }
                
    /**
                * Le SHM n'existe pas,
                * on peut
                * mettre à jour
                * sa dimension.
                **/
                
    else
                {
                    
    /**
                    * On update
                    * si besoin
                    * les paramètres
                    * d'allocation
                    * mémoire.
                    **/
                    
    $this->ALLOCATE($size);
                    if((
    $shm $this->wrapper_shmop_open($this->shmKey"n"0777$this->shmLimitBlockSize[$this->shmKey])) === false)
                    {
                        echo 
    "\t\t" 'Erreur création : Le SHM existe déjà.' "<br />\n\n";
                        return 
    false;
                    }
                    
    $this->shmId[$this->shmKey] = $shm;
                }
               
                return 
    true;
                break;
            default :
                            throw new 
    RuntimeException("Paramètre SHM faux = " $this->shmFlags[$this->shmKey]);
                            return 
    false;
                            break;
                    }
            return 
    true;
        }
        private function 
    ALLOCATE(int $size)
        {
            
    $BlockSize $this->shmOffsetEnreg[$this->shmKey] + $size 1;
            if((
    $this->shmBlockSize[$this->shmKey] < $BlockSize)||
                (
    $this->shmLimitBlockSize[$this->shmKey] < (2048 ceil($BlockSize[$this->shmKey] / 2048.0))))
            {
                
    $this->shmBlockSize[$this->shmKey] = $this->shmOffsetEnreg[$this->shmKey] + $size 1;
                
    /**
                * Surplus
                * pour dépassements[$this->shmKey]
                * peu fréquents.
                **/
                
    $this->shmLimitBlockSize[$this->shmKey] = 2048 ceil($this->shmBlockSize[$this->shmKey] / 2048.0);
                return 
    true;
            }
            return 
    false;
        }
        protected function 
    EXIST()
        {
            
    /**
            * SHM existe.
            **/
            
    if($this->OPEN("a"07770) !== false)
            {
                
    $this->wrapper_shmop_close($this->shmId[$this->shmKey]);
                return 
    true;
            }
            return 
    false;
        }
        protected function 
    READ(bool $block false)
        {
            if(
    $this->OPEN("w"00) === false)
            {
                echo 
    "\t\t" 'OPEN("w", 0, ' ') = false' "<br />\n\n";
                return 
    false;
            }
            
    /**
            if($block)
            {
                $this->BEGIN_WRITE();
            }
            else
            {
                $this->BEGIN_READ();
            }
            **/
            
    $this->BEGIN_READ();
            
    $len $this->wrapper_shmop_size($this->shmId[$this->shmKey]) - $this->shmOffsetEnreg[$this->shmKey];
            
    $enreg $this->wrapper_shmop_read($this->shmId[$this->shmKey], $this->shmOffsetEnreg[$this->shmKey], $len);
            if(
    strlen($enreg) != $len)
            {
                echo 
    "\t\t\t" 'TAILLE ENREG LU = ' strlen($enreg) . ' <> TAILLE SHMOP = ' $len "<br /><br />\n";
                
    /**
                if(!$block)
                {
                    $this->END_READ();
                }
                else
                {
                    $this->END_WRITE();
                }
                **/
                
    $this->END_READ();
                
    $this->wrapper_shmop_close($this->shmId[$this->shmKey]);
                return 
    false;
            }
            
    /**
            if(!$block)
            {
            **/
                
    $this->END_READ($this->shmId[$this->shmKey]);
    //        }
            
    $this->wrapper_shmop_close($this->shmId[$this->shmKey]);
            echo 
    "\t\t" 'DATA READ = ' $enreg "<br /><br />\n";
            return 
    $this->SHMOP_INFLATE($enreg);
        }
        protected function 
    WRITE(string $databool $block false)
        {
            
    $str $this->SHMOP_DEFLATE($data);
            
    $size strlen($str) + 1024;
            echo 
    "\t\t" 'DATA WRITE = ' $str "<br /><br />\n";
            echo 
    "\t\t" 'SIZE = ' $size "<br /><br />\n";
            
    /**
            if($size < $this->shmLimitBlockSize[$this->shmKey])
            {
                $size = $this->shmLimitBlockSize[$this->shmKey];
            }
            **/
            
    if($this->OPEN("c"0777$size) === false)
            {
                echo 
    "\t\t" 'OPEN("c", 0777, ' $size ') = false' "<br />\n\n";
                return 
    false;
            }
            
    /**
            if($block)
            {
                $this->END_READ();
            }
            **/
            /**
            * Si true,
            * sémaphore déjà posé
            * en écriture
            * par le READ().
            **/
            /**
            if(!$block)
            {
            **/
                
    $this->BEGIN_WRITE();
    //        }
            
    if(strlen($str) < 1)
            {
                
    $this->END_WRITE();
                
    $this->wrapper_shmop_close($this->shmId[$this->shmKey]);
                echo 
    "\t\t\tDATASIZE < 1.<br /><br />\n";
                return 
    false;
            }
            
    // Write Data
            
    $res $this->wrapper_shmop_write($this->shmId[$this->shmKey], $str$this->shmOffsetEnreg[$this->shmKey]);
            
    $this->END_WRITE();
            
    $this->wrapper_shmop_close($this->shmId[$this->shmKey]);
            return 
    $res;
        }
        
    /**
        protected function APPEND(string $data)
        {
            if($this->OPEN("w", 0777, 0) === false)
            {
                return false;
            }
            $enreg = $this->READ(true);
            if($enreg === false)
            {
                $this->END_WRITE();
                return false;
            }
            $str = $this->SHMOP_DEFLATE($enreg) . $data;
            $res = $this->WRITE($str , true);
            $this->wrapper_shmop_close($this->shmId[$this->shmKey]);
            return $res;
        }
        protected function RELEASE_LOCK()
        {
            if($this->OPEN("w", 0777, 0) === false)
            {
                return false;
            }
            $this->END_WRITE();
            $this->wrapper_shmop_close($this->shmId[$this->shmKey]);
            return true;
        }
        **/
        
    protected function SIZE()
        {
            if(
    $this->OPEN("a"07770) === false)
            {
                return 
    false;
            }
            
    $res $this->wrapper_shmop_size($this->shmId[$this->shmKey]);
            
    $this->wrapper_shmop_close($this->shmId[$this->shmKey]);
            return 
    $res;
        }
    }
    ?>


     
  88. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Rebond

    J'ai besoin d'une information au sujet des sémaphores.

    Qu'est-ce que c'est un sémaphore FIFO ?

    First-In First-Out n'est-il pas dans le concept d'un sémaphore quel que soit $max_acquire ?


    Comment implémenter un sémaphore FIFO en PHP ?

    Un sémaphore ouvert avec : sem_get($key, $max_acquire, $perm = 0666, $auto_release = 1) est-il un sémaphore FIFO si $max_acquire > 1 ?

    "Si $auto_release == 1 le sémaphore sera libéré à leur fermeture" ( sem_close ).

    Celà veut-il-dire qu'il y a sem_remove( ) dans ce cas ?

    Merci beaucoup.
     
  89. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Voilà voilà

    Je touche au but.

    Cà marche, je n'ai plus qu'à mémoriser $size ( taille paramètre de chaque bloc ) et $BlockSize ( idem ) , à chaque mise à jour de la taille des blocs.

    Je compte faire celà au début de chaque blocs.

    Les requêtes MySQL sont correctement mises en cache.

    Merci beaucoup.

    Amicalement.
     
  90. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour

    Voilà c'est fait.

    La mémoire shmop est régulée automatiquement.

    Quand le niveau de RAM occupé par les shmop_size() dépasse la moitié de 7 Mo, des enregs des blocs sont effacés, l'index est mis à jour et la RAM occupée baisse.

    Il y a 157 blocs au maximum, et les enregs sont répartis à peu près également sur les blocs par une clé de hashage en fonction de la clé de la requête MySQL à cacher.

    Cependant j'ai laissé le cache HTML ( merci à Noren ;) ), car le top m'indique souvent 100+% pour le processus mysqld.

    Merci de tester : https://www.pronostics-courses.fr

    Amicalement.
     
  91. passion
    passion WRInaute accro
    Inscrit:
    6 Janvier 2006
    Messages:
    3 514
    J'aime reçus:
    85
    Bonjour @ortolojf et bravo pour ton acharnement. Car dans ce cas, c'est une qualité. Tu t'es embarqué dans un domaine très complexe et pas forcément bien documenté.
    Merci d'avoir mis à disposition tes résultats pour la communauté.
    Je vais être hors sujet sur ce coup mais... tu sembles avoir de sérieuses compétences en dev mais ne penses-tu pas qu'il est grand temps de mettre à profit ces compétences pour faire un vrai design pour ton site ? Parce que sincèrement, AMHA, c'est vraiment pas attractif et convivial.
    Ne dénigre pas l'apparence au détriment des performances techniques.

    Tu sais sans doute qu'un internaute porte d'abord attention aux images sur un site plutôt que du texte. C'est valable pour tout le monde. La grande majorité des internautes ne prennent pas le temps de lire.
    Je pense que tu pourras le confirmer par la suite avec tes stats, ton taux de rebond devrait diminuer.

    On ne fait jamais un site pour soi mais pour les autres. Ce n'est pas si simple de se mettre à la place des utilisateurs. Il faut avoir suffisamment de recul pour changer de casquettes et ne plus penser comme le webmaster mais comme son utilisateur.

    Voilà... c'était mon observation du jour.
    Encore bravo pour ton travail. ;)
     
    #92 passion, 29 Juillet 2019
    Dernière édition: 29 Juillet 2019
  92. spout
    spout WRInaute accro
    Inscrit:
    14 Mai 2003
    Messages:
    8 733
    J'aime reçus:
    233
    @passion : Ça fait des années qu'on lui dit. Il réinvente la roue tout le temps mais pas la bonne. S'il mettait son énergie à ce que tu dis il aurait THE site de référence dans les pronos.

    [​IMG]
     
    passion apprécie ceci.
  93. passion
    passion WRInaute accro
    Inscrit:
    6 Janvier 2006
    Messages:
    3 514
    J'aime reçus:
    85
    Oui @spout lol
    J'ai pu souvent lire que @ortolojf avait du mal à entendre autre chose que ce que pourquoi il travaille. Mais bon, je suis d'une nature altruiste héhéhéhé donc bah, j'aurai fait ma BA ;)
    Mais bon, je me doute de sa réponse ;)
     
  94. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Il y a autre chose...

    Je m'apprête d'une part à corriger des erreurs dans le moteur de stats avant les courses, qui fait que des chevaux sont à zéro ( jamais couru ) avant, alors que c'est correct après les courses.

    D'autre part et conjointement, à poursuivre avec l'aide des tests déjà fait de RM Tech, et l'outil de Chrome, les améliorations SEO de mon site.

    Après celà, je ferai peut-être appel à un graphiste, mais j'ai peur de perdre la main sur mon site, et de recevoir des mauvais conseils.

    Addendum : Je vais rapidement programmer une fonction de correction des erreurs éventuelles dans les blocs, qui sont susceptibles de survenir à l'occasion d'arrêts intempestifs des scripts php

    Si l'index est endommagé aussi, je tâcherai de faire quelque chose de propre.

    Merci beaucoup pour votre aide.

    P.S Je peux si vous voulez, vous communiquer le code de ma librairie de synchronisation, et celle de mon cache, sinon mon orm maison qui l'utilise, sachant qu'avec d'autres interfaces MySQL il y aurait un gros travail d'adaptation du cache à faire.
     
    #95 ortolojf, 29 Juillet 2019
    Dernière édition: 29 Juillet 2019
  95. passion
    passion WRInaute accro
    Inscrit:
    6 Janvier 2006
    Messages:
    3 514
    J'aime reçus:
    85
    Yo ! La persévérance paye lol !
    "peut-être" est mieux que "non" !
    Voyons le verre à moitié plein ;)
     
  96. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour

    MariaDB souffre d'un défaut, c'est qu'il ne supporte pas les JOIN sur la même table.

    Par exemple :

    Code:
    
      SELECT CHEVAUX2.NUMCH, CHEVAUX2.NOMCH FROM CHEVAUX AS CHEVAUX1 LEFT JOIN CHEVAUX AS CHEVAUX2 ON CHEVAUX2.NOMCH LIKE CONCAT(CHEVAUX1.NOMCH, ':(%)') WHERE CHEVAUX1.NOMCH IN ('SIOUX', 'PLEUTRE' );
    
    
    Cà passe pas :

    Erreur : SQLSTATE[42000]: Syntax error or access violation: 1066 Not unique table/alias: ''


    A part MariaDB / MySQL, qu'est-ce qu'il y aurait comme SGDBR qui supporte les JOIN sur deux tables identiques ?

    Merci beaucoup.

    Amicalement.
     
  97. spout
    spout WRInaute accro
    Inscrit:
    14 Mai 2003
    Messages:
    8 733
    J'aime reçus:
    233
    Fait un UNION alors.
     
  98. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour Spout

    Cà marche :

    Code:
    
    SELECT CHEVAUX1.NUMCH, CHEVAUX1.NOMCH, CHEVAUX2.NUMCH, CHEVAUX2.NOMCH FROM CHEVAUX AS CHEVAUX1 LEFT JOIN CHEVAUX AS CHEVAUX2 ON CHEVAUX2.NOMCH LIKE CONCAT(CHEVAUX1.NOMCH, ':(%)') WHERE CHEVAUX1.NOMCH IN ('FOUDRE:DU:GOSIER', 'FAMOUS:STAR', 'FLAYA:DU:SAPTEL', 'FAYETTE', 'FONTAINEAUXPERLES', 'FLORE:BUISSONAY', 'FOLIE:DE:HOUELLE', 'FELINA', 'FRAISE:BLANCHE', 'FREEDOM:DU:BOULAY', 'FUTAIE:DzERPION', 'FUSEE:DU:MOUCHEL', 'FILLE:A:PAPA', 'FUSEE', 'FIBULE:DU:VIVIER', 'DELMONICA');
    
    
    Me donne tous les chevaux avec et sans nationalité.

    CHEVAUX2.NOMCH = NULL quand pas de nationalité.

    J'ai déjà mis l'add-on des alias à mon orm.

    Amicalement.
     
  99. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    2 789
    J'aime reçus:
    8
    Bonjour

    Je ne résiste pas au plaisir de vous communiquer le code de ma librairie d'accès partagé en lecture/écriture utilisant l'algorithme lecteur/rédacteur.

    Suis fatigué ce soir, à demain plus d'infos.

    Bien amicalement.

    PHP:


    <?php

    class SHMOP
    {
        const 
    SUDO '/usr/bin/sudo';
        const 
    PHP  '/usr/bin/php';
        
    /********************************/
        /*    VARIABLES MUTEX        */
        /********************************/
        /*    3 SEMAPHORES        */
        /********************************/
        /*         CLES        */
        /********************************/
        
    private $semWaitKey        = array();        // Clé mutex principal.
        
    private $semWaitKeyRead        = array();        // Sémaphore Lecture.
        
    private $semWaitKeyWrite    = array();        // Sémaphore Ecriture.
        /********************************/
        /*        SEM_ID        */
        /********************************/
        
    private $semWait    = array();
        private 
    $semWaitRead    = array();
        private 
    $semWaitWrite    = array();
        
    /********************************/
        /*  SHARED VAR ( PSEUDO FIFO )    */
        /********************************/
        
    private $shmReadVar        = array();    // Clé Variable Nbre Lecteurs.
        
    private $shmMemVar        null;        // Qté RAM  Variable Nbre Lecteurs.
        
    private $shmReadKey        = array();    // Clé Variable Nbre Lecteurs.
        
    private $shmRead        = array();    // Variable Nbre Lecteurs.
        /********************************/
        /*      RECORD LENGTH        */
        /********************************/
        
    private $shmReadersLength    null;
        
    /********************************/
        /*    VARIABLES SHM        */
        /********************************/
        
    private $shmId            = array();
        private 
    $shmMode        = array();
        private 
    $shmFlags        = array();
        private 
    $shmEnregOffset        null;
        private 
    $shmSize        null;
        private 
    $shmBlockSize        = array();
        private 
    $shmLimitBlockSize    = array();
        
    /**
        * C'est un singleton
        * par clés $this->shmKey.
        **/
        
    protected static $instance    = array(); // Instance de la classe.
        
    protected function __clone() { } // Méthode de clonage en privé.
        
    public static function getInstance(int $key)
        {
            
    /**   
            * Si on n'a pas 
            * encore instancié 
            * notre classe
            * pour cette $this->shmKey.
            **/
            
    if (!isset(self::$instance[$key])) 
            {
                
    self::$instance[$key] = new  self($key); // On s'instancie nous-mêmes. :)
            
    }
            return 
    self::$instance[$key];
        }
        protected function 
    __construct(int $key)
        {
            
    /**
            * Paramètres
            * du SHM
            * contenant
            * les data.
            **/
            
    $this->shmKey $key;
            
    $this->shmMode[$this->shmKey] = 0;
            
    $this->shmFlags[$this->shmKey] = "a";
            
    $this->shmId[$this->shmKey] = false;
            
    $this->shmEnregOffset 128;        // Offset du SHM;
            /**
            * Corriger
            * pour des clés
            * constantes.
            *
            * 3 sémaphores
            * seulement
            * pour toutes
            * les ressources
            * de synchronisation
            * SHM.
            **/
            
    $this->semWaitKey[$this->shmKey] = $this->shmKey 1000;
            
    $this->semWaitKeyRead[$this->shmKey] = $this->shmKey 2000;
            
    $this->semWaitKeyWrite[$this->shmKey] = $this->shmKey 3000;
            
    /**
            * 1 variable partagée
            * Nbre Lecteurs
            * par SHM.
            **/
            
    $this->shmReadKey[$this->shmKey] = $this->shmKey 4000;    // Clé du SHM Lect.
            
    $this->shmReadVar[$this->shmKey] = $this->shmKey 5000;    // Clé de la variable Lect.
            
    $this->semWait[$this->shmKey]        = 0;
            
    $this->semWaitRead[$this->shmKey]    = 0;
            
    $this->semWaitWrite[$this->shmKey]    = 0;
            
    $this->shmRead[$this->shmKey]        = 0;
            
    $this->shmMemVar            256;        // Qté RAM  Variable Nbre Lecteurs.
            
    $this->shmSize 1024;
            
    $this->INIT_MUTEX();
            
    $this->shmBlockSize[$this->shmKey] = $this->shmSize 1;
            
    /**
            * Longueur totale shared memory.
            **/
            
    $this->shmLimitBlockSize[$this->shmKey] = 2048 ceil($this->shmBlockSize[$this->shmKey] / 2048.0);
            
    $this->INIT_SIZE();
            
    $this->shmBlockSize[$this->shmKey] = $this->shmSize 1;
            
    /**
            * Longueur totale shared memory.
            **/
            
    $this->shmLimitBlockSize[$this->shmKey] = 2048 ceil($this->shmBlockSize[$this->shmKey] / 2048.0);
            
    error_reporting(true);
            return 
    $this;
        }
        function 
    __destruct()
        {
            
    $this->RELEASE_MUTEX();
            
    self::$instance[$this->shmKey] = null;
            return 
    true;
        }
        private function 
    INIT_SIZE()
        {
            
    $this->BEGIN_WRITE();
            
    /**
            * On vérifie
            * si le SHM
            * existe.
            **/
            
    $shm_alloc $this->wrapper_shmop_open($this->shmKey"a"0666$this->shmLimitBlockSize[$this->shmKey]);
            
    /**
            * Le SHM existe.
            **/
            
    if($shm_alloc !== false)
            {
                
    /**
                * Enreg
                * des tailles
                * brutes et
                * réelles.
                **/
                
    if(($size $this->SHM_INFLATE($this->wrapper_shmop_read($shm_alloc0$this->shmEnregOffset))) === false)
                {
                    echo 
    "\t\t" 'Erreur lecture taille SHM.' "<br />\n\n";
                    return 
    false;
                }
                
    $this->shmSize = (int)$size;
                
    $this->wrapper_shmop_close($shm_alloc);
            }
            
    $this->END_WRITE();
            return 
    true;
        }
        private function 
    INIT_MUTEX()
        {
            
    /**
            * USER root,
            * specific threatment
            * for opening
            * the SHM as nginx.
            **/
            
    if(posix_geteuid() != 0)
            {
                
    /************************/
                /* INSTANCIATION MUTEX    */
                /************************/
                
    if(!is_resource($this->semWait[$this->shmKey]))
                {
                    if((
    $this->semWait[$this->shmKey] = sem_get($this->semWaitKey[$this->shmKey], 106661)) === false)        // ID Mutex
                        
    return false;
                }
                if(!
    is_resource($this->semWaitRead[$this->shmKey]))
                {
                    if((
    $this->semWaitRead[$this->shmKey] = sem_get($this->semWaitKeyRead[$this->shmKey], 106661)) === false)    // ID SEM Lecteur
                        
    return false;
                }
                if(!
    is_resource($this->semWaitWrite[$this->shmKey]))
                {
                    if((
    $this->semWaitWrite[$this->shmKey] = sem_get($this->semWaitKeyWrite[$this->shmKey], 106661)) === false)    // ID SEM Rédacteur
                        
    return false;
                }
                if(!
    is_resource($this->shmRead[$this->shmKey]))
                {
                    if((
    $this->shmRead[$this->shmKey] = shm_attach($this->shmReadKey[$this->shmKey], $this->shmMemVar0666)) === false)    // ID Nbre Lecteurs
                        
    return false;
                }
            }
            else
            {
                
    /************************
                * INSTANCIATION MUTEX    *
                ************************/
                
    if(!is_resource($this->semWait[$this->shmKey]))
                {
                    unset(
    $cmd);
                    
    $cmd self::SUDO " -u nginx " self::PHP " -r 'unset(\$id1); \$id1 = sem_get(" $this->semWaitKey[$this->shmKey] . ", " ", " 0666 ", " "); /* echo \$id1; */'";    //Create ID Mutex as USER nginx
                    
    exec($cmd);
                    if((
    $this->semWait[$this->shmKey] = sem_get($this->semWaitKey[$this->shmKey], 106661)) === false)    //Create ID Mutex as USER nginx
                    
    {
                        return 
    false;
                    }
                }
                if(!
    is_resource($this->semWaitRead[$this->shmKey]))
                {
                    unset(
    $cmd);
                    
    $cmd self::SUDO " -u nginx " self::PHP " -r 'unset(\$id2); \$id2 = sem_get(" $this->semWaitKeyRead[$this->shmKey] . ", " ", " 0666 ", " "); /* echo \$id2; */'";    //Create ID Mutex as USER nginx
                    
    exec($cmd);
                    if((
    $this->semWaitRead[$this->shmKey] = sem_get($this->semWaitKeyRead[$this->shmKey], 106661)) === false)    //Create ID Mutex as USER nginx
                    
    {
                        return 
    false;
                    }
                }
                if(!
    is_resource($this->semWaitWrite[$this->shmKey]))
                {
                    unset(
    $cmd);
                    
    $cmd self::SUDO " -u nginx " self::PHP " -r 'unset(\$id3); \$id3 = sem_get(" $this->semWaitKeyWrite[$this->shmKey] . ", " ", " 0666 ", " "); /* echo \$id3; */ '";    //Create ID Mutex as USER nginx
                    
    exec($cmd);
                    if((
    $this->semWaitWrite[$this->shmKey] = sem_get($this->semWaitKeyWrite[$this->shmKey], 106661)) === false)    //Create ID Mutex as USER nginx
                    
    {
                        return 
    false;
                    }
                }
                if(!
    is_resource($this->shmRead[$this->shmKey]))
                {
                    unset(
    $cmd);
                    
    $cmd self::SUDO " -u nginx " self::PHP " -r 'unset(\$id4); \$id4 = shm_attach(" $this->shmReadKey[$this->shmKey] . ", " $this->shmMemVar ", " 0666 "); /* echo \$id4; */'";    //Create ID Mutex as USER nginx
                    
    exec($cmd);
                    if((
    $this->shmRead[$this->shmKey] = shm_attach($this->shmReadKey[$this->shmKey], $this->shmMemVar0666)) === false)    //Create ID Mutex as USER nginx
                    
    {
                        return 
    false;
                    }
                }
            }
            
    /************************/
            /*  INIIALISATION VAR    */
            /************************/
            /**
            * Init à zéro
            * de $this->shmRead
            * ( 1 variable Lect Par SHM ).
            **/
            
    if((!shm_has_var($this->shmRead[$this->shmKey], $this->shmReadVar[$this->shmKey]))
                &&((
    shm_put_var($this->shmRead[$this->shmKey], $this->shmReadVar[$this->shmKey], "0")) === false))    // Lect = 0.
            
    {
                echo 
    "\t\tERREUR AFFECTATION VAR RATEE.<br />\n\n";
                return 
    false;
            }
            return 
    true;
        }
        private function 
    RELEASE_MUTEX()
        {
            if(
    is_resource($this->semWaitRead[$this->shmKey]))
            {
                
    sem_release($this->semWaitRead[$this->shmKey]);
                
    sem_remove($this->semWaitRead[$this->shmKey]);
            }
            if(
    is_resource($this->semWaitWrite[$this->shmKey]))
            {
                
    sem_release($this->semWaitWrite[$this->shmKey]);
                
    sem_remove($this->semWaitWrite[$this->shmKey]);
            }
            if(
    is_resource($this->semWait))
            {
                
    sem_release($this->semWait[$this->shmKey]);
                
    sem_remove($this->semWait[$this->shmKey]);
            }
            if(
    is_resource($this->shmRead[$this->shmKey]))
            {
                
    shm_detach($this->shmRead[$this->shmKey]);
            }
            return 
    true;
        }
        private function 
    BEGIN_READ()
        {
            
    /**
            * Version CNAM
            **************
            * P(semWait)
            * P(semWaitRead
            * Lect = Lect + 1
            * IF(Lect == 1) P(semWaitWrite
            * V(semWaitRead
            * V(semWait)
            * lectures.
            **/
            /************************/
            /*   Commencer_Lire    */
            /************************/
            
    if((!is_resource($this->semWait[$this->shmKey]))
                &&(!
    is_resource($this->semWaitRead[$this->shmKey]))
                &&(!
    is_resource($this->semWaitWrite[$this->shmKey]))
                &&(!
    is_resource($this->shmRead[$this->shmKey])))
                
    $this->INIT_MUTEX();
            
    // SET THE FIFO.
            
    sem_acquire($this->semWait[$this->shmKey]);
            
    // SET THE SEM_READ.
            
    sem_acquire($this->semWaitRead[$this->shmKey]);
            
    //        echo "\t\tLect avant Incrementation = " . (int)shm_get_var($this->shmRead[$this->shmKey], $this->shmReadVar[$this->shmKey])  . "<br />\n\n";
            // INCREMENT var Lecteurs.
            
    if(shm_put_var($this->shmRead[$this->shmKey], $this->shmReadVar[$this->shmKey], (string)((int)shm_get_var($this->shmRead[$this->shmKey], $this->shmReadVar[$this->shmKey]) + 1)) === false)
            {
                echo 
    "\t\tERREUR INCREMENTATION VAR.<br />\n\n";
                
    $this->RELEASE_MUTEX();
                return 
    false;
            }
            
    //        echo "\t\tLect après Incrementation = " . (int)shm_get_var($this->shmRead[$this->shmKey], $this->shmReadVar[$this->shmKey])  . "<br />\n\n";
            
    if((int)shm_get_var($this->shmRead[$this->shmKey], $this->shmReadVar[$this->shmKey]) == 1)
                
    // SET THE SEM_WRITE.
                
    sem_acquire($this->semWaitWrite[$this->shmKey]);
            
    //        echo "\t\tLect après Incrementation et blocage = " . (int)shm_get_var($this->shmRead[$this->shmKey], $this->shmReadVar[$this->shmKey])  . "<br />\n\n";
            // RELEASE THE SEM_READ.
            
    sem_release($this->semWaitRead[$this->shmKey]);
            
    // RELEASE THE FIFO.
            
    sem_release($this->semWait[$this->shmKey]);
            return 
    true;
        }
        private function 
    END_READ()
        {
            
    /**
            * Version CNAM
            * ************
            * P(semWaitRead
            * Lect = Lect - 1
            * IF(Lect == 0) V(semWaitWrite
            * V(semWaitRead
            **/
            /************************/
            /*    Finir_Lire    */
            /************************/
            // SET THE SEM_READ.
            
    sem_acquire($this->semWaitRead[$this->shmKey]);
            
    //        echo "\t\tLect avant Décrémentation = " . (int)shm_get_var($this->shmRead[$this->shmKey], $this->shmReadVar[$this->shmKey])  . "<br />\n\n";
            // DECREMENT var Lecteurs.
            
    if(shm_put_var($this->shmRead[$this->shmKey], $this->shmReadVar[$this->shmKey], (string)((int)shm_get_var($this->shmRead[$this->shmKey], $this->shmReadVar[$this->shmKey]) - 1)) === false)
            {
                echo 
    "\t\tERREUR DECREMENTATION VAR.<br />\n\n";
                
    $this->RELEASE_MUTEX();
                return 
    false;
            }
            
    //        echo "\t\tLect après Décrémentation = " . (int)shm_get_var($this->shmRead[$this->shmKey], $this->shmReadVar[$this->shmKey])  . "<br />\n\n";
            
    if((int)shm_get_var($this->shmRead[$this->shmKey], $this->shmReadVar[$this->shmKey]) == 0)
                
    // RELEASE THE SEM_WRITE.
                
    sem_release($this->semWaitWrite[$this->shmKey]);
            
    //        echo "\t\tLect après Décrémentation et blocage = " . (int)shm_get_var($this->shmRead[$this->shmKey], $this->shmReadVar[$this->shmKey])  . "<br />\n\n";
            // RELEASE THE SEM_READ.
            
    sem_release($this->semWaitRead[$this->shmKey]);
            return 
    true;
        }
        private function 
    BEGIN_WRITE()
        {
            
    /**
            * Version CNAM
            **************
            * P(semWait)
            * P(semWaitWrite
            * V(semWait)
            * écritures.
            **/
            /************************/
            /*   Commencer_Ecrire    */
            /************************/
            
    if((!is_resource($this->semWait[$this->shmKey]))
                &&(!
    is_resource($this->semWaitRead[$this->shmKey]))
                &&(!
    is_resource($this->semWaitWrite[$this->shmKey]))
                &&(!
    is_resource($this->shmRead[$this->shmKey])))
                
    $this->INIT_MUTEX();
            
    // SET THE FIFO.
            
    sem_acquire($this->semWait[$this->shmKey]);
            
    // SET THE SEM_WRITE.
            
    sem_acquire($this->semWaitWrite[$this->shmKey]);
            
    // RELEASE THE FIFO.
            
    sem_release($this->semWait[$this->shmKey]);
            return 
    true;
        }
        protected function 
    END_WRITE()
        {
            
    /**
            * Version CNAM
            **************
            * V(semWaitWrite
            **/
            /************************/
            /*   Finir_Ecrire    */
            /************************/
            // RELEASE THE FIFO.
            
    sem_release($this->semWaitWrite[$this->shmKey]);
            return 
    true;
        }
        protected function 
    millisecond()
        {
            return 
    floor(microtime(true)/0.001 0.5);
        }
        
    /**
        * Pour les
        * ID de SHM.
        **/
        
    private function SHM_ID($str)
        {
            return 
    '"' $str '"';
        }
        
    /**
        * Format type
        * string conpressée
        * après linearisation.
        **/
        
    private function SHM_DEFLATE(string $value)
        {
            
    /**
            * On ajoute un '\0'.
            **/
            
    return $this->str_to_nts($value);
            
    /**
            * VALUE => COMPRESS => BASE64_ENCODE => STR
            **/
            
    $str base64_encode($value);
            
    $str =  base64_encode(gzcompress($value));
        }
        
    /**
        * Format type
        * string déconpressée
        * et délinéarisée.
        **/
        
    private function SHM_INFLATE($value)
        {
            if(
    $value === false)
            {
                return 
    false;
            }
            
    /**
            * On enlève le '\0'.
            **/
            
    $data =  $this->str_from_mem($value);
            return 
    $data;
            
    /*
            * STR => BASE64_DECODE => UNCOMPRESS.
            */
            
    return base64_decode($data);
            return 
    gzuncompress(base64_decode($data));
        }
        private function 
    str_from_mem(string &$value) {
            
    $i strpos($valuechr(0));
            if (
    $i !== false) {
                return 
    substr($value0$i);
            }
            return 
    $value;
        }
        private function 
    str_to_nts(string $value) {
            return 
    $value.chr(0);
        }
        private function 
    wrapper_shmop_open(int $keystring $flagsint $perm 0666int $size 0)
        {
            
    /**
            * USER root,
            * specific threatment
            * for opening
            * the SHM as nginx.
            **/
            
    if(posix_geteuid() == 0)
            {
                switch(
    $flags) {
                case 
    "n" :
                case 
    "c" :
                    
    /**
                    * Creation
                    * comme user
                    * nginx.
                    **/
                    
    exec(self::SUDO " -u nginx " self::PHP " -r '@shmop_open(" $key ", \"" $flags "\", " $perm ", " $size ");'"); //Create Shared Memory segment as USER nginx
                    
    $flags "w";
                    break;
                default :
                    break;
                }
            }
            return @
    shmop_open($key$flags$perm$size);
        }
        private function 
    wrapper_shmop_delete($shmId)
        {
            
    $result shmop_delete($shmId);
            
    //        echo "RESULTAT DELETE = " . $result . "<br />\n\n";
            
    return $result;
        }
        private function 
    wrapper_shmop_size($shmId)
        {
            return 
    shmop_size($shmId);
        }
        private function 
    wrapper_shmop_close($shmId)
        {
            return 
    shmop_close($shmId);
        }
        private function 
    wrapper_shmop_read($shmId$offset$tmp_count)
        {
            return 
    shmop_read($shmId$offset$tmp_count);
        }
        private function 
    wrapper_shmop_write($shmId$value$offset)
        {
            return 
    shmop_write($shmId$value$offset);
        }
        private function 
    OPEN(string $flagsint $modeint $size)
        {
            
    $this->shmMode[$this->shmKey] = $mode;
            
    $this->shmFlags[$this->shmKey] = $flags;
            
    $this->shmId[$this->shmKey] = false;
            if(
    $this->shmFlags[$this->shmKey] == "a")
            {
                if(
    $size == 0)
                {
                    
    $shm $this->wrapper_shmop_open($this->shmKey$this->shmFlags[$this->shmKey], 06660);
                }
                else
                {
                    
    $shm $this->wrapper_shmop_open($this->shmKey$this->shmFlags[$this->shmKey], 0666$this->shmLimitBlockSize[$this->shmKey]);
                }
                if(
    $shm === false)
                {
                    return 
    false;
                }
                
    $this->shmId[$this->shmKey] = $shm;
                return 
    true;
            }
            switch (
    $this->shmFlags[$this->shmKey]) {
            case 
    "n" :
                
    /**
                * On update
                * si besoin
                * les paramètres
                * d'allocation
                * mémoire.
                **/
                
    $this->ALLOCATE($size);
                
    $shm $this->wrapper_shmop_open($this->shmKey$this->shmFlags[$this->shmKey], 0666$this->shmLimitBlockSize[$this->shmKey]);
                
    /**
                * Le SHM
                * ne doit
                * pas exister.
                **/
                
    if($shm === false)
                {
                    echo 
    "\t\t" 'Erreur création : Le SHM existe déjà.' "<br />\n\n";
                    return 
    false;
                }
                
    $this->shmId[$this->shmKey] = $shm;
                
    /**
                * Enregistrement
                * de la taille
                * demandée.
                **/
                
    $str_size $this->SHM_DEFLATE($size);
                if(
    $this->wrapper_shmop_write($this->shmId[$this->shmKey], $str_size0) === false)
                {
                    echo 
    "\t\t" 'Erreur initialisation taille SHM.' "<br />\n\n";
                    return 
    false;
                }
                return 
    true;
                break;
                
    /**
                * Pour créer
                * un bloc
                * s'il n'existe pas,
                * ou l'ouvrir
                * en lecture/écriture
                * s'il existe.
                **/
            
    case "c" :
            case 
    "w" :
                
    /**
                * On vérifie
                * si le SHM
                * existe.
                **/
                
    $shm $this->wrapper_shmop_open($this->shmKey"w"0666$this->shmLimitBlockSize[$this->shmKey]);
                
    /**
                * Le SHM existe.
                *
                * On ne peut
                * l'effacer
                * puis le recréer
                * que si le sémaaphore
                * est libre.
                **/
                
    if($shm !== false)
                {
                    if((
    $enreg $this->SHM_INFLATE($this->wrapper_shmop_read($shm$this->shmEnregOffset$this->wrapper_shmop_size($shm) - $this->shmEnregOffset))) === false)
                    {
                        echo 
    "\t\t" 'Erreur lecture SHM.' "<br />\n\n";
                        return 
    false;
                    }
                    
    /**
                    * On update
                    * si besoin
                    * les paramètres
                    * d'allocation
                    * mémoire.
                    **/
                    
    if($this->ALLOCATE($size))
                    {
                        if(
    $this->wrapper_shmop_delete($shm) == false)
                        {
                            
    $this->shmId[$this->shmKey] = false;
                            return 
    false;
                        }
                        
    $this->wrapper_shmop_close($shm);
                        
    $this->shmId[$this->shmKey] = false;
                        if((
    $shm $this->wrapper_shmop_open($this->shmKey"n"0666$this->shmLimitBlockSize[$this->shmKey])) === false)
                        {
                            echo 
    "\t\t" 'Erreur création : Le SHM existait déjà.' "<br />\n\n";
                            return 
    false;
                        }
                        
    $this->shmId[$this->shmKey] = $shm;
                        
    /**
                        * Enregistrement
                        * de la taille
                        * demandée.
                        **/
                        
    $str_size $this->SHM_DEFLATE($size);
                        if(
    $this->wrapper_shmop_write($this->shmId[$this->shmKey], $str_size0) === false)
                        {
                            echo 
    "\t\t" 'Erreur update taille SHM.' "<br />\n\n";
                            return 
    false;
                        }
                        
    /**
                        * Recopie
                        * de l'enregistrement
                        * précédent.
                        **/
                        
    $str $this->SHM_DEFLATE($enreg);
                        if(
    $this->wrapper_shmop_write($this->shmId[$this->shmKey], $str$this->shmEnregOffset) === false)
                        {
                            echo 
    "\t\t" 'Erreur update et recopie SHM.' "<br />\n\n";
                            return 
    false;
                        }
                    }
                    else
                    {
                        
    /**
                        * On ne change pas
                        * la taille
                        * du SHM..
                        **/
                        
    $this->shmId[$this->shmKey] = $shm;
                    }
                }
                
    /**
                * Le SHM n'existe pas,
                * on peut
                * mettre à jour
                * sa dimension.
                **/
                
    else
                {
                    
    /**
                    * On update
                    * si besoin
                    * les paramètres
                    * d'allocation
                    * mémoire.
                    **/
                    
    $this->ALLOCATE($size);
                    if((
    $shm $this->wrapper_shmop_open($this->shmKey"n"0666$this->shmLimitBlockSize[$this->shmKey])) === false)
                    {
                        echo 
    "\t\t" 'Erreur création : Le SHM existe déjà.' "<br />\n\n";
                        return 
    false;
                    }
                    
    $this->shmId[$this->shmKey] = $shm;
                    
    /**
                    * Enreg
                    * des tailles
                    * brutes et
                    * réelles.
                    **/
                    
    $str_size $this->SHM_DEFLATE($size);
                    if(
    $this->wrapper_shmop_write($this->shmId[$this->shmKey], $str_size0) === false)
                    {
                        echo 
    "\t\t" 'Erreur initialisation taille SHM.' "<br />\n\n";
                        return 
    false;
                    }
                }
                return 
    true;
                break;
            default :
                throw new 
    RuntimeException("Paramètre SHM faux = " $this->shmFlags[$this->shmKey]);
                return 
    false;
                break;
            }
            return 
    true;
        }
        private function 
    ALLOCATE(int $size)
        {
            
    $BlockSize $size 1;
            if((
    $this->shmBlockSize[$this->shmKey] < $BlockSize)||
                (
    $this->shmLimitBlockSize[$this->shmKey] < (2048 ceil($BlockSize[$this->shmKey] / 2048.0))))
            {
                
    $this->shmBlockSize[$this->shmKey] = $size 1;
                
    /**
                * Surplus
                * pour dépassements[$this->shmKey]
                * peu fréquents.
                **/
                
    $this->shmLimitBlockSize[$this->shmKey] = 2048 ceil($this->shmBlockSize[$this->shmKey] / 2048.0);
                return 
    true;
            }
            return 
    false;
        }
        protected function 
    SHM_EXIST()
        {
            
    /**
            * SHM existe.
            **/
            
    if($this->OPEN("a"06660) !== false)
            {
                
    $this->wrapper_shmop_close($this->shmId[$this->shmKey]);
                return 
    true;
            }
            return 
    false;
        }
        protected function 
    SHM_DELETE()
        {
            
    $this->BEGIN_WRITE();
            if(
    $this->OPEN("w"0666128) === false)
            {
                echo 
    "\t\t" 'ERREUR OPEN("w", 0666, ' 128 ') = false' "<br />\n\n";
                
    $this->END_WRITE();
                return 
    false;
            }
            
    $this->wrapper_shmop_delete($this->shmId[$this->shmKey]);
            
    $this->wrapper_shmop_close($this->shmId[$this->shmKey]);
            
    $this->END_WRITE();
        }
        protected function 
    SHM_READ(bool $block false)
        {
            if(
    $block)
                
    /**
                * Blocage en écriture
                * en prévision
                * d'un appel
                * à $this->WRITE($data, true),
                * qui appellera
                * le END_WRITE();
                **/
                
    $this->BEGIN_WRITE();
            else
                
    /**
                * Blocage en lecture
                * END_READ() est lancé
                * en fin de
                * fonction.
                **/
                
    $this->BEGIN_READ();
            if(
    $this->OPEN("a"06660) === false)
            {
                echo 
    "\t\t" 'ERREUR OPEN("a", 0666, ' ') = false' "<br />\n\n";
                if(
    $block)
                    
    $this->END_WRITE();
                else
                    
    $this->END_READ();
                return 
    false;
            }
            
    $len $this->wrapper_shmop_size($this->shmId[$this->shmKey]) - $this->shmEnregOffset;
            
    $enreg $this->wrapper_shmop_read($this->shmId[$this->shmKey], $this->shmEnregOffset$len);
            if(
    strlen($enreg) != $len)
            {
                echo 
    "\t\t\t" 'ERREUR TAILLE ENREG LU = ' strlen($enreg) . ' <> TAILLE LUE = ' $len "<br />\n";
                
    $this->wrapper_shmop_close($this->shmId[$this->shmKey]);
                if(
    $block)
                    
    $this->END_WRITE();
                else
                    
    $this->END_READ();
                return 
    false;
            }
            
    $this->wrapper_shmop_close($this->shmId[$this->shmKey]);
            if(!
    $block)
                
    $this->END_READ();
            return 
    $this->SHM_INFLATE($enreg);
        }
        protected function 
    SHM_WRITE(string $databool $block false)
        {
            if(!
    $block)
                
    $this->BEGIN_WRITE();
            
    $str $this->SHM_DEFLATE($data);
            
    $size strlen($str) + 1024;
            
    /**
            if($size < $this->shmLimitBlockSize[$this->shmKey])
            {
                $size = $this->shmLimitBlockSize[$this->shmKey];
            }
            **/
            
    if($this->OPEN("c"0666$size) === false)
            {
                echo 
    "\t\t" 'ERREUR OPEN("c", 0666, ' $size ') = false' "<br />\n\n";
                
    $this->END_WRITE();
                return 
    false;
            }
            
    // Write Data
            
    $res $this->wrapper_shmop_write($this->shmId[$this->shmKey], $str$this->shmEnregOffset);
            
    $this->wrapper_shmop_close($this->shmId[$this->shmKey]);
            
    $this->END_WRITE();
            return 
    $res;
        }
        protected function 
    SHM_APPEND(string $data)
        {
            
    $enreg $this->READ(true);
            if(
    $enreg === false)
            {
                return 
    false;
            }
            
    $str $this->SHM_DEFLATE($enreg) . $data;
            
    $res $this->WRITE($strtrue);
            return 
    $res;
        }
        protected function 
    SHM_SIZE()
        {
            if(
    $this->OPEN("a"06660) === false)
            {
                return 
    false;
            }
            
    $res $this->wrapper_shmop_size($this->shmId[$this->shmKey]);
            
    $this->wrapper_shmop_close($this->shmId[$this->shmKey]);
            return 
    $res;
        }
    }
    ?>