Um Manifesto!

...

  • Increase font size
  • Default font size
  • Decrease font size

Blog

Game Over: Linux ganhou no Acer 5050!

E-mail Print PDF

Eu tenho um hardware complicado. Meu notebook é um acer 5050 e sempre deu trabalho Linux, mas firme e forte segui com minha saga de suporta-lo 100% no pinguim.

E a pouco tempo essa saga chegou no fim, e é Game Over, com vitória para o usuário, vitória do pinguim!

Basta um kernel recente e o Linux funciona no Acer 5050. Sem truques, sem mágica, sem compilações complicadas com parametros sinistros, agora quando eu quiser atualizar o  kernel, o farei sem medo.

Muito obrigado ao desenvolvedores do Kernel Linux. Tux #win. 

Last Updated on Saturday, 12 September 2009 19:35
 

O Shouter e o TwitterFlow2

E-mail Print PDF

Como disse, o importante é programar. Então como bom nerd e tentando manter o ânimo com projetos pessoais, estou sempre com projetinhos.

Semana passada consegui licenciar com o SHOUTCast(tm) Radio para (re)lançar o Shouter. O Shouter é um player que permite navegar entre as estações de radio online do SHOUTCast(tm) Radio , salvar suas favoritas e ouvi-la, é claro.

Foi um projeto curto, em 2 dias já estava funcional, mais 2 dias estava redondo. Mas demorou quase um mês para licenciar, fora encher de coisas a interface. Mas, enfim, saiu.

E têm também o TwitterFlow, já havia feito o cliente para twitter, mas estava muito insatisfeito com o resultado. Então depois de um tempo resolvi fazer um do zero, ai começou na quinta-feira 3 de setembro o TwitterFlow2, do zero, com o grande diferencial de usar OAuth.

Também já esta online, apesar de estar propenso a muitos erros ainda, e têm bastante o que acertar, mas estou satisfeito com o resultado.

Enfim, é isso. Estou precisando voltar mais ao PHP...

 

Hello World em JavaFX: Faça um streaming com a busca do twitter.

E-mail Print PDF

Não tem HelloWorld mais na moda que o Twitter.

Este artigo sera um tutorial sobre o básico do JavaFX, vai tratar a sintaxe, como construir uma interface básica e acessar um webservice. O Objeto final será um client para busca do twitter, atualizando automaticamente.

Não será um stream propriamente dito pois a API de Streaming do twitter requer autenticação, então para manter mais simples usará atualizações agendas para busca de novos itens. Não vou tratar de nenhuma ferramenta especifica, apenas do código em si, a parte de compilar e rodar fica a cargo da sua IDE. Vamos começar?

O primeiro passo é criar nosso projeto, que se chamará , muito criativamente, Searchr. Vou trabalhar apenas no pacote homônimo, searchr. Vamos primeiro o ponto de entrada na nossa aplicação, que será o Main, então temos o arquivo searchr/Main.fx , lembre-se de configurar sua IDE para usa-lo como ponto inicial.

O primeiro ponto de um aplicativo JavaFx é um objeto “Stage”, cada Stage representa uma janela. É importante notar que a janela é aberta no momento que criamos o Stage, assim que ele é construído. Cada Stage possui então um Scene, que é o conteúdo da janela, aonde vamos colocar nossos elementos gráficos.

O ponto de partida da aplicação é a função “run()”, quando temos o “run” lá criamos nosso stage e iniciamos qualquer outro processo necessário ao inicio da aplicação. Veja como colocamos então uma janela com um texto dentro:

// Main.fx, após imports
var stage: Stage ;
def scene: Scene = Scene {
fill: Color.WHITE
content: [ Text { content: “Hello JavaFx” } ]
}

function run() {
stage = Stage {
title: “Hello JavaFx”
width: 350
height: 500
scene: scene
}
}

Explicando tudo, na sintaxe do javafx temos duas formas de declarar uma variável, como sendo realmente variável ou definitiva, sendo preferível ser definitiva. O formato é então nomeDaVariavel: Tipo.

Temos então a construção de um objeto Scene, veja que na sintaxe declarativa iniciamos cada propriedade no momento da criação do objeto. Nesse caso criei o scene com “fill” branco e um array no conteúdo.

Uma lista é tratada como visto no content do Scene, entre colchetes, com elementos separados por virgula. Criei ainda um texto com conteúdo “Hello JavaFX”. Mais sobre listas mais tarde.

Em seguida declarei um função, nesse caso a principal “run”, aonde começa o programa, quando chega nesse ponto crio a janela que conterá minha UI. Vamos começar a explorar alguns elementos básicos de UI agora.

Minha ideia do aplicativo é extremamente simples, um campo de texto, um botão “Search” e em baixo a lista dos tweets.

Para organizar tudo, criarei um container vertical, o Vbox, e o coloco na cena (Scene). Com conteúdo vazio.

def container: VBox = VBox { spacing: 5, content: [] } ;
def scene: Scene = Scene {
fill: Color.rgb(51,51,51)
content: [ container ]
}

Crio agora a caixa de texto onde vai entrar a busca. E o botão para fazer o busca.

def input: TextBox = TextBox { promptText: “Search...” , action: doSearch, columns: 30};
def button: Button = Button { text: “Search”, action: doSearch };

Veja que temos ai um “action”, aponto ele para uma função “doSearch”, que tem a mesma assinatura que a propriedade “action”, que é uma função sem argumentos e que não retorne nada.

function doSearch(): Void {}

Deixo a função para mais tarde, veja que o tipo de retorno vem depois da declaração. Posso ainda definir assim:

def doSearch = function(): Void {}

Vou colocar esses elementos na mesma linha usando o Hbox, e já o incluo no container vertical.

def searchBar: HBox = HBox { spacing: 5, content: [ input, button] }
def container: VBox = VBox { spacing: 5, content: [ searchBar ] }

Vou declarar agora uma classe para generalizar a interface de cada linha que será o resultado da busca. Será um CustomNode, que é um elemento personalizado.

class SearchLine extends CustomNode {

public-init var profileUrl: String ;
public-init var user: String ;
public-init var text: String;
public var width: Number ;

override function create(): Node {
return HBox {
spacing: 5
content: [
ImageView {
image: Image {
url: profileUrl
, width: 54
, height: 54
, backgroundLoading: true
, placeholder: Image {
url: "{__DIR__}placeholder.png"
width: 54
height: 54
}}
}
Text {
content: “{user}: {text}”
wrappingWidth: bind width – 60
fill: Color.WHITESMOKE
}
]
}
}
}

Temos ai vários elementos para explorar, a declaração da Classe é básica. Temos então os atributos “public-init” que só podem ser alterados na construção do objeto. Width não é public-init pois pode mudar conforme o tamanho da janela mude, você verá mais tarde.

Tenho então que sobreescrever (o override) a função create da classe CustomNode, onde devo retorna o elemento customizado.

Nesse casso fiz uma linha HBox , com uma image e o texto do tweet. Vejam que na imagem defino a URL de onde deve ser carregada, informo para carregar em background, para não travar a UI, e defino uma imagem temporária (placeHolder).

Ai temos algo interessante, uma variável especial __DIR_ indica o diretório do aplicativo. E temos a string. Em Java FX não concatenamos como em Java, mas sim usando a expressão dentro de chaves, como:

def soma = “Soma de {a} + {b} = {a +b}”;

Em seguida temos o elemento texto, novamente com uma string com variáveis, e um limite de largura, aonde haverá quebra automática de linha. E um BIND.

Um bind é uma ligação entre uma variável ou propriedade e uma outra variável ou expressão, assim quando uma muda a outra é atualizada. Quando width mudar, a largura do texto irá acompanhar. Podemos ainda ter casos mais complexo, como expressões e loops, como veremos até o final.

Vamos criar agora o container dos tweets, esse será um pouco mais complexo, pois exibirá apenas parte dos tweets, e terá rolagem, mas isso vai explorar boas partes da linguagem. Então vamos por partes, primeiro a lista em si:

def tweetList: VBox = VBox { spacing: 5 , content: bind for ( tweet in tweets) {
SearchLine{
profileUrl: tweet.profileImage
user: tweet.user
text: tweet.text
width: bind scene.width -15
  } } }

Veja que interessante, eu liguei o conteúdo da lista a um loop, que gera a SearchLine. E garanti que o tamanho do texto vai bater com o tamanho da tela. Vamos definir esses itens faltosos logo:

class Tweet {
public var profileImage :String;
public var user: String ;
public var text: String ;
}
var tweets: Tweet[];

Essa classe vai conter cada tweet, como sendo nosso model. E temos a lista onde armazenamos os tweet achados.

Agora temos um detalhe, que é que não podemos exibir a lista toda por conta do espaço, então criamos um ClipView. Ele funciona contendo o conteúdo, mas exibindo apenas parte dele. Veja:

def clip: ClipView = ClipView {
clipY: 0
clipX: 0
node: tweetList
height: bind scene.height - 30
width: bind scene.width
}

Temos ai nosso ClipView, começando exibindo o começo apenas, contendo o VBox anterior, a altura será sempre o da janela menos 30 (mais ou menos o tamanho da barra de busca), e a largura será o da janela.

Um caso especial sobre o ClipView, é que é pannable. Ou seja, basta “segurar” e arrastar para rolar. Podemos definir ele como “pannable: false” e adcionar um ScrollBar também ou eventos de mouse, mas ai fica para outra oportunidade.

Agora é só inserir o clip no container:

def container: VBox = VBox { translateX: 10, translateY: 5, spacing: 5, content: [ searchBar, clip ] }

Adcionei ainda um posicionamento em X e Y para haver um espaço na janela. Feito a UI, agora é hora de mágica! Vamos ao acesso ao webservice.

Vou usar uma classe chamada AtomTask(podia ser RssTask, FeedTask, ou mesmo genérico HttpRequest), que recupera atom de tempos em tempos. Trabalhamos na função doSearch que definimos antes:

var current: AtomTask ;

function doSearch(): Void {
if(current != null) { current.stop(); }
current = AtomTask {
interval: 1m
location: "http://search.twitter.com/search.atom?q={input.text}"
onFeed: function(feed: Feed) {
delete tweets;
}
onEntry: function(item: Entry) {
insert Tweet {
profileImage: item.links[1].href
text: item.title.text
user: item.authors[0].name
} into tweets ;
}
};
current.start();
input.text = “”;
}

Crio uma variável para conter a Tarefa corrente. Ao fazer a busca, paro a tarefa anterior, e crio uma nova. Defino o intervalo de 1 minuto (é um tipo do JavaFx chamado Duration), a location de acordo com o conteúdo do input.

O evento onFeed é chamado assim que recebemos o Atom, ai eu limpo o array de tweets.

O evento onEntry recebe cada alemento achado no Atom, para cada um eu insiro um novo Tweet no array de tweets.

Em seguida eu inicio a tarefa, e limpo a caixa de texto. Assim como mágica ( #NOT ), o aplicativo está pronto. Agora você pode roda-lo usando webstart, através do jnlp que sua IDE criou(ou não), ou como applet no seu site.

Claro que esta extremamente simples, mas já serve para os principais conceitos do JavaFx, o código final esta no github, no streaming de search de twitter.

Last Updated on Monday, 07 September 2009 20:56
 

InputStream remoto em Java - baixando arquivos

E-mail Print PDF

Passei essa semana por esse problema em um projeto no trabalho.

O caso era realizar o download de um arquivo, no android. O problema era que apesar da conexão estar certa, o arquivo era salvo errado, os bytes estavam errados apesar do tamanho esta quase certo.

Acontece que usei um algorimo básico para baixar escrever no arquivo, primeiro fazia a coneão HTTP:

URL urlCn = new URL(url.toString().trim());
HttpURLConnection conn = (HttpURLConnection) urlCn.openConnection();
conn.setDoInput(true);

E em seguida criava o arquivo: 

File file = new File("downloads", name ); 
if(!file.exists()) {
    try {
      file.createNewFile();
      isNew = true;
    } catch (IOException e) {
      e.printStackTrace();
      return;
    }
}

Então chegava a problemática hora de escrever o conteúdo do arquivo, eu estava usando um algorimo básico, que sempre funciona com InputStreams locais.


int bSize = 1 * 1024 ;
FileOutputStream fos = null;
BufferedInputStream bis = new BufferedInputStream(is,bSize);

try {
   fos = new FileOutputStream(file);
   byte[] buffer = new byte[bSize];
   while(bis.read(buffer) > 0) {
      fos.write(buffer);
   }
   fos.flush();
   fos.close();
   bis.close();
} catch (FileNotFoundException e) {
   e.printStackTrace();
} catch (IOException e) {
   e.printStackTrace();

O algorismo lê, a cada "bSize" e escreve no arquivo, para não ocupar muita memória. 

A pegadinha esta em que nem sempre o InputStream da conexão me retorna a quantidade de bytes que eu pedi, mas eu sempre estava escrevendo o buffer inteiro. Logo se num buffer de 1k, o Stream só me deu 512B, eu estava escrevendo o resto de lixo (bytes da escrita antiga). 

A correção foi alterar o trecho para o código a seguir:

   int len1 = 0;
   while((len1 = bis.read(buffer)) > 0 ) {
      fos.write(buffer, 0,len1);
   }

E todos viveram felizes para sempre. 

 

Google App Engine DataStore com JDO e PHP

E-mail Print PDF

No artigo que explico a configuração inicial para rodar aplicações em PHP no Google App Engine (GAE), cito um pouco sobre a parte de persistência. Neste artigo pretendo aprofundar nesta parte, na prática.

Primeiro é importante lembrar que o GAE não oferece a API do JDBC, assim não podemos acessar bancos externos. Então no PHP não temos as funções comuns de BD, como mysql_connect ou PDO.

O banco de dados usado no GAE não segue um modelo relacional, como a maioria (principalmente no php) esta acostumado. GAE usa o datastore como um banco de dados baseado em Entidades. Essas entidades são como objetos, são na verdade estruturas de dados com chaves e valores.

Interessante notar que as estruturas são “schema-less”, ou seja, não precisam ser pré-definidas, os pares de chave=>valor serão gerados conforme forem enviados. Assim mudanças nos objetos não precisam serem “migradas” ao banco de dados.

Outro ponto importante nisto, é que, como não estamos lidando com dados relacionais, o pensamento de JOINs deve ser repensado. Na verdade, de preferencia, esquecidos. O datastore funciona muito bem em casos de relações proprietárias exclusivas, como classes “embedded”, mas JOIN como estamos acostumados em bancos relacionais são um inferno.

As entidades devem ser definidas como classes Java, usando as anotações devidas, e em seguida precisam ser “Enhanced” para gerarem o código da persistência em si. Vamos começar agora a gerar as nossas entidades.

O projeto será simples, como o : Teremos apenas User e Note. O pacote principal será o “app”, e o modelo estará em “app.model”. Então precisamos das pastas “src/app/model”. Faça o download do projeto e o coloque próximo ao SDK.

Vamos definir primeiro uma interface para identificar nossos objetos persistentes, essa será útil mais tarde. Em /src/app/model crie IModel.java .

Como disse, primeiro definimos nossas entidades, em Java. Primeiro a classe User, em src/app/model/User.java . Sem as partes das anotações, definimos a classe normalmente. Ele possui alguns dados básicos, e uma lista de Notas. Os atributos são privados e usamos acessores.

Agora vamos adcionar as anotações, e temos o User persistente. A primeira coisa é a anotação “PersistenceCapable” que define que a classe é persistente. Temos ainda a tag “PrimaryKey”, e a tag “Persistent”, que define que o atributo deve ser salvo. O “ValueStrategy” define que esse atributo será auto-gerado, então o próprio datastore vai gerar nossas chaves.

É importante ainda o “deatached=true” pois permite usar o objeto mesmo quando o datastore for fechado.

Repare porem que a lista de notas não é persistente, e sim “NotPersistent”, a tag é colocada para garantir que não vai haver conflito. Como disse antes vamos fazer as junções na mão.

Em seguida mapeamos a classes Note, sem a anotações. Temos alguns dados. Reparem no campo Text. Uso Text ao invés de String porque na datastore o string tem limite, então usamos o Text. Pode reparar ainda que temos o “User owner” que a parte de cá da relação, mas também temos o “Long userId” que é o que vai ser usado na realidade. Repare no método que define o “owner” automaticamente estou definindo o “userId”.

Fazemos então as anotações, dessa vez nada novo.

Agora que temos nossas classes mapeadas, podemos partir para parte de acesso ao banco de dados. Vou usar um modelo bem simples, além do PMF (padrão, já tem no blankphp) vou usar apenas uma classe auxiliar Storage (em /src/app) que vai me permitir acessar de forma geral o datastore. Agora vamos acompanhar a classe src.app.Storage método a método.

O primeiro método é o “getAll”, ele me permite recuperar todos os objetos de uma determinda classe, basta receber uma String que é o nome completo da classe ( “app.model.User” ou”app.model.Note”), e me retorna uma lista com elas.

Na primeira linha eu faço o acesso ao gerenciador de persistência, e digo que meus objetos não devem ficar alocados nele. Depois declaro a lista de model que vou retornar., crio a query, e a executo e armazeno o seu retorno em uma lista temporária.

Pegadinha número um. Para liberar os objetos vou passa-los a uma segunda lista.

Então, se houver objetos a retornar ( !=null e size >=1), eu crio minha lista, e a preencho com os objetos da temporária. Ainda garanto a associação com a persistência deles.

Caso qualquer coisa dê errado ou não tenha objetos, eu retorno nulo mesmo. E , lembre-se sempre, fecho o datastore.

O segundo , getWhere, funciona idêntico ao primeiro exceto que recebe uma clausula “where” e a adciona a query.

O terceiro, get, retorna um objeto pelo seu ID, sua chave primaria. Ele funciona de forma semelhante aos anteriores, exceto que na query eu identifico que quero pelo ID. E, ao invés de formar uma lista, eu recupero o primeiro item desta. Retorno este item (ou nulo) e, sempre, fecho o datastore.

O método sequinte, o quarto, é o put. Ele é o encarregado por salvar (tanto inserir, quanto atualizar) um objeto no datastore. Como pode ver a chamada é simples, temos apenas o “makePersistent”, que já usamos antes.

A lógica é simples, se eu passo um objeto ao makePersistent que não veio de uma consulta (que eu não recuperei com um dos métodos acima) será gerado um INSERT, caso seja um objeto já persistente, ou seja, que veio do datastore ele será atualizado.

O último método agora é o delete, sem mistérios.

Agora podemos compilar as classes com a seguinte linha, na raiz do projeto, use o comando:

“ant compile”

E “enhance” as classes com o comando:

“java -cp ../appengine-java-sdk/lib/appengine-tools-api.jar:war/WEB-INF/classes:../appengine-java-sdk/lib/user/appengine-api-1.0-sdk-1.2.1.jar com.google.appengine.tools.enhancer.Enhance war/WEB-INF/classes/app/model/User.class war/WEB-INF/classes/app/model/Note.class”

Enfim, a parte em Java esta pronta, no próximo vamos partir para a parte em PHP.

Last Updated on Friday, 14 August 2009 13:41
 

Do VirtualBox ao KVM, e como usar o KVM

E-mail Print PDF

Esse é um artigo que achava que tinha escrito uns anos atrás, mas parece que não. Enfim, história primeiro:

Quando comecei nesse "negócio" de usar Linux e SL, uma das primeiras maravilhas que me deparei foi o Qemu, e assim conheci o maravilhoso mundo da virtualização. Fato que o Qemu não é um virtualizador, mas sim um emulador. E era lento, por ser emulador, mesmo com a evolução do kqemu. Mas era poderoso. Inclusive o Android usa o Qemu para seu emulador do SDK. Mas com a necessidade, depois de um tempo migrei para um virtualizador, e o escolhido foi o ótimo VirtualBox. Por que sim. 

Estava muito feliz com o VBox, mas sempre fiquei de olho o KVM. O Kvm é parte do kernel do linux(logo opensource), que permite virtualizar sistemas através de instrução especificas existentes nos processadores modernos(ou nem tão modernos). Enfim, é, assim como o qemu, uma forma extremamente simples de ter um SO rodando como se fosse "mais um" processo do sistema. Muito simples mesmo. E, como bônus, o kvm se baseia no qemu modificado e pode usar as ótimas ferramentas do mesmo.

Eu ia mudar antes, mas como o VBox estava indo tão bem acabei enrolando, mas desde o aniversário do meu notebook, onde ganhou mais ram e um kernel recompilado o VBox perdeu desempenho. Devo ter sido eu a fazer algo errado, mas já queria migrar mesmo o passei ao KVM.

 

Desktops Virtuais
 

 

A performance esta ótima, basicamente tenho VMs do Win XP,  OpenSolaris (para aprender) e um Debian de standby. Estou feliz com isso, qualquer dia entra o Win 7 aí na história... ou não.

Acabou a  história, vamos ao que interessa. Para migrar as imagens do VBox para o formato compacto qcow do qemu, usa primeiro as ferramentas do próprio VBox, na pasta do Harddrive, geralmente ~/.VirtualBox/HardDrivers:

$  VBoxManager clonehd -format RAW old.vdi nova.img 

Depois convertemos a imagem bruta para o formato qcow2:

$ qmeu-img convert -f raw nova.img -O qcow nova.qcow

"Tcharã!" está pronta a nova imagem. Lendo assim parace fácil, mas imagens grandes demoram vários minutos para cada passo.

Uma pegadinha é que instalações do Windows podem precisar serem reparadas. Vejam bem, não precisa reinstalar. Coloque o CD, boot pelo cd, comece como se fosse instalar. Ao chegar na escolha de partições, pressione "R" sobre a partição do windows e continue. 

Usa o kvm é ridiculamente fácil, primeiro certifique-se de ter te-lo instalado e levante o modulo para sua plataforma:

# aptitude install kvm

# modprobe kvm-amd

Ou "kvm-intel". Garanta ainda que seu usuário possui permissões no dispositivo /dev/kvm adicionando-o ao groupo kvm:

# useradd username kvm

# chown kvm.kvm /dev/kvm 

A Sintaxe básica é a mesma do qemu, veja um exemplo:

$ kvm -hda nova.qcow -cdrom /dev/cdrom -usb -m 1024 -smp 2  -sd card.img -boot c

Isso diz que o kvm vai ter , na ordem, a imagem nova.qcow como hda (primeiro disco), cdrom no disposivo de sistema, usb ativado, 1G de ram, 2 núcleos, card.img com sdcard e vai bootar no hda (c). Muitas outras opções estão disponiveis no "kvm -help" ou "man kvm".

Você pode ainda ser mais fresco e usar o virt-manager, e ter uma interface gráfica para administrar suas VMs. Esta disponível no seu repositório linux favorito, e não esqueça o python-libvirt (ou python2.5-libvirt). Ou o Qemulator, Ou o AQemu.

Enfim, o KVM suporta live migrations, vários SOs e esta ai evoluindo bem. Confira um ótimo conteúdo em http://www.linux-kvm.org/

Seja mais feliz virtualizando.  

Last Updated on Wednesday, 12 August 2009 13:43
 


Page 2 of 11