Ubuntu 8.10 lançado oficialmente

Uma das distribuições mais populares do Linux – o Ubuntu – foi lançado oficialmente na sua versão 8.10 (release de outubro do 8) que é LTS (long term support – até 2010). Estou a puxar para ver. Já tive com o RC nas mãos mas acabei por não o usar (correctamente).

Info está disponível no site : www.ubuntu.com ou melhor ainda, na versão da comunidade portuguesa : http://www.ubuntu-pt.org/. Podem encontrar repositórios tugas do ISO do CD aqui.

Construir um ubuntu ( ou uma distribuição própria, por assim dizer..)

Nestes últimos dias, a minha mente tem estado algo dorido com a quantidade de info nova que tenho estado a adquirir. Tenho planeado há algum tempo construir um pequeno servidor em próprio para manter em casa, especialmente destinado a armazenar dados – SVN, máquinas virtuais, servidor de testes, backups, NAS… enfim.. um multifunções centralizado.

Finalmente surgiu a oportunidade de adquirir alguns dos elementos necessários – já tinha dois discos SATA de 640Gb que encontrei a bom preço (até subiram de preços quando desde que as adquiri), e investi no restante hardware, para suportar tudo. Conta com um processador Quad Core (Intel Q6600) que estava a um bom preço, importado, e componentes para misturar com alguns já existentes… uma maquina para servir a função durante uns bons anos, espero. Naturalmente e gostando do DIY como gosto, a caixa será um projecto de trabalho manual.

Mas depois vem o problema maior.. configurar o SO para manter isto tudo. E aqui começa a confusão. A ideia de virtualizar parece-me bem e útil, mas o como é q me está a deixar algo perplexo. Confesso que não estava a par das tecnologias de virtualização (para além de clientes como o VMWare, Virtualbox e VirtualPC). A palavra Hypervisor passou a fazer parte do meu vocabulário, o VMWare ESXi, o Xen Server, e o KVM pareceram ser opções interessantes, para usar como uma camada entre o hardware e os SOs.

Aliás parte da confusão vem daí – usar um sistema destes, hipervisor, mínimo, e correr N SOs sobre ele, ou optar por um SO Linux base e abrir os VMs que necessito, quando necessitar? Usar algo como um hipervisor, como base e depois outros por cima, preocupa-me… se houver avaria de configurações (e tendo em conta o q Murphy diz e o pouco que conheço desta tecnologia) que risco corre os dados nos SOs implementados. Tendo em conta que uma função importante do sistema é o de backup, não quero arriscar perder os dados por não poder aceder a eles por o hipervisor base ter dado o berro…. Possível? Arriscado? Antes de optar pela solução de SO “normal” com VMs, devo testar o esquema de hipervisor. O ESXi é gratuito mas tem algumas limitações, que não sei se são graves ou não. Xen parece interessante e tenho um colega que já usou e a quem vou certamente cravar informação. O KVM também pode ser ideal.

De qualquer forma, optando por um esquema “tradicional”, resta escolher o sabor de Linux a usar. Infelizmente, na minha opinião, há demasiado por onde escolher. Achava o esquema de licenciamento do Windows, chato (Home, Home premium, Business, Ultimate…), mas mesmo sendo gratuito, o Linux consegue ser complicado. Base Debian vs. Slax vs. outros; Gestor Gnome vs. KDE vs. XFCE vs…; etc, etc, etc. A possibilidade de escolha é bom, não haja duvida, mas demasiado acho que não é de todo o ideal. Por exemplo, se no caso do gestor de janelas houvesse apenas 1 geral, “themed”, talvez a gestão de tudo o resto (e aplicações compatíveis, etc) podesse ser melhorado. Também acho que o KDE tem o problema da letra “k”, especialmente antes dos nomes dos aplicativos. Deviam ter escolhido uma vogal, como a Apple… 😀

Decidi num portatil velho testar o Ubuntu Server e encaixar um ambiente gráfico. Vi-me grego para meter o Gnome a que estou habituado, e mesmo assim n consegui passar da linha de comandos, por mais info que achasse na web. Até que hoje, encontrei isto:

Trata-se de uma série de posts, que tem por base uma instalação do Ubuntu mínimo “Ubunto Minimal Install”, instalado a partir de um ISO de 9.5MB. A base do Ubuntu é instalado (pelo que vi numa VM, ocupa 667MB – certamente com pacotes puxados da net). O autor nos posts simplesmente configura o sistema ao seu gosto. Vale a pena a leitura, mas o que queria apresentar, principalmente, é como adicionar um dos ambientes gráficos possíveis a esta instalação, ou a uma instalação como o server.

sudo apt-get install xorg xfce4 gdm synaptic

Este commando deve resolver (pode ser necessário um “sudo apt-get update” previamente). Instala o Xorg com o sistema gráfico, xfce4 para o gestor de janelas, o GNOME display manager ao nivel do arranque gráfico e login, e o Synaptic para instalar programas no ambiente gráfico. o commando “startx”, arranca o sistema, naturalmente. A partir daí é adicionar ao gosto do freguês. 😀

VSX – DSLs -> T4

Nomenclatura complicada? Nem por isso. VSX significa Visual Studio Extensability, e a DSL é Domain Specific Languages. Finalmente comecei a implementar a minha própria DSL, que descreva a minha framework de programação, e (espero) que gere a maioria das classes que utilizo. Entre blogs e o livro Domain Specific Development with Visual Studio DSL Tools (Microsoft .Net Development), vou recolhendo o conhecimento da matéria e tentando implementar os conceitos. Para todos os efeitos, já consigo criar algumas classes/objectos da minha estrutura e gerar (ou transformar a definição em) código.

De qualquer forma, uma ferramenta muito interessante e importante é o T4 (Text Template Transformation Toolkit). Permite pegar na nossa definição de estrutura e converter para código, num conjunto de declarações. O problema que existe com este processo é que, infelizmente, o VS não tem implementado nenhum sistema de color-coding ou intelisense para o efeito, o que complica a tarefa. Por outro lado, a Clarius Consulting apresenta o T4 Editor que adiciona o color-coding ao IDE para os ficheiros de transformação. Na versão não gratuita (que custa $99), é adicionado o suporte de intelisense, que acredito que possa ser uma mais valia real. Para já estou a usar a versão comunitária.

De notar, após instalação, é necessário reinicializar o Experimental Hive da DSL, para assumir o editor. Para tal deve seguir a Iniciar -> Programas -> Visual Studio SDK -> Tools -> Reset Experimental Hive e aguardar que o programa complete.

Bibliotecas de Log

Logging – guardar registos de actividades das aplicações – é uma tarefa extremamente importante no desenvolvimento de uma aplicação, e ajuda muito a resolver as dores de cabeça que vão surgindo. Eu tenho usado, nas minhas aplicações, algumas classes de log construídas de raiz – num caso escrevendo os registos para XML, noutro, para um ficheiro texto simples (CSV).

Mas na verdade, existem já alguns módulos pela web dedicados a esta tarefa. Algumas efectuam o registo apenas de erros das aplicações (.NET) como é o caso do Elmah que falei anteriormente, ou do Spacebin que é um serviço externo de armazenamento dos registos. A vantagem destes é que captam automaticamente os erros, sem necessitar de inserir código específico À tarefa – apenas uma entrada no ficheiro de configuração.

Mas num comentário que surgiu no post do Elmah (e que não tomei a devida atenção), estava referido o Nlog, um projecto aberto com suporte para diversos típos de registos (trace, debug, info, erro…) e múltiplos repositórios (dbs, ficheiros, serviços, etc…). Este parece muito completo e quero experimentar! A documentação parece bastante completa e intuitiva.

Outro similar ao NLog, mas que utiliza uma abordagem diferente em termos do esquema dos repositórios, é o log4net que faz parte dos serviços de log da Apache. Novamente, múltiplas tipos e repositórios de registo, e OpenSource.

Não havendo razão para construir algo especifico a uma aplicação, estas são, certamente óptimas soluções!

Lucene ou PostgresSQL

Estou num certo impasse num projecto. Necessito de indexar um repositório de documentos, como também armazenar dados sobre esses documentos, numa aplicação. A aplicação terá um conjunto extra de funcionalidades, para além da gestão documental, e que utilizarei uma base de dados como suporte. mas para os documentos, dada a modelariedade do sistema, quer um indexador com base em sistema de ficheiros, quer com base em pesquisa de texto livre numa base de dados, são opções válidas. Simplesmente a manipulação dos dados (organização) e o cruzamento de dados teria que ser planeada consoante a forma de indexação.

Percori uma série de artigos e experiências na tentativa de chegar a uma conclusão. Uma hipótese era o Index Server da Microsoft que tinha sido usado num projecto universitário sobre o qual laborei. Pedi opinião a um colega que mantém o projecto e recomendou evitar… Sobrou o Lucene, que armazena os indices no sistema de ficheiros e tem uma versão .NET e o PostgresSQL, que sendo aberto e funcionando sobre o Windows, pareceu-me uma óptima escolha parta o suporte de dados. Ambos indexam o texto do documento, se bem que esse texto deve ser extraído, por exemplo, no caso dos PDFs. Decidi testar ambos para de alguma forma comparar e verificar se um é claramente melhor que outro.

Primeiro passo, criar um dataset. Usei cerca de 10000 mensagens de email, da qual tive que extrair os documentos em attachment (que é efectivamente o conjunto de dados que vou indexar na aplicação). Sobre esse processo falerei noutro post, que por si só é bastante interessante. Dos emails tenho cerca de 10000 emails, 2500 dos quais PDF.

Próximo passo, indexar ambos e comparar pesquisas. Para o caso do Lucene, utilizei um exemplo do KeyLimeTie. O exemplo inclui a biblioteca do Lucene.Net e um projecto de interface de utilizador, para indexar e pesquisar. Foi necessário efectuar uma pequena alteração para incluir a indexação de PDFs (os .doc funcionou nativamente no exemplo). Para o efeito, criei um novo tipo de documento PDFDocument, similar ao Document que já estava definido, e alterei apenas o pedaço de código que define o campo de texto a armazenar no Lucene:

FileInputStream fi = new FileInputStream(new java.io.File(f.FullName));

PDFParser parser = new PDFParser(fi);
parser.parse();
COSDocument cd = parser.getDocument();
PDFTextStripper stripper = new PDFTextStripper();
String text = stripper.getText(new PDDocument(cd));
cd.close();
            
doc.Add(Field.Text("contents", text));

Este processo utiliza a biblioteca do PDFBox, que apesar de ser Java, é utilizável através de outra referência, o IKVM .

para proceder á indexação, separei o formato PDF dos restantes num switch/case e adicionei ao IndexWriter um PDFDocument em vez de um Document

case "pdf":
     objIndexWriter.AddDocument(FileDocument.PDFDocument(objFile as FileInfo));
     mlngNumDocsIndexed += 1;
     break;

Indexar os documentos todos demorou aproximadamente 65 minutos (9830 documentos, 580 não indexados, 181 com erro). O índice (a pasta) ocupava cerca de 360MB). Posteriormente re-indexei apenas os PDF com o resultados de 23minutos para 2551 documentos, 580 não indexados, 181 com erro).

Para o Postgres, criei uma base através do pgAdmin III, com uma tabela:

CREATE TABLE "DocTest"
(
  "docID" integer NOT NULL DEFAULT 0,
  docfile character varying(300),
  "docText" text,
  "docVector" tsvector,
  id serial NOT NULL,
  CONSTRAINT "DocTest_pkey" PRIMARY KEY (id)
)

e com um trigger para criar o tsvector (vector com os termos e localização do módulo tsearch2).

CREATE TRIGGER tsvectorupdate2
  BEFORE INSERT OR UPDATE
  ON "DocTest"
  FOR EACH ROW
  EXECUTE PROCEDURE tsvector_update_trigger('docVector', 'pg_catalog.english', 'docText');

também importante foi a criação do indice GIN sobre o vector:

CREATE INDEX textsearch_idx
  ON "DocTest"
  USING gin
  ("docVector");

Em termos de aplicação, utilizei a base do exemplo do Lucene, mas modifiqeui o processo de indexação, claro. Extraí o texto e inseri os dados na BD, o método de extração dos dados do PDF é identico:

public class DocumentoIndexavel
{
    public int DocID { get; set; }
    public string DocFile { get; set; }
    public string DocText { get; set; }
}

public class DocDAL
{
    public static int Save(DocumentoIndexavel doc)
    {
        NpgsqlConnection conn = new NpgsqlConnection("Server=127.0.0.1;Port=5432;User Id=postgres;Password=postgresDB;Database=IndexerTest;");
        conn.Open();
        
        NpgsqlCommand command = new NpgsqlCommand("insert into \"DocTest\" (\"docID\", \"docfile\", \"docText\") values(" + doc.DocID +",'"+doc.DocFile+"','"+doc.DocText.Replace("'","")+"')", conn);
        Int32 rowsaffected;

        try
        {
            return command.ExecuteNonQuery();
        }
        catch (Exception e)
        {
            throw e;
        }
        finally
        {
          conn.Close();
        }
    }

}

Consegui em termos de tempos de indexação, este foi feito em dois tempos (devido a um bug q tinah no meu código) mas a app identificou 4093 ficheiros, indexando 3549 e os restantes com erros em cerca de 37 minutos.

Em ambos os casos houve um largo conjunto de campos não indexados, devido, especialmente, a problemas de abertura de ficheiros ou de codificação do mesmo. Mas para o efeito do teste essa situação não era grave.

À partida sabia que o caso da base de dados seria naturalmente mais lenta. Entre conectar à BD, e processar o insert, certamente que o tempo de execução seria mais longa que o da escrita para ficheiro no Lucene. De qualquer forma, a diferença encontrada não foi tão elevada quanto a que estava à espera.

Em temros de pesquisa, há algumas diferenças quer no conjunto de resultados, quer nos tempos:

Lucene Postgres
Indexação
ficheiros indexados 2551 3549
tempo indexação 23min. 37minutos
Pesquisa
“europass” 465 hits / 184ms 718 hits / 287ms
“sql” 10 hits / 60ms 132 hits / 17ms
“postgres” 6 hits / 80ms 9 hits / 20ms
“psicologia” 208 hits / 80ms 0 hits / 200ms*
“psicologia | stress” 244 hits / 72ms 120 hits / 20ms

Há resultados aceitaveis e outros muito estranhos. Por exemplo “psicologia” retornou resultados correctamente no Lucene e não no Postgres, apesar de “psicolog” ser um “stem” presente na coluna de vector. A generalidade das pesquisas parecem ser suficientemente rápidas, quer num sistema, quer noutro. Ainda vou ter de investigar melhor o porquê da falha na palavra “psicologia” (se alguem souber, agradeço comentário).

Apesar de o Postgres ser mais lento na indexação (em massa) penso que o vou manter. Tornará a gestão da aplicação mais simples (menos um repositório) e permitirá efectuar cruzamento de dados directamente na base, através das relações entre tabelas.

Three C# 2.0/3.0 Syntaxes That You Didn’t Know But Were Afraid to Ask

Um link interessante, com algumas novidades do C# 3.0. Enquanto que o primeiro ponto apresentado na página fala da declaração de propriedades, que já referi aqui anteriormente, os dois seguintes para mim são novidade. Gostei especialmente da novidade no operador ternário ?:, que num teste a null, em vez do formato do C# 2.0 :

Objecto obj1 = null;
Objecto obj2 = (obj1 == null ? new Object() : obj1);

pode ser escrito como :

Objecto obj1 = null;
Objecto obj2 = (obj1 ?? new Object());

As três demonstrações de sintaxe no site de Adam Tibi.

Frases…

Eles não precisam de um Magalhães, precisam é de ma-galhetas – Mohad Sabre Reluzente

Por acaso ontem tive a oportunidade de ver o Magalhães no Media Markt. O portátil até é bastante interessante. parece ser mais ergonómico que os restantes miniPortáteis, especialmente com os botões do rato. As teclas são pequenas na mesma, mas enfim a dimensão do portatil não permite mais. Mais um ponto a favor – o ecrã maior.