RSS

Arquivo mensal: maio 2010

Simples agenda usando DBIx::Class em Perl

neste exemplo mostro como usar DBIx::Class + SQLite para um trabalho simples uma agenda eletronica
vamos fazer o feito ,primeiro precisamos criar as tabelas

CREATE TABLE agenda (
nome VARCHAR(50),
telefone INT(10),
cidade VARCHAR(50)
);

add num banco chamado example.db dentro duma pasta chamada DB ótimo temos nosso banco
criamos um diretório com nome “MyDatabase” dentro desde diretório criamos Main.pm com conteudo

package MyDatabase::Main;
use base qw/DBIx::Class::Schema/;
__PACKAGE__->load_classes(qw/agenda/);

1;

feito isso criamos outra pasta com nome Main e dentro desta pasta criamos o arquivo agenda.pm
contendo dados das tabelas

package MyDatabase::Main::agenda;
use base qw/DBIx::Class/;
__PACKAGE__->load_components(qw/PK::Auto Core/);
__PACKAGE__->table(‘agenda’);
__PACKAGE__->add_columns(qw/ nome telefone cidade /);

1;

ótimo volte para pasta inicial onde tem o DB e o MyDatabase crie uma rquivo chamado agenda.pl com conteudo

#!/usr/bin/perl -w
#http://search.cpan.org/~ash/DBIx-Class-0.08010/lib/DBIx/Class/Manual/Intro.pod#It%27s_all_about_the_ResultSet
use MyDatabase::Main;

my $schema = MyDatabase::Main->connect(‘dbi:SQLite:db/example.db’);
Inicio:
mostra();
my @all = $schema->resultset(‘agenda’)->all;
my $all = $schema->resultset(‘agenda’);
print “total de cadastros $alln”;

print “digite o numero da opçãon”;
chomp($escolha=);
if (!!$escolha) {

####### busca simples
if($escolha eq “4”) {
print “digite o que buscarn”; chomp($busca1=);
my $rs = $schema->resultset(‘agenda’)->search(
{ nome => “$busca1” }
);
while (my $track = $rs->next) {
my $nome=$track->nome; my $tel=$track->telefone; my $local=$track->cidade;
print “$nome $tel $localn”;
}
goto Inicio;
}
####### listando lista de nomes
if($escolha eq “3”) {
my $rd = $schema->resultset(‘agenda’);
while (my $track = $rd->next) {
my $nome=$track->nome; my $tel=$track->telefone; my $local=$track->cidade;
print “$nome $tel $localn”;
}
sleep 2;
goto Inicio;
}
####### add cadastro
if($escolha eq “1”) {
print “digite um nomen”; chomp($nome=);
print “digite o telefonen”; chomp($telefone=);
print “digite a cidaden”; chomp($cidade=);
if((!!$nome) && (!!$telefone) && (!!$cidade)) {
my $novo = $schema->resultset(‘agenda’)->new(
{ nome => “$nome”, telefone => “$telefone”, cidade => “$cidade”});
$novo->insert;
}
goto Inicio;
}
###### remover cadastro
if($escolha eq “2”) {
print “digite um nome para remover da agenda n”; chomp($nome=);
$schema->resultset(‘agenda’)->search({ nome => “$nome” })->delete;
goto Inicio;
}

if($escolha eq “5”) { exit; }

}
sub mostra {
print ”
By Cooler
|——————————————–|
| Agenda com SQLite e DBIx::CLass |
|——————————————–|
| 1- adicionar cadastro |
| 2- remover cadastro |
| 3- listar cadastros |
| 4- procurar cadastro |
| 5- sair |
|——————————————–|
“;
}

para rodar “perl agenda.pl” pronto você tem uma agenda com DBIx::Class mais informações vide no CPAN
isso só foi uma receita simples de como pode ser usado este módulo

link sobre mais informações do módulo
http://search.cpan.org/~ash/DBIx-Class-0.08010/lib/DBIx/Class.pm

 
Deixe um comentário

Publicado por em maio 11, 2010 em Perl

 

Iniciando com CakePHP

neste “Post” vamos aprender
a instalar um framework e fazer uma agenda para intranet
com o uso do mesmo.

CakePHP a cada dia anda sendo mais usado e elogiado
seria um framework em PHP para fazer aplicações ala
RAILS isso mesmo imagine fazer tarefas com CRUD
possibilitando fazer um blog em 10 minutos,este framework
é chamado de CakePHP é compativel com
PHP4 e PHP5 já tem muitos plugins e já tem alguns livros falando
desta maravilhosa ferramenta…

cakephp

Antes que os programadores em PHP me crucifique
*não vou falar do “Symphony” pois ele não roda no PHP4
*não vou fazer as coisas na raça nem usando pear
*não vou falar do Zend nem outros frameworks de php
*não vou falar de de rails com ruby pois servers para hostar
ruby geralmente custam 10reais mais caros…
*não vou falar de Catalyst com Perl por que server que
aceite perl geralmente são mais caros.

Motivo “Dinheiro=tempo+POO+MVC”
Simplesmente pelo fato do CakePHP permitir desenvolvimento
rápido e rodar na maioria dos servidores nacionais e ser
seguro 😉

chega de blablabla e vamos ao Rock and roll
primeiro temos que preparar o ambiente adapte a parte de
instalação de acordo com seu “OS” sendo *BSD|MacOS use
ports se for Linux use o pacote especifico para sua
distribuição…

no exemplo eu instalei num debian

sudo apt-get install apache2 php5 libapache2-mod-php5 /
mysql-server libapache2-mod-auth-mysql php5-mysql phpmyadmin

sudo ln -s /usr/share/phpmyadmin/ /var/www/phpmyadmin

pronto preparamos a cozinha para o cozinheiro
agora vamos arrumar o Gás do forno xD,vamos arrumar
a configuração do “Apache 2″

tente deixar como no exemplo /etc/apache2/sites-enabled/000-default

DocumentRoot /var/www/
#cake/app/webroot/

Options All
AllowOverride All

Options All
AllowOverride All
Order allow,deny
allow from all


arrumamos a permissões agora vamos habilitar o Mod Rewrite
(módulo nativo do apache2),responsável por permitir a reescrita
de URLs, habilidade indispensável ao funcionamento do CakePHP
de o comando

a2enmod rewrite

feito isso estamos quase prontos para trabalhar com cakephp
vamos instalar ele…

apt-get install cakephp cakephp-scripts

pronto agora sim vamos fazer um bolo para testar nosso forno
primeiramente crie uma database no MySQL depois crie a tabela

CREATE TABLE telefones (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
nome VARCHAR(50),
tell VARCHAR(20),
extra TEXT,
created DATETIME DEFAULT NULL,
modified DATETIME DEFAULT NULL
);

agora vamos configurar o cake para sua database

cooler@gnu:/var/www$ mkdir agenda; cake bake agenda

Welcome to CakePHP v1.2.0.7296 RC2 Console
—————————————————————
App : www
Path: /var/www
—————————————————————
Bake Project
Skel Directory: /usr/share/php/cake/console/libs/templates/skel
Will be copied to: /var/www/agenda
—————————————————————
Look okay? (y/n/q)
[y] > y
Do you want verbose output? (y/n)
[n] > n
—————————————————————
Created: agenda in /var/www/agenda
—————————————————————

Creating file /var/www/agenda/views/pages/home.ctp
Wrote /var/www/agenda/views/pages/home.ctp
Welcome page created
Random hash key created for ‘Security.salt’
CAKE_CORE_INCLUDE_PATH set to /usr/share/php in webroot/index.php
CAKE_CORE_INCLUDE_PATH set to /usr/share/php in webroot/test.php
Remember to check these value after moving to production server
Your database configuration was not found. Take a moment to create one.
—————————————————————
Database Configuration:
—————————————————————
Name:
[default] >
Driver: (db2/firebird/mssql/mysql/mysqli/odbc/oracle/postgres/sqlite/sybase)
[mysql] >
Persistent Connection? (y/n)
[n] >
Database Host:
[localhost] >
Port?
[n] >
User:
[root] > root
Password:
> minha senha
Database Name:
[cake] > blog
Table Prefix?
[n] >
Table encoding?
[n] >

—————————————————————
The following database configuration will be created:
—————————————————————
Name: default
Driver: mysql
Persistent: false
Host: localhost
User: root
Pass: *******
Database: blog
—————————————————————
Look okay? (y/n)
[y] > y
Do you wish to add another database configuration?
[n] >

Creating file /var/www/agenda/config/database.php
Wrote /var/www/agenda/config/database.php

definimos nosso primeiro aplicativo e configuração do nosso banco de dados
perfeito! agora vamos fazer o sistema

cooler@gnu:/var/www$ cd agenda; cake bake

Welcome to CakePHP v1.2.0.7296 RC2 Console
—————————————————————
App : agenda
Path: /var/www/agenda
—————————————————————
Interactive Bake Shell
—————————————————————
[D]atabase Configuration
[M]odel
[V]iew
[C]ontroller
[P]roject
[Q]uit
What would you like to Bake? (D/M/V/C/P/Q)
> m
—————————————————————
Bake Model
Path: /var/www/agenda/models/
—————————————————————
Possible Models based on your current database:
1. Post
2. Telefone
Enter a number from the list above, type in the name of another model, or ‘q’ to exit
[q] > 2
Would you like to supply validation criteria for the fields in your model? (y/n)
[y] > n
Would you like to define model associations (hasMany, hasOne, belongsTo, etc.)? (y/n)
[y] > n

—————————————————————
The following Model will be created:
—————————————————————
Name: Telefone
Associations:
—————————————————————
Look okay? (y/n)
[y] > y

Baking model class for Telefone…

Creating file /var/www/agenda/models/telefone.php
Wrote /var/www/agenda/models/telefone.php
Cake test suite not installed. Do you want to bake unit test files anyway? (y/n)
[y] > n
—————————————————————
Interactive Bake Shell
—————————————————————
[D]atabase Configuration
[M]odel
[V]iew
[C]ontroller
[P]roject
[Q]uit
What would you like to Bake? (D/M/V/C/P/Q)
> c
—————————————————————
Bake Controller
Path: /var/www/agenda/controllers/
—————————————————————
Possible Controllers based on your current database:
1. Posts
2. Telefones
Enter a number from the list above, type in the name of another controller, or ‘q’ to exit
[q] > 2
—————————————————————
Baking TelefonesController
—————————————————————
Would you like to build your controller interactively? (y/n)
[y] > y
Would you like to use scaffolding? (y/n)
[n] > y

—————————————————————
The following controller will be created:
—————————————————————
Controller Name: Telefones
var $scaffold;
—————————————————————
Look okay? (y/n)
[y] > y

Creating file /var/www/agenda/controllers/telefones_controller.php
Wrote /var/www/agenda/controllers/telefones_controller.php
Cake test suite not installed. Do you want to bake unit test files anyway? (y/n)
[y] > n
—————————————————————
Interactive Bake Shell
—————————————————————
[D]atabase Configuration
[M]odel
[V]iew
[C]ontroller
[P]roject
[Q]uit

agora veja o Seu Bolo no navegador http://localhost/agenda/telefones
sem palavras o CakePHP fez tudo , ainda deu opção de SORT
com os elementos tudo feito,edit,add,remove…
veja como ficou no meu PC

Uploaded with ImageShack.us

QuickPost Quickpost this image to Myspace, Digg, Facebook, and others!

termino o “Post” por aqui quem gosto do framework entre e veja o manual em PT no link
http://book.cakephp.org/pt

curiosidade
pra quem não entendeu a brincadeira de Bolo e de forno cozinha etc…
saiba que “Cake” em inglês é bolo os developers do CakePHP brincão
muito com estes termos querendo ai passar algumas metáforas do
aplicativos de forma mais humorada,por exemplo o site do CakePHP
onde fica plugins e dicas para o mesmo chamase “bakery” ou seja
padaria… http://bakery.cakephp.org/

 
4 Comentários

Publicado por em maio 11, 2010 em PHP

 

Apostila de Perl

bom galera eu escrevi esta apostila a um ano atrás terminei ela nem tive tempo de passar corretor ortográfico deixa para próxima…
camel
é mais para iniciantes da linguagem ensina sockets,spiders,banco dados DBM e SQL e outras coisas como regex…

Download

 
2 Comentários

Publicado por em maio 9, 2010 em Perl

 

Socket em Linguagem C

Formato esta em HTML

ÍNDICE
| +01 – Introdução
| +02 – Explanação ao TCP/IP
| +03 – BSD Sockets
| +04 – Funções read(),send() e exemplo cliente HTTP
| +05 – Funções listen(),Bind(),accept() e servidor http exemplo
| +06 – Na prática fazendo um FUZZER TCP
| +07 – Servidor e Cliente com Fork
| +08 – Servidor de comandos e Scanner de portas
| +09 – Simple Socket Library
| +10 – Explanação ao UDP e exemplo de Servidor e cliente
| +11 – Exemplo UDP Flood
| +12 – Portabilidade com Windows,exemplo um Whois
| +13 – Conclusão
| +14 – Bibliografia
| +15 – Agradecimentos
| +16 – Sources externas

baixe em http://bugsec.googlecode.com/files/artigo_socket_em_C.zip

 
2 Comentários

Publicado por em maio 9, 2010 em Linguagem C

 

Usando NetBSD como Desktop

Artigo formato PDF http://bugsec.googlecode.com/files/netbsd_artigo4.pdf
NetBSD

 
2 Comentários

Publicado por em maio 9, 2010 em NetBSD

 

entendendo CouchDB beta paper

meu primeiro aqui no WP 🙂

vou adicionar um paper meu que preciso melhorar ortografia até por isso
está beta

Entendendo CouchDB
=========================
couchdb
Termo “Couch” é um acrônimo para “Cluster of Unreliable Commodity Hardware”
(Conjunto de Hardware Commodity Não-Confiáveis), “refletindo o objetivo
do banco de dados ser extremamente escalável, oferecendo alta disponibilidade
e confiabilidade, mesmo quando executando em um hardware que é tipicamente
suscetível a falhas”.

Em suma CouchDB é um banco de dados orientado a documentos, feito com “Erlang”
em conta de sua lendária programação multitarefa e desempenho,diferente de
bancos relacionais que estamos acostumados ver como MySQL,SQLite e PostgreSQL.

Da mesma forma que os SGBDRs oferecem o SQL como interface de
consulta, o CouchDB oferece uma interface de consultas adaptada aos
seus princípios arquiteturais baseados na Web,através do Representational
State Transfer (REST), que é utilizado como forma de inserir, atualizar,
extrair e remover dados do CouchDB.

Popularmente público rotula como NoSQL, este tipo de banco de dados assim
como “MongoDB”,muitos dizem que é errado pois usa SQL, mas este rótulo acabou
colando.

Quanto ao termo ACID no CouchDB, todo o layout de arquivos e sistema de
commit está baseado nestes princípios, o que resulta na garantia de um
estado sempre consistente do arquivo de banco de dados. A atualização de
documentos são serializadas e os leitores de banco nunca são bloqueados ou
nunca têm de esperar por escritores ou outros leitores. A leitura de documentos
pode ser realizada por diversos clientes sem ser bloqueada ou interrompida por
atualizações concorrentes. Esta característica se deve pela utilização de um
modelo baseado no algoritmo MVCC, onde cada cliente vê um retrato consistente
do banco de dados do começo até o final da operação de leitura.
(Apache CouchDB, Technical Overview, 2008)

*Antes de ir direto para prática vamos ao conceito REST

O REST utiliza um subconjunto de métodos disponíveis no protocolo
HTTP para realizar suas operações. De acordo com a especificação do
protocolo HTTP em (Fielding, et al., 2004) e a arquitetura definida por Fielding
(Fielding R. T., 2000), os métodos utilizados pelo REST são:

1. GET: uma operação de somente leitura. Esta operação é
idempotente e segura, significando que não importa a quantidade
de vezes que a operação seja aplicada, ou seja, o recurso seja lido,
o resultado deve ser sempre o mesmo. O ato de ler um documento
HTML não deve mudar o documento. Segura significa que            ao
invocar uma operação GET o estado do servidor não irá ser
alterado, ou seja, além da do consumo de recursos de CPU e
memória do servidor, nada mais será afetado (Burke, 2008);

2. PUT: geralmente relacionada com uma operação de inserção ou
atualização. Assim como o GET, também é idempotente, porém ao
usar o PUT, o cliente deve ter em mãos o recurso que está se
criando ou atualizando. A operação é idempotente pois ao enviar
mais de uma requisição não irá afetar o serviço em questão. Burke
(Burke, 2008) faz uma analogia com o processador de textos
Microsoft Word: “não importa a quantidade de vezes que você clica
no botão Salvar, o arquivo que será armazenado será logicamente
o mesmo documento”;

3. DELETE: utilizado para remover serviços. É idempotente, ao passo
que remover algo que já não está lá não é um problema;

4. POST: a única operação não idempotente e insegura do HTTP.
Este método não sofre muitas limitações exatamente para prover
ao sistema a possibilidade de executar outras operações fora do
contexto do GET (leitura), PUT (inserção e atualização) e DELETE
(remoção). No REST, é utilizada para modelar um serviço de
fabricação de objetos. Quando se usa o método PUT, sabe-se
exatamente o que está sendo criado, com o POST, é atribuído ao
servidor a tarefa de criar o objeto.

*Instalando o CouchDB

No linux

No meu debian foi tiro e quéda

apt-get install couchdb

No meu gentoo também

emerge -pv couchdb

fedora de um amigo do IRC

yum install couchdb

como eu não sei seus repositórios e nem sua distro vamos então

-requerimentos,caso use fedora troque apt-get por yum
$ sudo apt-get install automake autoconf libtool help2man
$ sudo apt-get install build-essential erlang libicu-dev libmozjs-dev  \
libcurl4-openssl-dev curl

-instalando o pacote na raça
$ wget http://apache.mirrors.esat.net/couchdb/0.10.0/apache-couchdb-0.10.0.tar.gz
$ tar xzvf apache-couchdb-0.10.0.tar.gz
$ cd apache-couchdb-0.10.0
$ ./configure
$ make
$ sudo make install
$ sudo adduser couchdb
$ sudo mkdir -p /usr/local/var/lib/couchdb
$ sudo mkdir -p /usr/local/var/log/couchdb
$ sudo mkdir -p /usr/local/var/run
$ sudo chown -R couchdb /usr/local/var/lib/couchdb
$ sudo chown -R couchdb /usr/local/var/log/couchdb
$ sudo chown -R couchdb /usr/local/var/run
$ sudo cp /usr/local/etc/init.d/couchdb /etc/init.d
$ sudo update-rc.d couchdb defaults
$ sudo /etc/init.d/couchdb start

*no MacOS e derivados de BSD procure pelos Ports

no MacOS por exemplo caso você não saiba o que é e não tenha
ports entre aqui http://www.macports.org/install.php
instale ports depois de o comando para instalar o couchdb

$ sudo port install couchdb curl

*no FreeBSD você pode usar “pkg_add -rv couchdb”

Bom tendo instalado o CouchDB tudo OK vamos ao teste

$ curl http://127.0.0.1:5984

como saida deve resultar “Wellcome do CouchDB”

Bom abra no seu navegador vamos ver o “Futon” gerenciador visual do
couchDB feito em javascript usando Jquery http://127.0.0.1:5984/_utils/index.html

Aberto o Futon vá para “test suite” e depois “Run” espere se tiver tudo OK sua instalação
não vai dar nenuma mensagem de erro. terminado o test não brinque agora com futon pois vamos
fazer testes práticos para entender algumas paradigmas…

Bom vamos usar o “Curl” para fazer comunicação com CouchDB assim
você entende a prática sem códigos longos em linguagens,estou
tentando ser mais transparente possível…

argvs do curl
“-d” usaremos para comunicação com JavaScript Object Notation (JSON)
“-X” usaremos para cominicação HTTP para enviar “GET,PUT,POST e DELETE.
“-v” isso é opcional caso queira ver os detalhes no modo de verbose

================== Comandos no Banco

criando banco chamado “contacts” e outro chamado “books”
curl -X PUT http://127.0.0.1:5984/contacts
curl -X PUT http://127.0.0.1:5984/books

listando todos os bancos
curl -X GET http://127.0.0.1:5984/_all_dbs

Deletar banco “books”
curl -X DELETE http://127.0.0.1:5984/books

para pegar informações do banco
curl -X GET http://127.0.0.1:5984/contacts

================== Comandos Documentos

criando documentos no banco exemplo “johndoe”
curl -X PUT http://127.0.0.1:5984/contacts/johndoe -d ‘{}’

caso queira ver o documento criado
curl -X GET http://127.0.0.1:5984/contacts/johndoe

caso queira deletar um documento especifico
curl -X DELETE http://127.0.0.1:5984/contacts/johndoe?rev=1-795358690

vamos criar um documento diferente com as hashs
{
“firstName”:”Joe”,
“lastName”:”Lennon”,
“email”:”joe@joelennon.ie”
}

curl -X PUT http://127.0.0.1:5984/contacts/joelennon -d ‘{“firstName”:\
“Joe”,”lastName”:”Lennon”,”email”:”joe@joelennon.ie”}’

então listamos…

curl -X GET http://127.0.0.1:5984/contacts/joelennon
{“_id”:”joelennon”,”_rev”:”1-
45597617″,”firstName”:”Joe”,”lastName”:”Lennon”,”email”:”joe@joelennon.ie”}

podemos vamos mudar o ID…
curl -X COPY http://127.0.0.1:5984/contacts/joelennon -H “Destination: johnsmith”
vendo o que foi criado
curl -X GET http://127.0.0.1:5984/contacts/johnsmith

agora seguindo outro documento

analisando a hash do JSON
{
“firstName”:”John”,
“lastName”:”Smith”,
“email”: [
“johnsmith@example.com”,
“jsmith@example.com”
],
“phone”:”(555) 555-5555″
}

curl -X PUT http://127.0.0.1:5984/contacts/johnsmith -d ‘{“_rev”:”1-
4152282996″,”firstName”:”John”,”lastName”:”Smith”,”email”:[“johnsmith@example.com”,”jsmith@e
xample.com”],”phone”:”(555) 555-5555″}’

================== Comandos VIEWs exemplos

Bom view seria um tipo de filtro para definirmos qual dos dados vão ser mostrados
vamos passar os dados

view sem filtro equivalente a um “select * from table”… em bancos relacionais
curl -X GET http://127.0.0.1:5984/contacts/_all_docs

agora usamos view com uma ordem
curl -X GET http://127.0.0.1:5984/contacts/_all_docs?descending=true

mesma view porem limitamos para apenas mostrar 1 documento
curl -X GET http://127.0.0.1:5984/contacts/_all_docs?descending=true\&limit=1

view que mostra todas as documentoss e seus conteudos
curl -X GET http://127.0.0.1:5984/contacts/_all_docs?include_docs=true

Uma view que lista documentos por ID em sequencia
curl -X GET http://127.0.0.1:5984/contacts/_all_docs_by_seq

================== Views na prática exemplo Blog

Bom agora sim você pode brincar no “Futon” hehehe

Bom leitor seguindo os exemplos você reparou que um simples javascript ínves
de comandos com “curl” pode trabalhar muito bem com CouchDB,você pode mesmo
fazer um blog só com javascript e couchdb sim é possível,Como não sou um
mestre em JavaScript demoraria muito para fazer tal feito mas posso mostrar
a teoria.

Estrutura de um documento de blog

{
“titulo”: “Este é um post no seu blog”,
“autor”: “mestre”,
“data”: “01/04/2010 12:38:00”,
“corpo”: “hoje estreando nosso blog com CouchDB “,
“comentarios”: [
{
“nome”: “curinga”,
“texto”: “Gostei muito do post!”,
“data”: “08/04/2010 2:31:09”
},
{
“nome”: “Fulano”,
“texto”: “Muito interessante, continue”,
“data”: “09/04/2010 1:17:31”
}
]
}

bom acessando http://localhost:5984/_utils/database.html?blog/_temp_view
podemos usar códigos javascripts para fazer um filtro  nos documentos

uma view para vermos apenas os comentários seria

function (doc){
if(doc.comentarios) emit(doc.comentarios, {texto: doc.texto});
}

agora uma view apenas para mostrar corpo do post

function (doc){
if(doc.corpo) emit(doc.corpo);
}

programação simples com javascript

agora vamos fazer listar somente o post do corpo criando uma view
procurando form “temporary view” você vai ver dois formularios para
sources

map function

function (doc){
if(doc.corpo) emit(doc.corpo);
}

reduce function

function(keys,values){
return keys;
}

clique no botão para salvar

irá aparecer dois formularios

escreva no primeiro “postcorpo”,segundo “corpopost” que seria nome da view

execute no navegador para verificar “http://localhost:5984/blog/_design/postcorpo/_view/corpopost”
veja sua View do documento personalizada listando somente “corpo” do POST

bom é isso ai posts futuros mais tarde…

 
Deixe um comentário

Publicado por em maio 9, 2010 em NoSQL