Set up a Vagrant machine for Grails development

Recently I’ve tried several times to integrate Vagrant in my development flow, without success. So, now that I have to start
Grails development I decided to setup a development environment first.

I used Vagrant with Virtualbox and Puppet for provisioning.

For the impatient, you can clone this repo and go with vagrant up to get a fully functional grails
environment. If you want to know what’s inside, keep on reading.

Initial setup

First install Vagrant and Virtualbox. Then create a folder and initialize the Vagrant machine:

$ mkdir vagrant_grails && cd vagrant_grails
$ vagrant box add base http://files.vagrantup.com/precise32.box
$ vagrant init base

Then open the newly created Vagrantfile and add these lines (or uncomment the relevant ones):

config.vm.provision :puppet do |puppet|
puppet.manifests_path = "manifests"
puppet.manifest_file = "default.pp"
puppet.module_path = "modules"
end

Vagrant will look for a default.pp file under the manifests folder and for any missing modules
under the modules folder. So let’s create them:

$ mkdir modules
$ mkdir manifests
$ touch manifests/default.pp

Installing required Puppet modules

We’ll need some modules from the Puppet forge: specifically apt and stdlib. You can clone them
under the modules folder, or you can download the archives and extract them. It’s up to you.

Installing Java

We’re ready to start. We need Java for Grails to work, so let’s get this settled. Unfortunately
since Java was acquired from Oracle it isn’t available as a package in Ubuntu repositories. So we’ll
need to add a ppa that has a package that will let us download the Java installer. The problem is,
this package require us to accept a license agreement. So we’ll need to automatically accept it.
Write this in the default.pp:

class grails {
    include apt
    apt::ppa { "ppa:webupd8team/java": }

    exec { 'apt-get update':
        command => '/usr/bin/apt-get update',
        before => Apt::Ppa["ppa:webupd8team/java"],
    }

    exec { 'apt-get update 2':
        command => '/usr/bin/apt-get update',
        require => [ Apt::Ppa["ppa:webupd8team/java"], Package["git-core"] ],
    }

    package { ["vim",
        "curl",
        "git-core",
        "bash"]:
        ensure => present,
        require => Exec["apt-get update"],
        before => Apt::Ppa["ppa:webupd8team/java"],
    }

    package { ["oracle-java7-installer"]:
        ensure => present,
        require => Exec["apt-get update 2"],
    }

    exec {
        "accept_license":
        command => "echo debconf shared/accepted-oracle-license-v1-1 select true | sudo debconf-set-selections && echo debconf shared/accepted-oracle-license-v1-1 seen true | sudo debconf-set-selections",
        cwd => "/home/vagrant",
        user => "vagrant",
        path => "/usr/bin/:/bin/",
        before => Package["oracle-java7-installer"],
        logoutput => true,
        }
}

include grails

The tasks are very simple: we update the repositories, add the webupd8team ppa, then we update the
repositories again. Then we install the Java installer and set the flag to accept the license,
without it asking us. In this way we’ll get a fully automated installation.

Installing Grails

Now we need to install Grails. The steps are very similar: we’ll add a PPA (as it is stated in the
Grails docs) and install the package. We’ll also need to set the JAVA_HOME environment variable
that is needed by Grails. Here is the full Puppet manifest:

class grails {
    include apt
    apt::ppa { "ppa:webupd8team/java": }
    apt::ppa { "ppa:groovy-dev/grails": }

    exec { 'apt-get update':
        command => '/usr/bin/apt-get update',
        before => Apt::Ppa["ppa:webupd8team/java"],
    }

    exec { 'apt-get update 2':
        command => '/usr/bin/apt-get update',
        require => [ Apt::Ppa["ppa:webupd8team/java"], Apt::Ppa["ppa:groovy-dev/grails"], Package["git-core"] ],
    }

    package { ["vim",
        "curl",
        "git-core",
        "bash"]:
        ensure => present,
        require => Exec["apt-get update"],
        before => Apt::Ppa["ppa:webupd8team/java"],
    }

    package { ["oracle-java7-installer"]:
        ensure => present,
        require => Exec["apt-get update 2"],
    }

    exec {
        "accept_license":
        command => "echo debconf shared/accepted-oracle-license-v1-1 select true | sudo debconf-set-selections && echo debconf shared/accepted-oracle-license-v1-1 seen true | sudo debconf-set-selections",
        cwd => "/home/vagrant",
        user => "vagrant",
        path => "/usr/bin/:/bin/",
        before => Package["oracle-java7-installer"],
        logoutput => true,
    }

    package { ["grails-ppa"]:
        ensure => present,
        require => Package["oracle-java7-installer"],
    }

    exec { "add_java_home":
        command => '/bin/echo "export JAVA_HOME=/usr/lib/jvm/java-7-oracle" >> /home/vagrant/.bashrc',
    }
}

include grails

Starting the machine

Now you only need to start your machine.

$ vagrant up
$ vagrant ssh

Multiple Sum with different conditions in MySQL

Today I was working on my last project that involves some statistics on data. I had a table like this:

sample table
]1 My table, with time and data fields.

I needed the daily, monthly and yearly sum of the value field. The simplest approach was to have three different queries to retrieve the needed values:

--day
SELECT SUM(value) 
FROM table 
WHERE DATE(time)=CURDATE();
-- month
SELECT SUM(value) 
FROM table 
WHERE MONTH(time)=MONTH(CURDATE()) AND YEAR(time)=YEAR(CURDATE());
-- year
SELECT SUM(value) 
FROM table 
WHERE YEAR(time)=YEAR(CURDATE());

But I wasn’t satisfied. I wanted to have all three values using only one query. So I searched for this issue and this is the resulting query:

SELECT 
  SUM(CASE WHEN DATE(time)=CURDATE() 
    THEN value 
    ELSE 0 end) AS value_day,
  SUM(CASE WHEN MONTH(time)=MONTH(CURDATE()) AND YEAR(time)=YEAR(CURDATE()) 
    THEN value 
    ELSE 0 end) AS value_month,
  SUM(CASE WHEN YEAR(time)=YEAR(CURDATE()) 
    THEN value 
    ELSE 0 end) AS value_year
FROM table

Using the CASE construct, we increment independently the three values so that each row that satisfies the condition gets summed up.

Git Tip: show modified files between two commits

If you need the list of files that were modified between a commit and the latest one you can use git diff with the --name-only parameter:

git diff --name-only 360c150 HEAD

You can use the same command to show the modified files between two commits. Just replace HEAD with a commit hash:

git diff --name-only <commit1> <commit2>

Sapere prima di fare (sulla coincidenza)

Ecco un altro episodio che mi ha insegnato come sia necessario sapere prima di fare.

Il compito che mi era stato assegnato era semplicissimo: mostrare una data formattata in JavaScript, tipo 7 Ottobre 2012. Che difficoltà poteva esserci?

Continue reading “Sapere prima di fare (sulla coincidenza)”

Error handling in C: una panoramica personale

Il C non fornisce un meccanismo standard per la gestione degli errori interno al linguaggio (come le eccezioni) quindi è compito del programmatore decidere come procedere.

Le prime volte che ho programmato in C, pensavo di risolvere la questione facilmente, semplicemente emulando le funzioni della libreria standard. Purtroppo mi sono dovuto scontrare con la dura realtà: le interfacce della libreria standard sono parecchio discordanti su come segnalare una situazione di errore.

Ad esempio atoi restituisce 0 se non riesce a convertire la stringa passata in ingresso, il che è strano, perché 0 è un elemento del dominio della funzione. Infatti il programma:

//Esempio di output di atoi
//

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    const char uno[] = "uno";
    const char due[] = "2";
    const char zero[] = "0";

    int num1 = atoi(uno);
    int num2 = atoi(due);
    int num0 = atoi(zero);

    printf("atoi("uno") vale %dn", num1);
    printf("atoi("2") vale %dn", num2);
    printf("atoi("0") vale %dn", num0);

    return 0;
}

produrrà il seguente output:

[[email protected]]$ ./atoi.out 

atoi("uno") vale 0
atoi("2") vale 2
atoi("0") vale 0

Oppure le funzioni della famiglia *alloc, che restituiscono NULL in caso di errore ed un puntatore all’area di memoria allocata in caso di successo, oppure ancora printf che restituisce il numero di caratteri stampati in caso di successo ed un numero negativo in caso contrario.
Insomma sembra che ogni funzione voglia dire la sua sull’argomento.

Tabula rasa: una libreria da zero

Sviluppare una libreria da zero porta quindi alcuni vantaggi.
Uno di questi è la possibilità di creare delle interfacce coerenti che consentano di presumere la posizione dei parametri e i valori di ritorno delle funzioni, tanto per fare un esempio, oppure di gestire coerentemente le situazioni d’errore.

Facendo alcune ricerche ho notato che esistono due orientamenti principali per la gestione degli errori in C:

  • Restituire lo stato dell’operazione, passando eventuali parametri di output via puntatore
  • Inserire in ogni metodo della libreria un parametro di output contenente lo stato dell’operazione

Restituire lo stato dell’operazione

In questo modello, si creano interfacce che restituiscono sempre un booleano (oppure un intero), indicando l’esito dell’operazione, ad esempio:

//Definizione di myFun
bool myFun(int InParam, int *OutParam);
//Implementazione di myFun
bool myFun( int InParam, int *OutParam )
{
    //Se non ci sono problemi il valore di ritorno sarà true
    bool status = true;

    if( condizioniFavorevoli ) {
        *OutParam = InParam * 2;
    } else {
        //ERRORE! Computazione fallita!
        status = false;
    }

    return status;
}                    

La variabile condizioniFavorevoli rappresenta una possibile situazione di errore in cui potrebbe incorrere myFun, mentre il parametro di uscita OutParam è passato tramite puntatore.
Un possibile utilizzo di questa funzione potrebbe essere il seguente:

/* Test per myFun
 * Compilare con -DFALSE per simulare una condizione di errore
 */
#include <stdio.h>
#include <stdbool.h> //C99
#include <stdlib.h>

#ifndef FALSE
bool condizioniFavorevoli = true;
#else
bool condizioniFavorevoli = false;
#endif

//Definizione di myFun
...

int main(void)
{
    bool status;
    int result;

    status = myFun( 3, &result );
    if( !status ) {
        fprintf(stderr, "Errore in myFunn");
        exit(1);
    }

    printf("Il risultato di myFun: %dn", result);

    return 0;
}

//Implementazione di myFun
...

Un possibile miglioramento sul tema, come consigliato in questa risposta su StackOverflow è quello di creare un tipo che contenga tutti i possibili errori utilizzati nella libreria, ed utilizzarlo al posto del semplice booleano, rendendo il codice più espressivo. Ad esempio:

/*
 * errors.h
 *
 * */

#ifndef STATUS_ERROR
#define STATUS_ERROR

typedef enum 
{
    SUCCESS,
    E_DIVIDE_ZERO,
    E_PASS_ONE
} STATUS;

#endif

#include "errors.h"

STATUS print_divide_ten(int input)
{
    STATUS ReturnStatus;

    ReturnStatus = SUCCESS;

    if( input == 0 ) {
        ReturnStatus = E_DIVIDE_ZERO;
    } else if( input == 1 ) {
        ReturnStatus = E_PASS_ONE;
    } else {
        printf("Faccio la divisione %dn", 10 / input);
    }

    return ReturnStatus;
}

L’utilizzo è praticamente lo stesso del caso precedente, solo che in questo caso è possibile decidere come comportarsi a seconda del valore di ritorno.
Aggiungendo una funzione che trasponga il codice di errore in un messaggio significativo per l’utente si ha a disposizione una buona infrastruttura per la gestione degli errori:

void explain_error_code( STATUS code )
{
    switch(code)
    {
        case SUCCESS:
            printf("Tutto okn");
            break;
        case E_DIVIDE_ZERO:
            printf("È stata tentata una divisione per zeron");
            break;
        case E_PASS_ONE:
            printf("Il valore uno non è accettato");
            break;
        default:
            printf("Status code sconosciuton");
            break;
    }
}

Stato passato tramite puntatore

L’altro modello di gestione degli errori consiste nell’utilizzare il valore di ritorno della funzione per un eventuale output, mentre lo stato è passato tramite un parametro della funzione.

La funzione di esempio si trasformerebbe nel modo seguente:

int myFun2( int InParam, bool *Status )
{
    *Status = true;

    if( condizioniFavorevoli ) {
        return InParam * 2;
    } else {
        *Status = false;
    }

    return -1;
}

Mentre un possibile esempio di utilizzo sarebbe:

int main(void)
{
    bool status;
    int result;

    result = myFun2( 3, &status );
    if( !status ) {
        fprintf(stderr, "Errore in myFunn");
        exit(1);
    }

    printf("Il risultato di myFun: %dn", result);

    return 0;
}

Chiaramente anche in questo caso è possibile utilizzare una struct contenente le diverse tipologie di stati di ritorno da utilizzare nel programma chiamante.

Considerazioni

Ho letto commenti a favore e contro dell’uno e dell’altro metodo di gestione degli errori: c’è chi ritiene che l’output gestito tramite valore di ritorno sia più “naturale”, e chi invece sostiene che un eventuale situazione d’errore passi inosservata utilizzando un parametro di output.

Personalmente, ritengo che le due notazioni siano equivalenti in quanto, soprattutto in linguaggi come il C, il controllo degli errori debba essere ai limiti del maniacale.
Piuttosto credo sia meglio concentrarsi sulla coerenza delle interfacce: ovvero scegliere un metodo di gestione degli errori per la libreria in sviluppo, e mantenere sempre lo stesso stile. In questo modo si facilita il lavoro all’utilizzatore finale della libreria, che può contare su un comportamento quantomeno prevedibile degli strumenti che ha a disposizione.

Bonus: implementare le eccezioni in C

Facendo ricerche su questo argomento ho appreso che è possibile simulare la gestione delle eccezioni in C utilizzando la coppia di funzioni setjmp/longjmp.

Una prima implementazione è possibile trovarla sul sito di Francesco Nidito, mentre per una trattazione più approfondita è possibile consultare C Interfaces and Implementations: Techniques for Creating Reusable Software.

Per un altro esempio d’uso delle funzioni setjmp/longjmp, potete consultare questo post dell’amico Gian Paolo “JP” Ghilardi

Deragliamento??

Certe volte sembra che Linux ti voglia mettere alla prova! Cioè non gli basta che tu hai lasciato i prati verdi delle installazioni “AVANTI-AVANTI-AVANTI-ATTESA-FINE” per un più misterioso mondo fatto di tar, source, xzvf, make, install….no. Periodicamente, ti trovi ad installare qualcosa, dovrebbe andare tutto a buon fine e invece ti ritrovi enigmatici errori…Stasera mi ero messo bellin bellino, deciso a reinstallare ruby on rails sulla mia nuova Kubuntu Gutsy Gibbon, quando mi ritrovo un :

ERROR: While executing gem … (Gem::GemNotFoundException)
Could not find rails (> 0) in any repository

e quand’è cosi non ti resta che affidarti a San Google, sperando che qualcuno abbia avuto gli stessi tuoi problemi (sarà iettatura??), e che li abbia risolti…Fortunatamente è stato cosi…e ora sono pronto per “Cavalcare i binari” (in inglese [Ridin’ the Rails ndr] fa molto più figo, non c’è che dire….:S)
Saluti!