Semplici Database con GDBM per Linux

Da qualche tempo a questa parte l’uso dei motori SQL ( Structured Query Language ) come PostgreSQL, MySQL o mSQL per gestire database, sta prendendo notevolmente piede. Si tratta di una soluzione che da un lato consente di operare molto facilmente sui dati, ma che porta a dover avere un server dati e quindi un consumo elevato di risorse. Per piccoli e semplici database quindi, ecco che spunta l’ipotesi di utilizzare le librerie gdbm come ottima alternativa ad un complesso motore SQL.
La libreria gdbm discende per concezione da dbm e ndbm, con lo scopo di superarne i limiti arbitrari e produrre codice OpenSource. L’alta efficienza di gdbm deriva dal ridotto numero di funzioni implementate:

  • aprire una tabella in sola lettura o scrittura
  • leggere un record conoscendone la chiave
  • scrivere un record come coppia chiave / altri campi
  • cancellare un record conoscendone la chiave
  • scorrere la lista dei record
  • chiudere una tabella

Una tabella può essere aperta in lettura da più processi, mentre solo da uno nel caso di apertura in scrittura, per garantire l’integrità dei dati. Per aprire una tabella si utilizza la funzione

gdbm_open(file, dimensione_blocco, modo, permessi, errori)

  • File è il path completo della tabella da aprire.
  • Dimensione_blocco serve quando gdbm crea la tabella per la prima volta, è un multiplo di 2 con minimo di 512; normalmente in ambiente Linux si utilizza 4096.
  • Modo può avere questi valori: GDBM_READER per aprire la tabella in sola lettura, GDBM_WRITER per aprirla in scrittura, GDBM_WRCREAT come il precedente e creando la tabella se non esiste e GDBM_NEWDB come il precedente ma creando sempre una nuova tabella.
  • Permessi indica i bit di protezione che deve avere la nuova tabella e si comporta come chmod per i permessi dei file che abbiamo visto in uno scorso articolo.
  • Errori è la funzione che gdbm chiama in caso di errori fatali e può essere NULL per utilizzare la funzione di default.

Il valore di ritorno della funzione gdbm_open è di tipo GDBM_FILE e va usato per ogni riferimento futuro alla tabella. Una volta aperta una tabella, soprattutto quando è in scrittura, occorre chiuderla per rilasciare le risorse utilizzando la funzione gdbm_close ovviamente con l’handle della tabella aperta.
La libreria gdbm tratta in modo opaco i record di una tabella, cioè non ne conosce il contenuto e li vede semplicemente come array di byte. Il tipo di dato su cui opera gdbm per le chiavi ed i valori si chiama datum ed è una struttura composta da:

char* dptr
int dsize

Il primo punta ai dati veri e propri, mentre il secondo ne specifica la lunghezza. Per leggere un record si utilizza la funzione:

gdbm_fetch(tabella, chiave)

quindi basta avere l’handle della tabella e la chiave per trovare un valore, attenzione perché la funzione carica in memoria il dptr del datum con malloc, quindi una volta utilizzato occorre liberare la memoria con free. Per scrivere un record invece si usa la funzione:

gdbm_store(tabella, chiave, valore, flag)

oltre alla tabella dobbiamo dare sia la chiave che il valore, entrambi di tipo datum, quindi un flag che può essere: GDBM_INSERT o GDBM_REPLACE, credo che siano molto semplici da comprendere le differenze tra i due. Per cancellare un record si utilizza la funzione:

gdbm_delete(tabella, chiave)

credo che non ci sia bisogno di alcuna spiegazione. Vediamo quindi un semplicissimo esempio per toccare con mano la programmazione con la libreria gdbm ed in particolare l’inserimento di due valori per riempire l’archivio.

/* File data.c
           Compilazione: gcc -Wall -o data data.c -lgdbm */

#include "stdio.h"
#include "gdbm.h"

int main(int argc, char** argv)
{
      GDBM_FILE data;

      datum key1 = {"1", 1};
      datum val1 = {"Rossi", 5};

      datum key2 = {"2", 1};
      datum val2 = {"Bianchi", 7};

      data = gdbm_open("clienti.db", 4096, GDBM_NEWDB, 0644, NULL);
       if (!data)
      {
               printf("Errore aprendo il file dei clienti\n");
               return -1;
       }

       if (gdbm_store(data, key1, val1, GDBM_INSERT) != 0)
      {
               printf("Errore nell'inserire la prima coppia di valori\n");
               gdbm_close(data);
               return -1;
       }

       if (gdbm_store(data, key2, val2, GDBM_INSERT) != 0)
       {
               printf("Errore nell'inserire la seconda coppia di valori\n");
               gdbm_close(data);
               return -1;
       }

       gdbm_close(data);
       printf("Tutto è andato liscio come l'olio!\n");

       return 0;
}

Su una Ubuntu 10.04 dovrete installare il pacchetto di sviluppo di gdbm che se non mi sbaglio si chiama libgdbm-dev. Ora che abbiamo caricato i dati in archivio possiamo leggerli:

/* File data.c
           Compilazione: gcc -Wall -o data data.c -lgdbm */

#include "stdio.h"
#include "string.h"
#include "malloc.h"
#include "gdbm.h"

int main(int argc, char** argv)
{
        GDBM_FILE data;

        datum key;
        datum val;

        data = gdbm_open("clienti.db", 4096, GDBM_READER, 0644, NULL);
        if (!data)
        {
                printf("Errore aprendo il file dei clienti\n");
                return -1;
        }

        key = gdbm_firstkey(data);
        while (key.dptr)
        {
                val = gdbm_fetch(data, key);
                if (val.dsize > 0)
               {
                      printf("Cognome: %s\n", val.dptr);
                      free(val.dptr);
               }
               key = gdbm_nextkey(data, key);
       }

        gdbm_close(data);

        return 0;
}

In questo esempio abbiamo trovato la prima chiave e poi iterato sulle successive fino a quando il campo dptr del datum della chiave non è NULL, che significa che non ci sono più dati nella tabella. Per le altre funzioni di questa semplice ma potente libreria vi rimando alla documentazione ufficiale, sempre rimanendo a disposizione per eventuali chiarimenti.

Informazioni su Giampaolo Rossi

Sviluppatore di software gestionale da oltre 28 anni.
Questa voce è stata pubblicata in Database, Linux e contrassegnata con . Contrassegna il permalink.

Una risposta a Semplici Database con GDBM per Linux

  1. bru scrive:

    il terzo parametro di gdbm store, è la lunghezza della stringa da inserire nel db
    gdbm_store(data, key2, val2, GDBM_INSERT )

    che serve per creare la struttura di datum

    typedef struct {
    char *dptr;
    int dsize;
    } datum;

    struttura molto semplice, ma prona al buffer overflow, utilizzare una libreria per le stringhe riduce il numero dei buffer overflow disseminati nel codice, qmail docet
    http://it.wikipedia.org/wiki/Qmail

    oggi vanno di moda i db non relazionali perche sui grossi numeri scalano meglio (=creano meno rogne)
    http://nosql-database.org/

I commenti sono chiusi.