mercredi 30 septembre 2009

Erlang : guide de survie : Le démarrage

Bon voici le récit de mes premiers essais avec Erlang.
Après un échec cuisant avec Haskell pour sortir quelques lignes de code, je refais une tentative avec Erlang.

1) Le lancement du shell : erl , puis crtl-g pour passer en mode JCL (lancer ou arrêter les processus)

2) Lancement du menu graphique depuis le shell erl : toolbar:start().
Chaque instruction se termine par un '.' (point).

3) Compilation dans le shell : c(nom_du_programme). ou en ligne de commande
erlc . On obtient des fichiers avec l'extension 'beam'.
Très vite il est nécessaire de se creer un Makefile pour automatiser la compilation. Il existe un automake qui permet de génerer des squelettes pour des projets avec OTP (Open Telecom Platform).
Exemple de mon Makefile de base :

# leave these lines alone
.SUFFIXES: .erl .beam .yrl

.erl.beam:
erlc -W $<

.yrl.erl:
erlc -W $<

ERL = erl -boot start_clean

# Here's a list of the erlang modules you want compiling
# If the modules don't fit onto one line add a \ character
# to the end of the line and continue on the next line

# Edit the lines below
MODS = fileinfo truncate

# The first target in any makefile is the default target.
# If you just type "make" then "make all" is assumed (because
# "all" is the first target in this makefile)

all: compile

compile: ${MODS:%=%.beam}

## special compilation requirements are added here


## run an application from the makefile
run:
erl -noshell -s truncate main /root/Desktop/Lost.last.mkv

# remove all the code

clean:
rm -rf *.beam erl_crash.dump






L'entrée 'run' permet de lancer le programme avec les bonnes options pour éviter les saisies fastidieuses.

4) Le lancement en ligne de commande d'un programme:

erl -noshell -s nom_du_module fonction_du module parametre

Un programme lancé de cette façon ne s'arrête jamais , il faut ajouter un exit ou encore mieux : un init:stop(). Si le programme lance des processus par spawn, l'arret du processus père met fin aux processus fils.

5) Pour envoyer un message sur la console l'équivalent d'un print "coucou" se fait par l'instruction io:format("coucou",[]) , un peu comme l'instruction printf en C. Les règles de formatage sont plus réduites qu'en C:
'~s' pour une chaîne de caractère
'~w' pour un type quelconque (entier ,chaine,tuple)
'~p' pour une présentation en ligne.
'~f' nombre
La syntaxe est longueur.precision.padding

Exemple: ~10.2.0f donne : longeur totale 10 , 2 chiffres après la virgule et des '0' en complement.
Le '~n' donne un retour charriot '\n'.

Pour formater une variable au moment de l'assignation:
T= io_lib:format("le texte est ~w",['"ci"]).

Autre exemple: charge des entiers sur 2 caracteres, avec 0 en tête.
Texte= lists:flatten( io_lib:format("~2..0w",[I])),

6) Structure d'un programme .
Si la résolution d'un probleme peut se faire de manière linéaire , il ne sert à rien de le faire en Erlang. Par contre si on désire faire travailler plusieurs processus en même temps (concurrent) , l'Erlang est le langage qui est fait pour ca.
L'unité de base est le module , le module regroupe des fonctions. On peut classifier les fonctions en 3 catégories
- Les fonctions autonomes qui réalisent des traitements
- Des fonctions de supervision, qui lancent et gèrent les fonctions autonomes
- Les fonctions qui charpentent le programme et les données (gestion de la configuration, accès aux structures).

il est recommandé d'organiser le code en trois groupes:
- Les fichiers d'entete (hrl , comme les fichiers header en C) .
- Un fichier par module , un module par fonctions connexes
- Un fichier regroupant les fonctions d'intendance et le superviseur.
exemple :

-module (truncate).
-export([main/1,console/1,launcher/2]).
-define(GO2OCTET, 1073741824). %ratio de conversion
-define(TRUNK, 104857600). % taille de morceaux
-define(MOTIF, "trunk_%%.mkv"). % nom en sortie
-include("structures.hrl").


Dans l'ordre : le nom du module , les fonctions que le module expose (exporte) , la définition de quelques macros, l'include vers les fichiers headers. On trouvera rarement des clauses d'import. Il suffit d'appleler autre_module:fonction() pour que le compilateur recherche autre_module.beam.

7) Les structures de données
Comme en C, il est possible de manipuler des 'record'. Ces structures permettent de manipuler des données organisées.
Exemple :

%% La description dun segment
-record(segment,{nom,debut,longueur}).
create_segment(Nom,Debut,Longueur)->
#segment{nom = Nom,
debut=Debut,
longueur=Longueur}.


Le fichier contient la description de la structure et les fonctions pour la manipuler (create_ ou new ou foobar) .

Pour retrouver les données :

Nom_segment =H#segment.nom ,
Debut_segment =H#segment.debut,
Longueur_segment =H#segment.longueur,



8) Un exemple de procédure complète

main([A]) ->
%recuperation de la ligne de commande
Nom_fichier = atom_to_list(A),
Tailleoctet= fileinfo:file_size_and_type(Nom_fichier),
Taille= round (Tailleoctet/ ?GO2OCTET * 100)/100,
io:format("Taille du fichier:~p Go~n",[Taille]),
io:format("Trunk ~p Octets~n",[?TRUNK]),
%preparation du nombre de morceaux et de leur taille
Morceaux= fileinfo:decoupe(Tailleoctet,round(?TRUNK),0,0,"eric%%.mkv",[]),
io:format("Result ~p~n",[Morceaux]),
% lancement des decoupages
launcher(Morceaux,Nom_fichier). % lancement processus qui vont decouper le fichier

% init:stop().
%% donc le programme ne s arrete jamais !!

9) détail du lanceur


launcher([],Nom) -> ok;
launcher([H|Reste],Nom) -> Nom_segment =H#segment.nom ,
Debut_segment =H#segment.debut,
Longueur_segment=H#segment.longueur,
io:format("Lancement de ~p debut ~p longueur ~p~n",[Nom_segment,Debut_segment,Longueur_segment]),
spawn(fileinfo,create_segment,[Nom,Nom_segment,Debut_segment,Longueur_segment]),
launcher(Reste,Nom).



La procédure est récursive, la premiere ligne est le cas trivial :
launcher([],Nom) -> ok;
La liste est vide , je n'ai plus rien à lancer.




10) Les pages d'aide.

erl -man NOM_De_LA_PAGE

exemples :
erl -man Erlang (% donne le détails des BIFS Build In Function)
erl -man io
erl -man file

Il reste à voir :
-Le mode debug
-L'écriture d'un vrai superviseur
-Le dalogue entre le superviseur et les processus travailleurs

lundi 21 septembre 2009

Le libre l'avenir du web (musique) ?


Apres Radiohead , le groupe de rock Smashing Pumpkins vient d'offrir aux Internautes leur dernier album à telecharger gratuitement. Comment dans ce cas vont ils gagner de l'argent ?. Simplement en proposant une version CD/DVD bourrée de bonus et de très bonne qualité.
Le libre est il l'avenir de la musique et du WEB ?. Les études revelent que les plus gros telechargeurs sont aussi les plus gros acheteurs de produits culturels . Cela reste des sondages. Quand on interroge des amis , une grosse majorité regarde plus Arte ou Thalassa que les grosses daubes de TF1. Il y aurait donc deux types de telechargeurs: ceux qui telechargent sans scrupules et les autres qui compensent volontairement ou non par des achats réguliers.

Un modèle economique se dessine pour la musique: Libre et gratuite sur Internet avec une rémuneration pour par le biais des collectors et des concerts. Par contre pour le cinéma l'équation est plus dure à résoudre, d'autant qu'avec les dernieres nouveautés, il est possible d'avoir une qualité cinema à la maison avec en plus l'avantage de pouvoir régler le volume sonore (les cinemas abusent de leurs installations).

En attendant en avant la musique.


mardi 15 septembre 2009

Bienvenue chez Erlang


J'ai attrapé des migraines en essayant de comprendre les principes de la programmation fonctionnelle avec Haskell. Pour la première fois je n'ai pas réussi à écrire un petit programme de démonstration avec un nouveau langage.

Je me suis rabattu sur Erlang et là , la lumière à jaillie ! J'ai compris les grands principes d'Erlang grâce à mes lectures sur Haskell.

Erlang est un langage fonctionnel 'allégé' avec beaucoup moins de contrainte qu' Haskell mais aussi moins de richesse au niveau du traitement récursif (exemple: les opérations de map/fold par la gauche ou à droite).

Les grands principes d'Erlang

Erlang est orienté 'concurrent' . Il faut traduire le terme par processus 'partenaires'.

Quand on a faire à un traitement lourd , il y a plusieurs solutions :
  1. La plus couteuse: Utiliser une énorme machine avec un énorme CPU : cette solution est passée de mode.
  2. Lancer plusieurs petits programmes pour traiterle même problème:
Là on en encore 3 possibilités :

  • Technique du Fork.
On peut utiliser la technique du Fork présente sur les machines Unix. Le processus père est dupliqué en processus fils. Tout l'environnement du père est ainsi cloné dont les descripteurs de fichier. Il n'y a souvent qu'un seul programme qui doit faire le test suivant: je suis le père ou je suis un des fils. On trouvera ainsi dans le code des paragraphes de libération de ressources qui ne seront activés que dans l'environnement d'un processus fils. Il faudra aussi gérer la communication inter-processus par l'utilisation de sémaphore ou des tubes nommés.

  • Les Threads.
Les threads partagent un espace de mémoire commun et peuvent ainsi échanger des informations. Par contre , il faut utiliser des rtechniques de synchronisation et de verrouillage de memoire.

  • Par message
Erlang utilise des messages pour communiquer entre les processus , comme on peut le faire avec notre client de messagerie. On ne parle plus de thread mais de processus. Chaque processus à son propre espace d'adressage. Chaque processus possède une boite au lettre et est capable de recevoir ou d'envoyer des messages dans un protocole propre à Erlang. Cette gestion est facilitée par l'utilisation des principes de la programmation fonctionnelle .

Ainsi Erlang est capable de lancer et de superviser plusieurs precessus en local MAIS aussi en mode distant sur des machines distinctes.

Les principes de la programmation fonctionnelle dans Erlang.

  • Les variables.

Les variables sont immuables : Il est possible d'assigner une variables mais on ne peut pas la modififer (SANS qu'on puisse parler de constante.) Question : comment incrémenter une variable ?

  • Les fonctions
Un programme est une suite de fonction. Chaque fonction est protégée par un filtre (motif ou condition) qui permet ou non de rentrer dans certaines parties de la fonction .

  • La récursivité.

Un programmeur habitué à ses boucles FOR , WHILE ne trouvera pas directement les équivalences. C'est d'ailleurs peut etre une erreur de conception que d'avoir à faire une boucle de type classique.

Les livres

En francais Lien vers Eyrolles

En Anglais : La bible Erlang

lundi 14 septembre 2009

S'envoyer en l'air dans la rue


Pour cela, il faut chausser une paire d'échasse urbaine. Formée d'une longue tige flexible en fibre élastique, équipée d'un repose pied.

Il ne faut pas plus de 3 minutes pour maitriser l'engin. La difficulté réside dans ces deux points:
* Il n'est pas possible de resté immobile, il faut en permanence piétiner pour rester en équilibre.
* Il faut inverser les mécanismes naturels de compensation : Quand on perd l'équilibre: il faut se dresser au lieu de s'accroupir.

Il est possible de courir à 40 Km (à vérifier) . Les échasses compensent 10 fois plus que les membres inférieurs et donc il n'y pas de risques de problèmes articulaires mais gare à la chute.

20090829-_aaj0842n


mardi 25 août 2009

Openstreetmap

J'avais déja parlé du projet de cartographie libre :openstreetMap dans un post précedent.


Christophe CAZIN a lui, posté ce message sur le forum 'service public' :



Une série d'articles très intéressants sur OpenStreetmap et ses acteurs.

"Mais la vraie bonne surprise était que la DGFiP a offert à OpenStreetMap l’accès à son Web Map Service. Concrètement, cela signifie qu’un plug-in pour le logiciel JOSM peut télécharger les données cadastrales directement depuis les serveurs de cadastre.gouv.fr, et les afficher par-dessus les tracés de routes comme un calque supplémentaire." (extrait d'un des articles)

Merci donc à la DGFiP ...

J'ai constaté récemment que mon téléphone Galaxy Android n'est pas le seul à pouvoir afficher les cartes d'Openstreetmap (avec l'application AndNav2): les GPS de marque Garmin, pour certains modèles, peuvent intégrer des cartes extérieures sur des modules mémoires sd-card et proposer les cartes d'Openstreetmap (L'europe entière est disponible).
Pas besoin donc de connections 3G et d'abonnement web illimité pour profiter d'une cartographie mobile de terrain libre ...

Voici un des modèles :
http://www.maisondugps.com/GPS-de-randonnee/GARMIN/6520,(010-00630-01)-GPS-Garmin-Etrex-Vista-Hcx.html
La chaine de liaison usb avec les modèles GARMIN fonctionne parfaitement sous Linux (Mandriva et Ubuntu ): J'ai testé !

Cartes de France pour GPS GARMIN :
http://fredericbonifas.free.fr/osm/garmin.html


Des dizaines d'applications libres arrivent tout les jours sous Linux, Windows , (et ANDROID) pour exploiter ces données dont le spectre d'utilisation libre laisse place à une grande créativité ! (sport, transports, tourisme, services, urgences, radars , surveillance etc ...)

Quelques logiciels : Navit, Viking , Gpsbabel , Gpsd , JOSM etc ...

Christophe

PS: je suis en train de corriger le plan de la Baule pour ajouter tous les sens uniques que j'ai relevé il y a quelques semaines sur le terrain !


Les routards du web : « Nous sommes comme des fourmis »

http://www.ecrans.fr/Les-routards-du-web-Qui-sont-ils,7888.html


par Camille Gévaudan

lundi 24 août 2009

Le sinclair ZX81



J'ai remis en marche mon prmier ordinateur le zinclair ZX81 acheté en 1980. D'une capacité de 1ko , il était doté d'une extension mémoire de 16ko.

Je l'avais démonté pour le loger dans un boitier muni d'un vrai clavier.

Le guide utilisateur était vraiment très bien fait. Il donnait toutes les adresses système.
J'ai même retrouvé des vidages de programmes en langage machine

quelques liens sur le zx81:
wikipedia


jeudi 23 juillet 2009

Prise en main de couchDB

L'installation de couchDB ne pose de problème avec les gestionnaires de paquets. Le système installe le programme erlang/OTP qui comporte un shell erlang. C'est dans ce langage que seront traité les requetes HTTP et traduite les fonctions javascript.

Sur une Debian, l'installation lance les programmes suivants:

2575 ? S 0:00 /bin/sh -e /usr/bin/couchdb -c /etc/couchdb/couch.ini -b -r 5 -p /var/run/couchdb.pid -o /dev/null -e /dev/null -R
2576 ? Sl 0:01 /usr/lib/erlang/erts-5.6.3/bin/beam -Bd -- -root /usr/lib/erlang
-progname erl (),.........
receive done -> done end. -couchini /etc/couchdb/couch.ini -pidfile /var/run/couchdb.pid -heart



Un script qui gèrera le daemon (usr/bin/couchdb) et le shell erlang (beam) .

Configuration


Le fichier de configuration couch.ini se trouve sous le répertoire /etc/couchdb

Il ressemble à ceci : (j'ai ajouté des commentaires en fin de ligne)


[Couch]

ConsoleStartupMsg=Apache CouchDB is starting. #message d'accueil

DbRootDir=/var/lib/couchdb # repertoire des fichiers BTREE

Port=5984 # port d'ecoute

BindAddress=127.0.0.1 # adresse de l'interface reseau

DocumentRoot=/usr/share/couchdb/www # repertoire de stockage des pages web d'administration

LogFile=/var/log/couchdb/couch.log # les logs

UtilDriverDir=/usr/lib/couchdb/erlang/lib/couch-0.8.0-incubating/priv/lib

LogLevel=info #log level (info ,debug)

[Couch Query Servers]

javascript=/usr/bin/couchjs /usr/share/couchdb/server/main.js

(remarque : couchDB est un projet Apache mais n'utilise pas de serveur Apache.)

L'interface d'administration: FUTON

Elle s'affiche à l'adresse suivante : http://127.0.0.1:5984/_utils



Cette interface permet de tout faire : création d'une entrée, réplication , statistiques.

Créer deux instances de couchDB.

Pour réaliser des essais de réplication , il est parfois necessaire de creer deux instances sur la même machine. Il faudra définir deux ports d'ecoute , avoir deux répertoire de données etc.

Commencons par duppliquer le fichier couch.ini en couch2.ini
Puis il faut éditer couch2.ini et modifer ces lignes :

portable:~# diff /etc/couchdb/couch.ini /etc/couchdb/couch2.ini
5c5
< consolestartupmsg="Apache"> ConsoleStartupMsg=Apache CouchDB instance 2 is starting.
7c7
< dbrootdir="/var/lib/couchdb"> DbRootDir=/var/lib/couchdb2
9c9
< port="5984"> Port=5985
13c13
< documentroot="/usr/share/couchdb/www"> DocumentRoot=/usr/share/couchdb2/www
15c15
< logfile="/var/log/couchdb/couch.log"> LogFile=/var/log/couchdb/couch2.log

Il faut créer avec les bons droits les répertoires pour la deuxième instance. Et copier les fichiers existants de la première instance vers les répertoires de la deuxième instance. Le répertoire DbRootDir des fichiers BTREE peut etre vide. Il sera mis à jour par le mécanisme de la réplication.

Afin on lancera les deux services par en prenant soin d'arrêter préalablement le service couchDB (/etc/init.d/couchdb stop )

couchdb -c /etc/couchdb/couch.ini &
couchdb -c /etc/couchdb/couch2.ini &

Voila , on est prêt pour essayer la réplication.