<?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>Roberto Moutinho</title>
	<atom:link href="http://robertomoutinho.com.br/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://robertomoutinho.com.br/blog</link>
	<description>Web Development - Scalability - DevOP</description>
	<lastBuildDate>Thu, 26 Apr 2012 19:05:44 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Custom Log Format no varnishncsa</title>
		<link>http://robertomoutinho.com.br/blog/custom-log-format-no-varnishncsa/</link>
		<comments>http://robertomoutinho.com.br/blog/custom-log-format-no-varnishncsa/#comments</comments>
		<pubDate>Thu, 26 Apr 2012 19:05:44 +0000</pubDate>
		<dc:creator>moutinho</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Varnish]]></category>

		<guid isPermaLink="false">http://robertomoutinho.com.br/blog/?p=98</guid>
		<description><![CDATA[Para quem precisa definir um padrão diferente do &#8220;apache commons log&#8221; para servidores Varnish&#8230; esta tarefa trivial esconde um problema chato de solucionar. De acordo com a documentação (varnishncsa), o parametro -F serve exatamente para este proposito. Mas nem tudo são flores, pois ao tentar declarar este padrão direto ao DAEMON_OPTS do init script (/etc/init.d/varnishncsa [...]]]></description>
			<content:encoded><![CDATA[            <script type="text/javascript" src="http://robertomoutinho.com.br/blog/wp-content/plugins/wordpress-code-snippet/scripts/shBrushCpp.js"></script>
<p>Para quem precisa definir um padrão diferente do &#8220;apache commons log&#8221; para servidores Varnish&#8230; esta tarefa trivial esconde um problema chato de solucionar.</p>
<p>De acordo com a documentação (<a href="https://www.varnish-cache.org/docs/trunk/reference/varnishncsa.html" target="_blank">varnishncsa</a>), o parametro -F serve exatamente para este proposito. Mas nem tudo são flores, pois ao tentar declarar este padrão direto ao DAEMON_OPTS do init script (/etc/init.d/varnishncsa &#8211; redhat/centos) o processo silenciosamente entra em modo &#8220;default&#8221; e segue sem erros&#8230;</p>
<p>O problema mora nas aspas que precisam ser &#8220;escaped&#8221; corretamente (<a href="http://stackoverflow.com/questions/1661193/start-stop-daemon-quoted-arguments-misinterpreted" target="_blank">+ info</a>) e acabam por se misturar com as aspas do atributo.</p>
<p>A forma mais simples de contornar este problema é trabalhar com mais um atributo e adiciona-lo na execução, conforme o script abaixo:</p>
<p><pre class="brush: cpp">#! /bin/sh
#
# varnishncsa Control the Varnish NCSA logging daemon
#
# chkconfig: - 90 10
# description: Varnish Cache logging daemon
# processname: varnishncsa
# config: 
# pidfile: /var/run/varnishncsa.pid

### BEGIN INIT INFO
# Provides: varnishncsa
# Required-Start: $network $local_fs $remote_fs
# Required-Stop: $network $local_fs $remote_fs
# Default-Start:
# Default-Stop:
# Short-Description: start and stop varnishncsa
# Description: Varnish Cache NCSA logging daemon
### END INIT INFO

# Source function library.
. /etc/init.d/functions

retval=0
pidfile=&quot;/var/run/varnishncsa.pid&quot;
lockfile=&quot;/var/lock/subsys/varnishncsa&quot;
logfile=&quot;/var/log/varnish/varnishncsa.log&quot;

exec=&quot;/usr/bin/varnishncsa&quot;
prog=&quot;varnishncsa&quot;

LOG_FORMAT=&quot;-F \&quot;\&quot;%{X-IP}i\&quot; %l %u %t \&quot;%r\&quot; %s %b \&quot;%{Referer}i\&quot; \&quot;%{User-agent}i\&quot;\&quot;&quot;
DAEMON_OPTS=&quot;-c -a -w $logfile -P $pidfile -D&quot;

# Include varnishncsa defaults
[ -e /etc/sysconfig/varnishncsa ] &amp;&amp; . /etc/sysconfig/varnishncsa

start() {

	if [ ! -x $exec ]
	then
		echo $exec not found
		exit 5
	fi

	echo -n &quot;Starting varnish ncsa logging daemon: &quot;

	daemon --pidfile $pidfile $exec &quot;$DAEMON_OPTS&quot; &quot;$LOG_FORMAT&quot;
	echo
	return $retval
}

stop() {
	echo -n &quot;Stopping varnish ncsa logging daemon: &quot;
	killproc -p $pidfile $prog
	retval=$?
	echo
	[ $retval -eq 0 ] &amp;&amp; rm -f $lockfile
	return $retval
}

restart() {
	stop
	start
}

reload() {
	restart
}

force_reload() {
	restart
}

rh_status() {
	status -p $pidfile $prog
}

rh_status_q() {
	rh_status &gt;/dev/null 2&gt;&amp;1
}

# See how we were called.
case &quot;$1&quot; in
	start)
		rh_status_q &amp;&amp; exit 0
		$1
		;;
	stop)
		rh_status_q || exit 0
		$1
		;;
	restart)
		$1
		;;
	reload)
		rh_status_q || exit 7
		$1
		;;
	force-reload)
		force_reload
		;;
	status)
		rh_status
		;;
	condrestart|try-restart)
		rh_status_q || exit 0
		restart
		;;
	*)
	echo &quot;Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}&quot;

	exit 2
esac

exit $?
</pre></p>
]]></content:encoded>
			<wfw:commentRss>http://robertomoutinho.com.br/blog/custom-log-format-no-varnishncsa/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Checar se processo está rodando &#8211; Shell script para processos 24/7</title>
		<link>http://robertomoutinho.com.br/blog/checar-se-processo-esta-rodando-shell-script-para-processos-247/</link>
		<comments>http://robertomoutinho.com.br/blog/checar-se-processo-esta-rodando-shell-script-para-processos-247/#comments</comments>
		<pubDate>Wed, 25 Apr 2012 13:29:10 +0000</pubDate>
		<dc:creator>moutinho</dc:creator>
				<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://robertomoutinho.com.br/blog/?p=96</guid>
		<description><![CDATA[Para processos criticos 24/7, que inexplicavelmente (ou explicavelmente) tem o habito de terminarem sua execução, segue um pequeno shell script para ajudá-los na tarefa de mantê-los no ar e evitar ter de trabalhar via VPN 3:00am. #!/bin/bash cd /directory/where/your/process/is process='com.yourdomain.yourProcess' if [ &#34;$1&#34; == 'stop' ] then ps -ef &#124; grep -v grep &#124; grep [...]]]></description>
			<content:encoded><![CDATA[            <script type="text/javascript" src="http://robertomoutinho.com.br/blog/wp-content/plugins/wordpress-code-snippet/scripts/shBrushCpp.js"></script>
            <script type="text/javascript" src="http://robertomoutinho.com.br/blog/wp-content/plugins/wordpress-code-snippet/scripts/shBrushPython.js"></script>
<p>Para processos criticos 24/7, que inexplicavelmente (ou explicavelmente) tem o habito de terminarem sua execução, segue um pequeno shell script para ajudá-los na tarefa de mantê-los no ar e evitar ter de trabalhar via VPN 3:00am.</p>
<p><pre class="brush: python">#!/bin/bash

cd /directory/where/your/process/is

process='com.yourdomain.yourProcess'


if [ &quot;$1&quot; == 'stop' ]
        then
                ps -ef | grep -v grep | grep $process
                if [ $? -eq 1 ]
                        then
                                echo &quot;yourProcess [STOP] - No process found&quot;
                        else
                                kill -9 `ps -ef | awk '/[c]om.yourdomain.yourProcess/{print $2}'`
                                echo &quot;yourProcess [STOP] - Stopped&quot;
                fi
        else
                ps -ef | grep -v grep | grep $process
                if [ $? -eq 1 ]
                        then
                                java -cp .:../lib/mysql-connector-java-5.1.16.jar com.yourdomain.yourProcess &amp; &gt; /dev/null
                                echo $$ &gt; yourProcess.pid
                                echo &quot;yourProcess [START] - Process started. Check logs for runtime problems&quot;
                        else
                                echo &quot;yourProcess [WARNING] - Process already running&quot;
                fi
fi</pre></p>
<p>&nbsp;</p>
<p>Para isso&#8230; basta colocar este processo no cron para verificar de 5 em 5 minutos se o processo ainda está sendo executado.</p>
]]></content:encoded>
			<wfw:commentRss>http://robertomoutinho.com.br/blog/checar-se-processo-esta-rodando-shell-script-para-processos-247/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Modificando SQL com parametros de indexação do Solr (DIH)</title>
		<link>http://robertomoutinho.com.br/blog/modificando-sql-com-parametros-de-indexacao-do-solr-dih/</link>
		<comments>http://robertomoutinho.com.br/blog/modificando-sql-com-parametros-de-indexacao-do-solr-dih/#comments</comments>
		<pubDate>Tue, 24 Apr 2012 12:55:34 +0000</pubDate>
		<dc:creator>moutinho</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Solr]]></category>

		<guid isPermaLink="false">http://robertomoutinho.com.br/blog/?p=94</guid>
		<description><![CDATA[Uma grande sacada na utilização do DataImportHandler (tirada do livro &#8220;Apache Solr 3 Enterprise Search Server&#8220;) é a possibilidade de passar parametros para o SQL que está contido no arquivo de configuração. Um bom caso de uso é a possibilidade de informar via SQL se a extração de dados deve ser completa ou parcial (delta). [...]]]></description>
			<content:encoded><![CDATA[            <script type="text/javascript" src="http://robertomoutinho.com.br/blog/wp-content/plugins/wordpress-code-snippet/scripts/shBrushCpp.js"></script>
            <script type="text/javascript" src="http://robertomoutinho.com.br/blog/wp-content/plugins/wordpress-code-snippet/scripts/shBrushPython.js"></script>
            <script type="text/javascript" src="http://robertomoutinho.com.br/blog/wp-content/plugins/wordpress-code-snippet/scripts/shBrushXml.js"></script>
<p>Uma grande sacada na utilização do DataImportHandler (tirada do livro &#8220;<a href="http://www.amazon.com/Apache-Solr-Enterprise-Search-Server/dp/1849516065/" target="_blank">Apache Solr 3 Enterprise Search Server</a>&#8220;) é a possibilidade de passar parametros para o SQL que está contido no arquivo de configuração.</p>
<p>Um bom caso de uso é a possibilidade de informar via SQL se a extração de dados deve ser completa ou parcial (delta).</p>
<p>vamos ao exemplo:</p>
<p><pre class="brush: xml">&lt;dataConfig&gt;
        &lt;dataSource
                type=&quot;JdbcDataSource&quot;
                name=&quot;ds&quot;
                driver=&quot;com.mysql.jdbc.Driver&quot;
                url=&quot;jdbc:mysql://127.0.0.1/my_db&quot;
                encoding=&quot;UTF-8&quot;
                user=&quot;usuario&quot;
                password=&quot;senha&quot;
		batchSize=&quot;-1&quot; // usar somente com MySQL
        /&gt;

	&lt;document name=&quot;product&quot;&gt;
		&lt;entity name=&quot;item&quot; 
			dataSource=&quot;ds&quot;
			pk=&quot;key&quot;  
			query=&quot; 
select * from my_db.my_table 
where ('${dataimporter.request.fullindex}' != 'false'
or
timestamp &amp;gt; date_sub(now(),interval 30 minute))
&quot;&gt;
		&lt;/entity&gt; 
	&lt;/document&gt; 
&lt;/dataConfig&gt;</pre></p>
<p>Desta forma, o parametro &#8220;${dataimporter.request.fullindex}&#8221; será substituido pelo valor passado na requisição.</p>
<p><em>http://127.0.0.1/solr/myCore/dataimport?command=full-import&amp;&amp;fullindex=true</em></p>
<p>fará com que o SQL final seja interpretado como uma extração total (sem o parametro que define onde o timestamp deverá ser maior do que os ultimos 5 minutos)</p>
<p><em>http://127.0.0.1/solr/myCore/dataimport?command=full-import&amp;&amp;fullindex=false</em></p>
<p>fará com que o SQL final seja interpretado como uma extração parcial. (mesmo com o &#8220;command=full-import&#8221;)</p>
]]></content:encoded>
			<wfw:commentRss>http://robertomoutinho.com.br/blog/modificando-sql-com-parametros-de-indexacao-do-solr-dih/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Grails 2.0 com MongoDB &#8211; Connection refused</title>
		<link>http://robertomoutinho.com.br/blog/grails-2-0-com-mongodb-connection-refused/</link>
		<comments>http://robertomoutinho.com.br/blog/grails-2-0-com-mongodb-connection-refused/#comments</comments>
		<pubDate>Mon, 23 Apr 2012 04:26:05 +0000</pubDate>
		<dc:creator>moutinho</dc:creator>
				<category><![CDATA[Grails]]></category>
		<category><![CDATA[MongoDB]]></category>
		<category><![CDATA[connection refused]]></category>
		<category><![CDATA[grails]]></category>
		<category><![CDATA[mongodb]]></category>

		<guid isPermaLink="false">http://robertomoutinho.com.br/blog/?p=88</guid>
		<description><![CDATA[Se você também está enfrentando problemas de recusa de conexão do MongoDB para sua app Grails (seja 2.0 ou não)&#8230; Antes de começar a chutar seu desktop/notebook, verifique a porta de conexão configurada em seu DataSource.groovy: Está escrito &#8220;port = 27107&#8221; certo ? Pois bem&#8230; a documentação do plugin está errada (até a presente data). [...]]]></description>
			<content:encoded><![CDATA[            <script type="text/javascript" src="http://robertomoutinho.com.br/blog/wp-content/plugins/wordpress-code-snippet/scripts/shBrushCpp.js"></script>
            <script type="text/javascript" src="http://robertomoutinho.com.br/blog/wp-content/plugins/wordpress-code-snippet/scripts/shBrushPython.js"></script>
            <script type="text/javascript" src="http://robertomoutinho.com.br/blog/wp-content/plugins/wordpress-code-snippet/scripts/shBrushXml.js"></script>
<p>Se você também está enfrentando problemas de recusa de conexão do MongoDB para sua app Grails (seja 2.0 ou não)&#8230;<br />
Antes de começar a chutar seu desktop/notebook, verifique a porta de conexão configurada em seu DataSource.groovy:</p>
<p>Está escrito &#8220;<strong>port = 27107</strong>&#8221; certo ?</p>
<p>Pois bem&#8230; a<a href="http://grails.github.com/inconsequential/mongo/manual/index.html" target="_blank"> documentação do plugin</a> está errada (até a presente data).</p>
<p>A porta correta é <strong>27017</strong> e não a informada na documentação.</p>
<p>Este erro de documentação passa facilmente despercebido na hora de configurar e da uma certa dor de cabeça&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://robertomoutinho.com.br/blog/grails-2-0-com-mongodb-connection-refused/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Escrevendo um transformador dih para Solr</title>
		<link>http://robertomoutinho.com.br/blog/esrcevendo-um-transformador-dih-para-solr/</link>
		<comments>http://robertomoutinho.com.br/blog/esrcevendo-um-transformador-dih-para-solr/#comments</comments>
		<pubDate>Fri, 20 Apr 2012 17:44:50 +0000</pubDate>
		<dc:creator>moutinho</dc:creator>
				<category><![CDATA[Solr]]></category>

		<guid isPermaLink="false">http://robertomoutinho.com.br/blog/?p=78</guid>
		<description><![CDATA[O primeiro passo de quem está desenvolvendo/configurando o Solr, geralmente é transformar um dado utilizando javascript declarado dentro do proprio arquivo de configuração&#8230; porém por experiência propria, a manutenção deste codigo se torna complexa (por falta de um bom debug) e é especialmente lento no processo de indexação. Eis então que surge o transformador em [...]]]></description>
			<content:encoded><![CDATA[            <script type="text/javascript" src="http://robertomoutinho.com.br/blog/wp-content/plugins/wordpress-code-snippet/scripts/shBrushCpp.js"></script>
            <script type="text/javascript" src="http://robertomoutinho.com.br/blog/wp-content/plugins/wordpress-code-snippet/scripts/shBrushPython.js"></script>
            <script type="text/javascript" src="http://robertomoutinho.com.br/blog/wp-content/plugins/wordpress-code-snippet/scripts/shBrushXml.js"></script>
            <script type="text/javascript" src="http://robertomoutinho.com.br/blog/wp-content/plugins/wordpress-code-snippet/scripts/shBrushJava.js"></script>
<p>O primeiro passo de quem está desenvolvendo/configurando o Solr, geralmente é transformar um dado utilizando javascript declarado dentro do proprio arquivo de configuração&#8230; porém por experiência propria, a manutenção deste codigo se torna complexa (por falta de um bom debug) e é especialmente lento no processo de indexação.</p>
<p>Eis então que surge o transformador em formato de &#8220;lib&#8221; importada para o DIH (<a href="http://wiki.apache.org/solr/DIHCustomTransformer" target="_blank">DIHCustomTransformer</a>).</p>
<p>Se você já sabe que todos os seus documentos sofrerão algum tipo de transformação de dados, você já pode salvar algum tempo e declarar um transformador mais genérico (sem necessidade de declarar quais atributos sofrerão customização). Como por exemplo, um website aonde as url são construidas com algumas tecnicas de SEO combinadas e podem sofrer alteração durante sua edição (tornando uma persistência desta uri em banco uma opção ruim).</p>
<p>Chega de blábláblá&#8230;</p>
<p>Sua classe deverá implementar obrigatoriamente um metodo chamado &#8220;transformRow&#8221;. [ public Object transformRow(Map&lt;String, Object&gt; row) ]<br />
<pre class="brush: java">private static final String IN_TAG = &quot;rawTags&quot;;
private static final String TAG = &quot;tags&quot;;

public Object transformRow(Map&lt;String, Object&gt; row) {

// Obter o valor da coluna retornada do DB.
		String tag = (String) row.get(IN_TAG);

		if (null != tag) {

			String[] tagList = tag.split(&quot;,&quot;);

// adiciona como campo multi-valor as tags j&Atilde;&iexcl; &quot;splitadas&quot; por virgula.
			row.put(TAG,tagList);

// remove o atributo nao tratado do documento a ser indexado. (basta nao declarar em seu schema, mas por boa pratica &Atilde;&copy; interessante remover)
			row.remove(IN_TAG);

		}
}</pre><br />
dificil não ? (LOL)</p>
<p>Apartir deste exemplo básico tudo se torna um jogo e quebra-cabeça.<br />
<pre class="brush: java">public class customTransformer {

	private static final String IN_TAG = &quot;rawTags&quot;;
	private static final String TAG = &quot;tags&quot;;

	private static final String URL = &quot;url&quot;;
	private static final String TITLE = &quot;title&quot;;
	private static final String DOMAIN = &quot;domain&quot;;
	private static final String FOLDER = &quot;folder&quot;;

	public Object transformRow(Map&lt;String, Object&gt; row) {

		String title = (String) row.get(TITLE);
		String domain = (String) row.get(DOMAIN);
		String folder = (String) row.get(FOLDER);

			StringBuffer url = new StringBuffer();
			url.append(&quot;http://&quot;);
			url.append(domain.toLowerCase());
			url.append(&quot;/&quot;);
			url.append(folder.toLowerCase());
			url.append(&quot;/&quot;);
			url.append(lowerCaseStripSpacesAndAccents(title));
			url.append(&quot;.html&quot;);
			String SeoUrl = url.toString();
			row.put(URL, SeoUrl);

		String tag = (String) row.get(IN_TAG);

		if (null != tag) {

			String[] tagList = tag.split(&quot;,&quot;);
			row.put(TAG,tagList);
			row.remove(IN_TAG);

		}

	}</pre></p>
<p>obs: Antes de escrever um transformador customizado para o Solr é necessário ter bom conhecimento de como funciona o <a href="http://wiki.apache.org/solr/DataImportHandler" target="_blank">Data Import Handler</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://robertomoutinho.com.br/blog/esrcevendo-um-transformador-dih-para-solr/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Combinando Memcached, MySQL e codigo C para autenticar usuários de uma API RESTFull.</title>
		<link>http://robertomoutinho.com.br/blog/using-memcached-mysql-inline-c-varnish-cache-to-authenticate-basic-keys-restfull-api/</link>
		<comments>http://robertomoutinho.com.br/blog/using-memcached-mysql-inline-c-varnish-cache-to-authenticate-basic-keys-restfull-api/#comments</comments>
		<pubDate>Mon, 05 Sep 2011 18:24:38 +0000</pubDate>
		<dc:creator>moutinho</dc:creator>
				<category><![CDATA[Varnish]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[inline c]]></category>
		<category><![CDATA[libmemcache]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[rest]]></category>
		<category><![CDATA[restfull]]></category>
		<category><![CDATA[varnish]]></category>
		<category><![CDATA[web scraping]]></category>

		<guid isPermaLink="false">http://robertomoutinho.com.br/blog/?p=50</guid>
		<description><![CDATA[Depois de algum tempo pesquisando (e principalmente inspirado pelo post do Dr. Carter), resolvi implementar uma autenticação de clientes API (RESTfull) que precisava escalar. O intuito deste post é compartilhar o pedaço de codigo (inline C) hoje responsável pela autenticação dos clientes e não como configurar o Varnish Cache para escalar websites. O codigo consiste [...]]]></description>
			<content:encoded><![CDATA[            <script type="text/javascript" src="http://robertomoutinho.com.br/blog/wp-content/plugins/wordpress-code-snippet/scripts/shBrushCpp.js"></script>
            <script type="text/javascript" src="http://robertomoutinho.com.br/blog/wp-content/plugins/wordpress-code-snippet/scripts/shBrushPython.js"></script>
            <script type="text/javascript" src="http://robertomoutinho.com.br/blog/wp-content/plugins/wordpress-code-snippet/scripts/shBrushXml.js"></script>
            <script type="text/javascript" src="http://robertomoutinho.com.br/blog/wp-content/plugins/wordpress-code-snippet/scripts/shBrushJava.js"></script>
<p>Depois de algum tempo pesquisando (e principalmente inspirado pelo post do <a href="http://drcarter.info/2010/04/how-fighting-against-scraping-using-varnish-vcl-inline-c-memcached/">Dr. Carter</a>), resolvi implementar uma autenticação de clientes API (RESTfull) que precisava escalar.</p>
<p>O intuito deste post é compartilhar o pedaço de codigo (inline C) hoje responsável pela autenticação dos clientes e não como configurar o Varnish Cache para escalar websites.</p>
<p>O codigo consiste em pegar a chave de autenticação enviada através de um Header HTTP especifico e verificar sua autenticidade, combinando com a contagem de requests que o cliente possui permissão (tudo isso evitando ao maximo uma chamada ao banco de dados).</p>
<p><pre class="brush: cpp">/* Import these modules in the begining of your VCL code */

C{
#include &lt;string.h&gt;
#include &lt;/usr/local/include/libmemcached/memcached.h&gt;
#include &lt;syslog.h&gt;
#include &lt;/usr/include/mysql/mysql.h&gt;
#include &lt;stdio.h&gt;
}C

/* Place the code inside your &quot;vcl_recv&quot; wherever you want (as longs as your requests passes thru the code) */

C{
      memcached_server_st *servers = NULL;
      memcached_st *memc;
      memcached_return_t rc;
	/* 
	I use a combination of &quot;API Key + Client IP&quot; to count the requests.
	Adapt the key used to suit your needs. 
	*/
      char key[50];
      strcat(key, VRT_GetHdr(sp, HDR_REQ, &quot;\012X-API-Key:&quot;));
      strcat(key, &quot;_&quot;);
      strcat(key, VRT_IP_string(sp, VRT_r_client_ip(sp)));

      memc= memcached_create(NULL);
      servers= memcached_server_list_append(servers, &quot;localhost&quot;, 11211, &amp;rc);
      rc= memcached_server_push(memc, servers);
      syslog(LOG_INFO, &quot;Memcached connection = %s&quot;,memcached_strerror(memc, rc));
	/* If the connection to memcached was succesfull we'll decrement the value of this key. */
      if (rc == MEMCACHED_SUCCESS) {
	rc = memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT, 10);
        uint64_t intval;
        rc= memcached_decrement(memc, key, strlen(key), (uint64_t)1, &amp;intval);

        if (rc != MEMCACHED_SUCCESS) {
	/* 
	If decrement has failed (probably the key is not in cache) we need to authenticate the key on database.
	Remember to create a view (for safety reasons the mysql user is only privileged to use the created view) and to add an index on your table (for a fast read).
	*/
          syslog(LOG_INFO, &quot;Key found in Memcached ? = %s&quot;,memcached_strerror(memc, rc));
	  MYSQL     *conn;
	  MYSQL_RES *res;
	  MYSQL_ROW  row;
	  char rows;
	  char query[200];
	  sprintf(query, &quot;select request-limit from view where api_key = '%s'&quot; ,VRT_GetHdr(sp, HDR_REQ, &quot;\012X-API-Key:&quot;));
	  conn = mysql_init(NULL);
	  if (mysql_real_connect (conn,&quot;localhost&quot;,&quot;user&quot;,&quot;password&quot;,&quot;database_name&quot;,0,NULL,0) != NULL){
	    mysql_real_query(conn,query,strlen(query));
	    res = mysql_store_result(conn);
	    row = mysql_fetch_row(res);

	    if (row) {
		  	syslog(LOG_INFO, &quot;Result != NULL&quot;);
			char *limit = row[0];
			syslog(LOG_INFO,&quot;Key found in MySQL with %s requests total.&quot;,limit);
			rc= memcached_set(memc, key, strlen(key), limit, strlen(limit), (time_t)3600, (uint32_t)0);
			syslog(LOG_INFO, &quot;Key %s stored in Memcached ? = %s&quot;,key,memcached_strerror(memc, rc));
			/*
			If the API Key was found in database we collect the request limit value and store it.
			I also set a 1 hour limit for this memcached object (3600) and log the response code from memcached.
			*/
	    } else {
 			 syslog(LOG_INFO, &quot;Key: %s not found in MySQL.&quot;,VRT_GetHdr(sp, HDR_REQ, &quot;\012X-API-Key:&quot;));
	                 VRT_error(sp, 401, &quot;Unauthorized.&quot;);
        	         VRT_done(sp, VCL_RET_ERROR);
			/* The provided key was not found in database. Return a &quot;401 Unauthorized&quot; code. */
	    }
          } else {
		    syslog(LOG_INFO,&quot;MySQL: Error %u (%s)&quot;,mysql_errno (conn), mysql_error (conn));
                    VRT_error(sp, 500, &quot;Internal server error.&quot;);
                    VRT_done(sp, VCL_RET_ERROR);
			/* In case of a database connection problem we return a &quot;500 Internal server error&quot; code. */
          }
    	  mysql_free_result(res);
	  mysql_close(conn);
        }
        else {
	  syslog(LOG_INFO, &quot;Key found in Memcached ? = %s&quot;,memcached_strerror(memc, rc));
          syslog(LOG_INFO, &quot;Decrement key %s in Memcached ? = %s&quot;,key,memcached_strerror(memc, rc));

          if (intval &lt; 1) {
	    syslog(LOG_INFO, &quot;Key %s limit exceeded. Client Ip = %s&quot;,VRT_GetHdr(sp, HDR_REQ, &quot;\012X-API-Key:&quot;),VRT_IP_string(sp, VRT_r_client_ip(sp)));
            VRT_error(sp, 403, &quot;Forbidden&quot;);
            VRT_done(sp, VCL_RET_ERROR);
		/* If the decremented result from memcached is lower than &quot;1&quot; we return a &quot;403 Forbidden&quot; code. Client requests maxed-out. */
          }
        }
      }
      memcached_free(memc);
      memcached_server_list_free(servers);
}C
</pre></p>
<p>para o carregamento das bibliotecas necessárias, você precisará adicionar ao script de inicialização do Varnish (/etc/sysconfig/varnish) os seguintes parametros:</p>
<p>-p &#8216;cc_command=exec cc -fpic -shared -Wl,-x -L/usr/local/include/libmemcached/memcached.h -L/usr/lib64/mysql -lmysqlclient -lmemcached -o %o %s&#8217;</p>
<p>&nbsp;</p>
<p>obs1: você vai precisar ter instalado em seu servidor o mysql-client &amp; mysql-devel package assim como a libmemcached.</p>
<p>A thank you note to the varnish mailing list which assisted me thru the entire process.</p>
]]></content:encoded>
			<wfw:commentRss>http://robertomoutinho.com.br/blog/using-memcached-mysql-inline-c-varnish-cache-to-authenticate-basic-keys-restfull-api/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

