<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Linux Attitude&#187; Lecture de code</title>
	<atom:link href="http://linux-attitude.fr/tag/lecture-de-code/feed" rel="self" type="application/rss+xml" />
	<link>http://linux-attitude.fr</link>
	<description>Le libre est un état d&#039;esprit</description>
	<lastBuildDate>Tue, 20 Jul 2010 19:54:56 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Petit patch patch noël</title>
		<link>http://linux-attitude.fr/post/petit-patch-patch-noel</link>
		<comments>http://linux-attitude.fr/post/petit-patch-patch-noel#comments</comments>
		<pubDate>Mon, 26 Nov 2007 22:24:00 +0000</pubDate>
		<dc:creator>peck</dc:creator>
				<category><![CDATA[Développement]]></category>
		<category><![CDATA[Lecture de code]]></category>

		<guid isPermaLink="false">http://linux-attitude.fr/post/petit-patch-patch-noel</guid>
		<description><![CDATA[Niveau&#160;:     



Savoir relire le code d'un autre est indispensable. Et ce pour plusieurs raisons, soit parce que vous voulez vous mettre à travailler sur un projet existant, soit parce que vous voulez simplement fournir un patch pour un code qu'on vous a fourni (probablement open source). Nous allons donc voir de [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Niveau</strong>&nbsp;: <img src="/public/Pics/s.gif" alt="Star" /> <img src="/public/Pics/s.gif" alt="Star" /> <img src="/public/Pics/s.gif" alt="Star" /> <img src="/public/Pics/s.gif" alt="Star" /> <img src="/public/Pics/e.gif" alt="Empty" /><br /></p>



<p>Savoir relire le code d'un autre est indispensable. Et ce pour plusieurs raisons, soit parce que vous voulez vous mettre à travailler sur un projet existant, soit parce que vous voulez simplement fournir un patch pour un code qu'on vous a fourni (probablement open source). Nous allons donc voir de quoi il s'agit, puis mettre en pratique sur apache.</p>


<p>Pour vous lancer dans l'aventure, il peut vous être utile de savoir utiliser <a href="http://linux-attitude.fr/post/Mes-amis-les-drapeaux">ctags ou etags</a>. De plus, connaître des techniques de <a href="http://fr.wikipedia.org/wiki/Lecture_rapide" hreflang="fr">lecture rapide</a> vous permettra d'aller plus vite.</p>



<p>Plantons le décor, nous voulons faire un patch à apache 2.2 pour permettre d'ajouter dans les logs les durées de récupération de données par mod_proxy. Récupérons le code source et partons de ce qu'on sait (et n'oublions pas de le dupliquer pour nous simplifier la création de patch par la suite).</p>
<pre>
$ cp -a apache2-2.2.6 apache2-2.2.6.old
$ cd apache2-2.2.6
$ find . -type f | grep &quot;c$&quot; | xargs ctags
</pre>


<p>On sait qu'actuellement, grâce à mod_log_config, on peut logguer les durées individuelles des requêtes. Le code source semble divisé logiquement, nous allons donc lire modules/loggers/mod_log_config.c. Parcourons-le rapidement, on constate un certain nombre de fonctions log_*, probablement pour écrire dans les logs. Étant donné la façon dont elles sont appelées, il doit y avoir une référence dans un tableau quelque part. On la trouve en fin de fichier, ainsi que la fonction qui nous intéresse&nbsp;: log_request_duration_microseconds.</p>


<p>Lisons-la&nbsp;:</p>
<pre>
$ vi -t log_request_duration_microseconds
</pre>

<p>Deux choses intéressantes&nbsp;:</p>
<ul>
<li>apr_time_now() -&gt; au vu du nom et de la précision, ça doit donner la date et l'heure en microsecondes. Donc on sait comment on va calculer notre durée.</li>
<li>r-&gt;request_time et request_rec *r -&gt; on en déduit qu'il existe une structure par requête dans laquelle on pourra stocker les dates de début et de fin.</li>
</ul>

<p>Cherchons maintenant où appeler ces fonctions pour calculer les durées. Nous allons donc lire ./modules/proxy/mod_proxy.c. On le parcourt en largeur et on constate que&nbsp;:</p>
<ul>
<li>C'est plutôt bien commenté</li>
<li>Les noms de fonction ont un sens</li>
<li>La majorité des fonctions s'appelle proxy_*</li>
</ul>

<p><span id="more-15"></span></p>


<p>On prend la liste de ces fonctions et au vu des noms, proxy_handler est celle qui a le plus de chance de nous intéresser. À la lecture de la fonction, on voit que le début n'appelle pas de fonction non standard ayant un sens (en gros ap_die et ap_finalize_request_protocol) on saute donc jusqu'à&nbsp;:</p>
<pre>
    do {
        char *url = uri;
        /* Try to obtain the most suitable worker */
</pre>

<p>Ça commence à nous intéresser. À l'intérieur on trouve enfin quelque chose d'utile&nbsp;:</p>
<pre>
        /* handle the scheme */
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r-&gt;server,
                     &quot;Running scheme %s handler (attempt %d)&quot;,
                     scheme, attempts);
        access_status = proxy_run_scheme_handler(r, worker, conf,
                                                 url, NULL, 0);
</pre>

<p>Et voila, on a trouvé ce qui nous intéressait vraiment. Pour preuve&nbsp;: ...</p>


<p>Et pour ceux qui veulent savoir, la fonction appelée derrière dans le cas de mod_proxy_http est proxy_http_handler, qu'on trouve cette fois beaucoup plus facilement à la lecture de ./modules/proxy/mod_proxy_http.c.</p>


<p>On placera donc nos appels à apr_time_now() juste avant et après cette fonction.</p>


<p>Avant de placer l'appel, il faut préparer la structure qui hébergera l'information. On a vu qu'on pourrait la mettre dans request_rec, heureusement on voit que les données relatives à la requête sont disponibles dans notre fonction sous cette forme. Allons y mettre notre information&nbsp;:</p>
<pre>
$ vi -t request_rec
</pre>

<p>On ajoute 2 champs, qu'on copie d'un champ qu'on connaît et qui a déjà le bon type&nbsp;: request_time</p>
<pre>
    /** Time when the proxy request started */
    apr_time_t proxy_begin;
    /** Time when the proxy request stopped */
    apr_time_t proxy_end;
</pre>


<p>Et ajoutons nos 2 lignes</p>
<pre>
        r-&gt;proxy_begin = apr_time_now();
        access_status = proxy_run_scheme_handler(r, worker, conf,
                                                 url, NULL, 0);
        r-&gt;proxy_end = apr_time_now();
</pre>


<p>Et enfin, on ajoute au module de log la possibilité de logguer tout ceci sur un code non occupé&nbsp;: choisissons %W</p>


<p>Et voila, c'est fini, ou presque. Il ne reste plus qu'à</p>
<ul>
<li>Créer le patch&nbsp;: <code>diff -ru apache2-2.2.6.old apache2-2.2.6</code></li>
<li>Recompiler</li>
<li>Tester</li>
<li>Envoyer à l'auteur</li>
</ul>


<p><strong>PS</strong>&nbsp;: Vous trouverez 2 patchs en pièce jointe, le premier ne patche que mod_proxy_http car je l'ai trouvé plus facile à lire au premier abord. Le second correspond au texte de l'article. Cf les annexes ci-dessous.</p>
	Tags:<a href="http://linux-attitude.fr/tag/lecture-de-code" title="Lecture de code" rel="tag">Lecture de code</a><br />
]]></content:encoded>
			<wfw:commentRss>http://linux-attitude.fr/post/petit-patch-patch-noel/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mes amis les drapeaux</title>
		<link>http://linux-attitude.fr/post/mes-amis-les-drapeaux</link>
		<comments>http://linux-attitude.fr/post/mes-amis-les-drapeaux#comments</comments>
		<pubDate>Sun, 25 Nov 2007 23:47:00 +0000</pubDate>
		<dc:creator>peck</dc:creator>
				<category><![CDATA[Développement]]></category>
		<category><![CDATA[Lecture de code]]></category>

		<guid isPermaLink="false">http://linux-attitude.fr/post/mes-amis-les-drapeaux</guid>
		<description><![CDATA[Niveau&#160;:     
Résumé&#160;: ctags &#38;&#38; etags


J'imagine qu'il vous arrive de lire le code d'un autre, ou même de lire le votre, et de chercher des fonctions précises.
Si vous faites avec grep, vous perdez du temps a différencier les appels des déclarations. Si vous avez un vrai environnement de développement, alors vous disposez [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Niveau</strong>&nbsp;: <img src="/public/Pics/s.gif" alt="Star" /> <img src="/public/Pics/s.gif" alt="Star" /> <img src="/public/Pics/e.gif" alt="Empty" /> <img src="/public/Pics/e.gif" alt="Empty" /> <img src="/public/Pics/e.gif" alt="Empty" /><br />
<strong>Résumé</strong>&nbsp;: ctags &amp;&amp; etags</p>


<p>J'imagine qu'il vous arrive de lire le code d'un autre, ou même de lire le votre, et de chercher des fonctions précises.
Si vous faites avec grep, vous perdez du temps a différencier les appels des déclarations. Si vous avez un vrai environnement de développement, alors vous disposez déjà de la fonction et vous avez raison.</p>


<p>Bon, maintenant supposons que vous n'ayez que des moyens ultra-sophistiqués à votre disposition, emacs ou vi.</p>


<p>Il existe deux commandes (qui en fait sont les mêmes) pour générer un fichier de tag qui sera lu par emacs ou vi pour retrouver instantanément ou est définie une fonction. Ces commandes sont etags pour emacs et ctags pour vi, avec presque les mêmes arguments. Elle comprennent toutes les 2 un très grand nombre de langages différents (<code>etags --help</code> pour la liste):</p>


<p>Pour indexer des fichiers&nbsp;:</p>
<pre>
$ ctags fichier1.c fchier2.h 
$ etags fichier1.c fchier2.h 
</pre>


<p>ctags génère un fichier tags alors que etags génère un fichier TAGS. Attention, les options par défaut de etags et de ctags ne sont pas les mêmes.</p>


<p>Avec vi, vous pouvez ouvrir directement le fichier contenant la définition de la fonction main en utilisant l'option suivante&nbsp;:</p>
<pre>
$ vi -t main
</pre>


<p>Pour utiliser le fichier de tags dans un éditeur déjà ouvert, vous avez plusieurs raccourcis.</p>
<ul>
<li>Sous emacs <code>M-. main</code> et <code>M-x tags-search main</code>(et bien d'autres <a href="http://www.cs.cmu.edu/cgi-bin/info2www?(emacs)Find%20Tag" title="http://www.cs.cmu.edu/cgi-bin/info2www?(emacs)Find%20Tag">http://www.cs.cmu.edu/cgi-bin/info2...</a> )</li>
<li>Sous vi <code>:tag main</code> et <code>ctrl-]</code></li>
</ul>

<p>Pour indexer tout un projet, utilisez une commande du style (à adapter selon le langage)&nbsp;:</p>
<pre>
$ find . -type f  -name '*.c' -o -name '*.h' | xargs etags
</pre>


<p>Enfin un certain nombre d'options peut vous intéresser, pour cela je vous conseille la lecture de man etags. En particulier -d -g -m -t et -T</p>
	Tags:<a href="http://linux-attitude.fr/tag/lecture-de-code" title="Lecture de code" rel="tag">Lecture de code</a><br />
]]></content:encoded>
			<wfw:commentRss>http://linux-attitude.fr/post/mes-amis-les-drapeaux/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk
Page Caching using apc (user agent is rejected)
Database Caching 2/20 queries in 0.016 seconds using apc

Served from: linux-attitude.fr @ 2010-07-31 04:13:45 -->