vendredi 27 novembre 2009

lxml: Python et Xml

L'un des meilleurs package XML disponible pour Python est lxml (aussi connu comme ElementTree).
Ce package n'est pas disponible par défaut lors de l'installation de Python, il convient donc de faire le nécessaire (voir détails plus loin).

Tutorial
ElementTree dispose d'un excellent tutorial de prise en main qu'il ne faut surtout pas rater sur "code speak".
Code Speak publie également une documentation pdf complète.
L'article "ElementTree Overview" propose un court survol de eTree mais incluant néanmoins le parsing, chargement et sauvegarde.
Voir également "Python XML processing with lxml"

Exemple
Cette exemple montre la création et la sauvegarde d'un document XML.
Plus d'exemples sont disponibles dans l'excellent tutorial dédié a lxml.etree sur "Code Speak".
>>> from lxml import etree
>>> _rootNode = etree.Element( 'root-node' )
>>> etree.SubElement( _rootNode, 'first-child' )
<Element first-child at 124b3c0>
>>> etree.SubElement( _rootNode, 'second-child' )
<Element second-child at 1241e10>

>>> _attr = _rootNode.attrib
>>> _attr['UnAttribut']='UneValeur'
>>> print( etree.tostring( _rootNode, pretty_print=True ) )
<root-node UnAttribut="UneValeur">
  <first-child/>
  <second-child/>
</root-node>

>>> # sauvegarde dans un fichier
>>> _tree = etree.ElementTree( _rootNode )
>>> _f = open( 'test.xml', 'w' )
>>> with _f:
 _tree.write( _f )

 
>>> # autre sauvegarde
>>> _tree.write( 'test2.xml' )

Installation de lxml
ElementTree fait partie du package lxml qui peut être installé depuis Python Package Index (PyPI) à l'aide de easy_install (voir cet article) .
Le package lxml se base sur libXml et libXslt qui ne sont habituellement pas installés dans l'environment Windows (voir la note "installing lxml" sur "code speak" pour quelques infos complémentaires).
En temps normal, les package PyPI contiennent les dépendances binaires (DLL) nécessaires et ces dernieres sont automatiquement installées par easy_install.
Il arrive cependant que les dépendances binaires ne soient pas encore disponibles dans la dernière version d'un package (ce qui peut être le cas pour des packages en cours de développement).
Dans ce cas, easy install retourne inévitablement le message d'erreur "** make sure the development packages of libxml2 and libxslt are installed **".
Dans ce cas, il convient d'identifier dans PyPI la dernière version stable du package et de passer ce numéro de version en paramètre à easy_install.
Ce fut le cas lors de ma tentative d'installation lxml à l'aide de easy_install ("best match" pour la version 2.2.3).
Le commande d'installation correcte était finallement:
easy_install lxml==2.2.2

Informations relatives au port de LibXml sous Windows
Zlatkovic dispose d'un site spécifique concernant le portage de LibXml sous Windows.
Ce site propose également un lien ftp (ftp.zlatkovic.com/libxml/) permettant de télécharger les DLLs libXml et consort (à installer manuellement dans le répertoire c:\windows\).
Comme le précise Zlatkovoc sur son site, il existe un certains nombre de dépendance entre libXml et d'autres librairies comme zlib et vicon (voir image ci-dessous).
image: www.zlatkovic.com/images/libxml-pkgdeps.png
A noter finalement qu'en installant LibXml, LibXslt, IconV and ZLib quelques utilitaires sont également installés et disponible en ligne de commande (xsltproc,  xmlcatalog, xmllint, minigzip).

jeudi 26 novembre 2009

Liste des commandes DBCC

Voici un article de "Novick software" qui explique comment obtenir une liste de toutes les commandes DBCC de Sql Server.
Cette liste  inclus les commandes non documentées ainsi que la syntaxe.



DBCC activecursors [(spid)]

DBCC addextendedproc (function_name, dll_name)

DBCC addinstance (objectname, instancename)

DBCC adduserobject (name)

DBCC auditevent (eventclass, eventsubclass, success, loginname
                                            , rolename, dbusername, loginid)

DBCC autopilot (typeid, dbid, tabid, indid, pages [,flag])

DBCC balancefactor (variance_percent)

DBCC bufcount [(number_of_buffers)]

DBCC buffer ( {'dbname' | dbid} [, objid [, number [, printopt={0|1|2} ]
                                  [, dirty | io | kept | rlock | ioerr | hashed ]]])
                                         
DBCC bytes ( startaddress, length )

DBCC cachestats

DBCC callfulltext

DBCC checkalloc [('database_name'[, NOINDEX | REPAIR])]
                           [WITH NO_INFOMSGS[, ALL_ERRORMSGS][, ESTIMATEONLY]]

DBCC checkcatalog [('database_name')] [WITH NO_INFOMSGS]

DBCC checkconstraints [( 'tab_name' | tab_id | 'constraint_name' | constraint_id )]
                                          [WITH ALL_CONSTRAINTS | ALL_ERRORMSGS]

DBCC checkdb [('database_name'[, NOINDEX | REPAIR])]
                                  [WITH NO_INFOMSGS[, ALL_ERRORMSGS]
                                    [, PHYSICAL_ONLY][, ESTIMATEONLY][,DBCC TABLOCK]

DBCC checkdbts (dbid, newTimestamp)]

DBCC checkfilegroup [( [ {'filegroup_name' | filegroup_id} ]
                                 [, NOINDEX] )] [WITH NO_INFOMSGS
                      [, ALL_ERRORMSGS][, PHYSICAL_ONLY][, ESTIMATEONLY][, TABLOCK]]

DBCC checkident ('table_name'[, { NORESEED | {RESEED [, new_reseed_value] } } ] )

DBCC checkprimaryfile ( {'FileName'} [, opt={0|1|2|3} ])

DBCC checktable ('table_name'[, {NOINDEX | index_id | REPAIR}])
                                      [WITH NO_INFOMSGS[, ALL_ERRORMSGS]
                                      [, PHYSICAL_ONLY][, ESTIMATEONLY][, TABLOCK]]

DBCC cleantable ('database_name'|database_id, 'table_name'|table_id,[batch_size])

DBCC cacheprofile [( {actionid} [, bucketid])

DBCC clearspacecaches ('database_name'|database_id,
                               'table_name'|table_id, 'index_name'|index_id)

DBCC collectstats (on | off)

DBCC concurrencyviolation (reset | display | startlog | stoplog)

DBCC config

DBCC cursorstats ([spid [,'clear']])

DBCC dbinfo [('dbname')]

DBCC dbrecover (dbname [, IgnoreErrors])

DBCC dbreindex ('table_name' [, index_name [, fillfactor ]]) [WITH NO_INFOMSGS]

DBCC dbreindexall (db_name/db_id, type_bitmap)

DBCC dbrepair ('dbname', DROPDB [, NOINIT])

DBCC dbtable [({'dbname' | dbid})]

DBCC debugbreak

DBCC deleteinstance (objectname, instancename)

DBCC des [( {'dbname' | dbid} [, {'objname' | objid} ])]

DBCC detachdb [( 'dbname' )]

DBCC dropcleanbuffers

DBCC dropextendedproc (function_name)

DBCC dropuserobject ('object_name')

DBCC dumptrigger ({'BREAK', {0 | 1}} | 'DISPLAY' | {'SET', exception_number}
                                             | {'CLEAR', exception_number})

DBCC errorlog

DBCC extentinfo [({'database_name'| dbid | 0}
                 [,{'table_name' | table_id} [, {'index_name' | index_id | -1}]])]

DBCC fileheader [( {'dbname' | dbid} [, fileid])

DBCC fixallocation [({'ADD' | 'REMOVE'},
                           {'PAGE' | 'SINGLEPAGE' | 'EXTENT' | 'MIXEDEXTENT'}
                                   , filenum, pagenum [, objectid, indid])

DBCC flush ('data' | 'log', dbid)

DBCC flushprocindb (database)

DBCC free dll_name (FREE)

DBCC freeproccache

dbcc freeze_io (db)

dbcc getvalue (name)

dbcc icecapquery ('dbname', stored_proc_name
                              [, #_times_to_icecap  (-1 infinite, 0 turns off)])
     Use 'dbcc icecapquery (printlist)' to see list of SP's to profile.
     Use 'dbcc icecapquery (icecapall)' to profile all SP's.
       
dbcc incrementinstance (objectname, countername, instancename, value)

dbcc ind ( { 'dbname' | dbid }, { 'objname' | objid }, { indid | 0 | -1 | -2 } )

DBCC indexdefrag ({dbid | dbname | 0}, {tableid | tablename}, {indid |indname})

DBCC inputbuffer (spid)

DBCC invalidate_textptr (textptr)

DBCC invalidate_textptr_objid (objid)

DBCC iotrace ( { 'dbname' | dbid | 0 | -1 }
                             , { fileid | 0 }, bufsize, [ { numIOs | -1 }
                               [, { timeout (sec) | -1 } [, printopt={ 0 | 1 }]]] )

DBCC latch ( address [, 'owners'] [, 'stackdumps'])

DBCC lock ([{'DUMPTABLE' | 'DUMPSTATS' | 'RESETSTATS' | 'HASH'}] |
                                          [{'STALLREPORTTHESHOLD', stallthreshold}])

DBCC lockobjectschema ('object_name')

DBCC log ([dbid[,{0|1|2|3|4}[,['lsn','[0x]x:y:z']|['numrecs',num]|['xdesid','x:y']
                 |['extent','x:y']|['pageid','x:y']|['objid',{x,'y'}]|['logrecs',
                           {'lop'|op}...]|['output',x,['filename','x']]...]]])

DBCC loginfo [({'database_name' | dbid})]

DBCC matview ({'PERSIST' | 'ENDPERSIST' | 'FREE' | 'USE' | 'ENDUSE'})

DBCC memobjlist [(memory object)]

DBCC memorymap

DBCC memorystatus

DBCC memospy

DBCC memusage ([IDS | NAMES], [Number of rows to output])

DBCC monitorevents ('sink' [, 'filter-expression'])

DBCC newalloc - please use checkalloc instead

DBCC no_textptr (table_id , max_inline)

DBCC opentran [({'dbname'| dbid})] [WITH TABLERESULTS[,NO_INFOMSGS]]

DBCC outputbuffer (spid)

DBCC page ( {'dbname' | dbid}, filenum, pagenum
                                 [, printopt={0|1|2|3} ][, cache={0|1} ])

DBCC perflog

DBCC perfmon

DBCC pglinkage (dbid, startfile, startpg, number, printopt={0|1|2}
                                              , targetfile, targetpg, order={1|0})

DBCC pintable (database_id, table_id)

DBCC procbuf [({'dbname' | dbid}[, {'objname' | objid}
                                          [, nbufs[, printopt = { 0 | 1 } ]]] )]

DBCC proccache

DBCC prtipage (dbid, objid, indexid [, [{{level, 0}
                                    | {filenum, pagenum}}] [,printopt]])

DBCC pss [(uid[, spid[, printopt = { 1 | 0 }]] )]

DBCC readpage ({ dbid, 'dbname' }, fileid, pageid
                                 , formatstr [, printopt = { 0 | 1} ])

DBCC rebuild_log (dbname [, filename])

DBCC renamecolumn (object_name, old_name, new_name)

DBCC resource

DBCC row_lock (dbid, tableid, set) - Not Needed

DBCC ruleoff ({ rulenum | rulestring } [, { rulenum | rulestring } ]+)

DBCC ruleon (  rulenum | rulestring } [, { rulenum | rulestring } ]+)

DBCC setcpuweight (weight)

DBCC setinstance (objectname, countername, instancename, value)

DBCC setioweight (weight)

DBCC show_statistics ('table_name', 'target_name')

DBCC showcontig (table_id | table_name [, index_id | index_name]
                         [WITH FAST, ALL_INDEXES, TABLERESULTS [,ALL_LEVELS]])

DBCC showdbaffinity

DBCC showfilestats [(file_num)]

DBCC showoffrules

DBCC showonrules

DBCC showtableaffinity (table)

DBCC showtext ('dbname', {textpointer | {fileid, pageid, slotid[,option]}})

DBCC showweights

DBCC shrinkdatabase ({dbid | 'dbname'}, [freespace_percentage
                                            [, {NOTRUNCATE | TRUNCATEONLY}]])

DBCC shrinkfile ({fileid | 'filename'}, [compress_size
                                     [, {NOTRUNCATE | TRUNCATEONLY | EMPTYFILE}]])

DBCC sqlmgrstats

DBCC sqlperf (LOGSPACE)({IOSTATS | LRUSTATS | NETSTATS | RASTATS [, CLEAR]}
                                                  | {THREADS} | {LOGSPACE})

DBCC stackdump [( {uid[, spid[, ecid]} | {threadId, 'THREADID'}] )]

DBCC tab ( dbid, objid )

DBCC tape_control {'query' | 'release'}[,('\\.\tape')]

DBCC tec [( uid[, spid[, ecid]] )]

DBCC textall [({'database_name'|database_id}[, 'FULL' | FAST] )]

DBCC textalloc ({'table_name'|table_id}[, 'FULL' | FAST])

DBCC thaw_io (db)

DBCC traceoff [( tracenum [, tracenum ... ] )]

DBCC traceon [( tracenum [, tracenum ... ] )]

DBCC tracestatus (trace# [, ...trace#])

DBCC unpintable (dbid, table_id)

DBCC updateusage ({'database_name'| 0} [, 'table_name' [, index_id]])
                                        [WITH [NO_INFOMSGS] [,] COUNT_ROWS]

DBCC upgradedb (db) DBCC usagegovernor (command, value)

DBCC useplan [(number_of_plan)]

DBCC useroptions DBCC wakeup (spid)

DBCC writepage ({ dbid, 'dbname' }, fileid, pageid, offset, length, data)

mardi 24 novembre 2009

5 minutes pour comprendre les produits Visual Studio

Voici un lien vers la page "5 minutes pour comprendre Visual Studio".
Cette page reprend des vidéos de 5 minutes chacune axée sur un produit spécifique "Visual Studio".
Cela ne comprend pas unique l'environnement Visual Studio lui même mais également des produits comme:
  • Team Foundation Server.
    Se présente comme le serveur idéal pour faire collaborer les équipes de développement de toutes tailles.
    Team foundation serveur est composé de plusieurs modules:

    • Gestion de configuration (branch, sources)
    • Portail collaboratif
    • Gestion d'anomalie
    • Serveur de compilation
    • Suivit de projet.

  • Team Test
  • Team Architect
  • Visual Studio Shell

lundi 23 novembre 2009

décodage des entités html en SqlServer

Pour différentes raisons il arrive qu'un algorithme d'encodage soit utilisé pour encoder des données avant de les stocker dans une DB.
Bien malheureusement, l'usage des datasets n'est pas toujours un standard. 
L'encodage devient alors un moyen commode d'éviter la corruption d'une requête sql lorsqu'une valeur de type texte contient des guillemets (quotes) ou autres caractères susceptibles de corrompre la requête..
Parmi ces types d'encodage, il existe l'encodage sous forme d'entité html (voir Wikipédia ou Zytrax pour plus d'info).
Cet encodage se base sur in formalisme permettant l'encodage de caractère à base de nom symbolique ou de valeur numérique.  C'est bien evidemment sur le codage numérique que cette fonction s'attarde.


Décodage des entités html (numérique seulement)
A titre d'exemple, voici une fonction rudimentaire décodant les entités html numériques contenu dans les champs textes.
A noter que cette fonction ne traite que les entités numériques en 3 positions/chiffres uniquement.
-- =============================================
-- Author: Domeu
-- Create date: 23 nov 2009
-- Description: Decode string containing numerical html entities
-- Changes: 
--   24 nov 2009, fix side effect when HtmlString ends with HtmlEntity
-- Example:
--   Print dbo.fnDecodeHtmlString( 'Test &#049;&#048;&#054;&#050;&#055; get completed' )
-- =============================================
CREATE FUNCTION fnDecodeHtmlString 
(
 @HtmlString varchar(Max)
)
RETURNS varchar(max)
AS
BEGIN
 -- Declare the return variable here
 DECLARE @Result varchar(max)
 DECLARE @RightPart varchar(max)
    SELECT @Result = @HtmlString

    DECLARE @iPos bigint
    DECLARE @EntityNumber varchar( 10 )
    -- Start finding &#xx; patterns
    SELECT @iPos = CHARINDEX( '&#', @Result)
    while @iPos>0
    begin
      -- Check if we have the ";" 4 digits further in the string
      -- The correct Html entity format is "&#012;"
      if SubString( @Result, @iPos+2+3, 1 )=';'
      BEGIN
      -- Correct Html Entity Detected
    -- extract entity number
    SELECT @EntityNumber = SubString( @Result, @iPos+2, CHARINDEX( ';', @Result, @iPos )- (@iPos+2) )
         -- ATTN: RightPart may be when &#xx; is the last item of the string !!!
    SELECT @RightPart = RIGHT( @Result, LEN(@Result) - CHARINDEX( ';', @Result, @iPos ) )
    SELECT @Result = LEFT( @Result, @iPos-1 ) -- String before the #;

    IF CONVERT( int, @EntityNumber )>255
    SELECT @Result = @Result + '?' -- cannot convert value > ASCII code 255
    ELSE
    SELECT @Result = @Result + CHAR( CONVERT( INT, @EntityNumber ) )
          -- ATTN: RightPart may be when x; is the last item of the string !!!
          --       Use coalesce to avoids NULL concatenation.
    SELECT @Result = @Result + coalesce( @RightPart, '' ) 
      END
      ELSE
      BEGIN
        -- &# does not start an Html Entity 
        -- Do not modify the &# and start finding the next occurence of &#
        SELECT @iPos = @iPos + 2
      END
      -- finding next occurence
      SELECT @iPos = CHARINDEX( '&#',@Result, @iPos ) 
    end
 -- Return the result of the function
 RETURN @Result
END
GO

Déclaration de fonctions utilisateurs
Juste un petit paragraphe pour mentionner une excellente référence de Sql Team concernant la création de fonction utilisateur en Sql Serveur .
Outre le définition de fonction scalaires, cet article:
  • démontre l'usage des fonctions scalaires lors de la creation de table (calculated field).
  • Aborde les fonctions "Inline Table-Value User-Defined" et "Multi-statement Table-Valued User-defined"

Python - Cas pratique

Voici un cas pratique (et professionnel) d'utilisation de Python.
Grâce à Python il a été possible de faire une vérification croisée en utilisant seulement quelques lignes de code.
Voici donc un exemple vivant d'utilisation de techniques de lecture de fichier, d'itérateur et de compréhension list.

Description
Le but étant de comparer le contenu:
  1. D'une feuille Excel contenant des noms de tables pour lesquelles il faut implémenter un audit à l'aide de triggers.
    Deux des colonnes de ce document étant un copier-coller dans un fichier texte.
  2. La liste des tables sur lesquelles le consultant a déjà installé les triggers d'audit. Le nom de ces triggers étant formalisé, une simple requête sur sysobjects permet d'obtenir cette liste (également copier/coller dans un fichier texte).
Les deux fichiers précédemment décrits sont disponibles ici.

Le but

  1. Le consultant a t'il modifié toutes les tables comme attendu?
    Vérifier que les noms de table présent dans le feuille Excel (point 1) soient équipés de trigger comme attendu (et donc répertoriés dans le liste des tables du point 2). 
  2. Le consultant a t'il fait de l'excès de zèle?
    Vérifier qu'il n'y a pas de table (point 2) ayant inopinément reçu des triggers d'audit.
    Donc une entrée de la liste des tables (point 2) non présente dans la liste Excel (point 1).
     
Le code

>>> def readfile( sName ):
 _file = open( sName, 'r' )
 _content = _file.readlines()
 _file.close()
 return _content


>>> import re # Regular expression
>>> #--- Process Table List ---
>>> tablelist = readfile( 'c:/temp/tablelist.txt' )
>>> # Remove the \n at each end of line
>>> tablelist = [ re.sub(r'\n','', item) for item in tablelist ]
>>> #--- Process Excel List ---
>>> excellist = readfile( 'c:/temp/excellist.txt' )
>>> # content of excellist is
>>> #    ['tblTMProject\tok\n', 'tblCMPerson\tok\n',
>>> # extract the tablename before the tab
>>> #    only if tab+"ok" can be located within the string
>>> excellist = [ re.split(r'\t', item)[0] for item in excellist if re.search(r'\tok', item)>0 ]
>>> excellist = [ item.strip() for item in excellist ] # remove spaces

>>> #--- Find the missing table in Excellist ---
>>> #  find table name from tablelist not listed in the excel list 
>>> [ item for item in tablelist if not any( item.lower()==excelitem.lower() for excelitem in excellist ) ]
['xxxOrganization', 'xxxXmlImportSession', 'xxxComboType']

>>> #--- Find the missing table in tablelist ---
>>> #  find table name from excellist not listed in the table list
>>> [ item for item in excellist if not any( [ item.lower()==tableitem.lower() for tableitem in tablelist ] )]
[]

Information complémentaire:

samedi 21 novembre 2009

Livres à lire

Ma petite Françoise se sert énormément de cette liste et ne peut malheureusement pas la modifier.
Afin d'éviter les doubles emplois, pensez à la contacter avant vos achats... elle se fera un plaisir de jouer la coordinatrice.

Voici une petite liste de livre qu'il me faudra un jour lire.


Thriller
Henri Loevenbruck

  • Le syndrome Copernic de Henri Loevenbruck info
    + +  Edt: Flammarion
  • Les cathédrales du vide de Henri Loevenbruck info
    + +  Edt: Flammarion
  • Le testament des siècles de Henri Loevenbruck info
    A vérifier Grand format?
Autre  
  • Les héritiers du soleil noir de James Twining info
    Edt: Hachette, Thriller halletant sur fond d'histoire et d'ésotérisme.
  • La porte dérobée de Meyer Eric et Christine Kerdellant info
    + +  Edt: Laffont. Thriller informatique, super critiques sur Amazon.
    ATTENTION, plusieurs livres portent ce même titre.
  • La croix des assassins de Eric Giacometti et Jacques Ravenne info
    Edt: Fleuve noir. Thriller Franc-maçon, critique moyenne  (quelques commentaires enthousiastes) sur Amazon. Semble être un 4ième roman.
  • La bible de Darwin de James Rollins info
    Edt: Fleuve noir. 
Romans

  • PS: I Love you de Cecilia Ahern info
    Edt: Albin Michel 
  • L'ordre du monde de Denis l'épée info
    Edt: Timée Editions, ISBN: 978-2-35401-009-6
  • T-Rex de Douglas Preston info
    Edt: L'archipel, ISBN-13: 978-2809800227
      
  • Parce que je t'aime de Guillaume Musso info
    Edt: XO Editions
  • Web Mortem de Christine Adamo info
    Edt: Albin Michel

Policiers

  • Sherlock Holmes (Tome 1) de Sir Conan Doyle info
    Edt: Robert Laffont (Bouquins)
  • Sherlock Holmes (Tome 2) de Sir Conan Doyle info
    Edt: Robert Laffont (Bouquins)
  • Opale de Stéphane Lefebvre info
    Edt:
Science Fiction
Micheal Crichton
  • Voyage de Michael Crichton info
    Edt: Robert Laffont
  • La variété Andromède de Michael Crichton info
    Edt: Robert Laffont
  • Etat d'urgence de Michael Crichton info
    Edt: Robert Laffont 
Autre

  • Autre Monde de Maxime Chattam pas d'info site officiel
    Sorti le 3 Nov 2008, pas d'info sur Amazon
  • Ilium de Dan Simons info
    L'Illiade et l'Odyssée version futuriste et technologique. Abordable et excellent selon les commentaires sur Amazon. Recommandé par Jean-Yves.
  • Olympos de Dan Simons info
    Suite d'Ilium.
  • Les enfants de la destinée, Tome 1: Coalescence de Stephen Baxter info
  • La route de Cormac McCarthy info
    Excellente évaluation sur Amazon.
  • Neuromancien de William Gibson info
    Edt: J'ai lu
  • Le problème de Turing de HARRISON Harry info
    + +  Excellent roman de SF basé sur l'intelligence artificielle.
    Edt: Robert Laffont
Science

  • L'histoire Universelle des chiffres (Tome 1 & 2) de Georges Ifrah info
    Edt: Robert Laffont (Bouquins)
  • Biographie de Fernand Seguin, vulgarisateur scientifique Canadien.
    Voir cette emission (youtube) sur Radio Canada.

Histoire
  • The Charlemagne Pursuit de Steve Berry
    Quand la traduction sera disponible
  • Urbi et Orbi de Steve Berry info
  • Labyrinthe de Kate Mosse info
    Edt: JC Lattes, Roman historique Egypte
Fantastique
  • Saga Fascination: Fascination - Tome 1/4 de Stephenie Meyer info
    L'une des meilleures côtes d'Amazon. Semble intéressant.
    Francoise???

Littérature & autres styles

  • Où on va, Papa de Jean-Louis Fournier info, critique
     Coup de coeur +++  Edt: Stock
    Lecture poignante en prévision. 
  • L'enfance muselée : un médecin témoigne de Bonnet Catherine
    Edt: Thomas Mols, Bierges. ISBN: 978-2-930480-01-5
  • La part de l'autre de Eric-Emmanuel Schmitt info
    Edt: Albin Michel.
    Que se serait-il passé si Hitler n'avait pas été recalé aux beaux arts.
  • Un chat de Noel (autre titre possible) de Charles Dikens info
The adventures of Tintin
Un peu de lecture (pour le plaisir) dans la langue de Shakespear.
Ces livres sont disponibles aux éditions Egmont.
  • The land of black gold
  • King Ottokar's sceptre
  • The black island
  • Destination moon
  • The red sea sharks
  • Tintin in American

Divers

  • La terre vue du ciel info http://www.lamatiniere.fr/
  • J'apprends à dessiner les chats - Philippe Legendre - Edt. Fleurus
  • J'apprends à dessiner l'école - Philippe Legendre - Edt. Fleurus
  • J'apprends à dessiner la mer - Philippe Legendre - Edt. Fleurus 
  • J'apprends à dessiner la ferme - Philippe Legendre - Edt. Fleurus
  • J'apprends à dessiner le bord de l'eau - Philippe Legendre - Edt. Fleurus 
  • J'apprends à dessiner les animaux du monde - Philippe Legendre - Edt. Fleurus 
  • J'apprends à dessiner les animaux de la maison - Philippe Legendre - Edt. Fleurus
  • (Indécis) J'apprends à dessiner les camions - Philippe Legendre - Edt. Fleurus

Quelques livres sur lesquels je dois encore me renseigner:
  • A la croisée des mondes (l'intégrale) de Philip Pullman - Ed Gallimard. ISBN: 978-2-07-061455-4
  • Livre des superstitions - ed.Robert Laffont (Bouquins). Code barre: 978-2-221-068304
  • Dictionnaire des symboles - ed. Robert Laffont (Bouquins). ISBN: 978-2-221-08716-9.
  • Diderot ou la philosophie de la séduction de Eric Emmanuel Schmitt - Ed Albin Michel
    Attention: Tendance philo 

dimanche 15 novembre 2009

Linux et les systèmes RTOS (Real Time Operating System)

Petit résumé d'une récente lecture relative aux systèmes d'exploitation de type "temps réel" (RTOS).
 

contraintes des systèmes RTOS
L'article "Anatomy of real-time Linux architectures" (pdf) paru sur IBM propose une excellente introduction aux systèmes temps réels qui présente les différentes exigences/contraintes de ces systèmes.
C'est ainsi que sont abordés les temps de latences, le traitement en tâches périodiques, les deadlines.
Les systèmes RTOS ont la capacité de pouvoir assumer des tâches "temps réel" (immédiatement) même lorsque l'OS est déjà fortement chargé.
Dans les systèmes RTOS, l'interruption des tâches (et processus) est un des principes fondateur. Il permet de libérer du temps machine pour un tâche de type "temps réel".
Par exemple, un fois les différents senseurs activés, l'analyse du déclenchement d'un AirBag doit être traité endéans les quelques micro-secondes. Un Airbag se déclenchant trop tard étant plus dangereux qu'un véhicule sans d'AirBag! C'est là que réside l'une des principales contrainte du traitement "temps réel".
A contrario, les systèmes Linux normaux ne peuvent pas interrompre certaines tâches en cours. Par exemple, un appel au Kernel effectué par un processus n'est pas interromput (et pas intérrompable). Ces appels au Kernel sont exécutés jusqu'a leurs termes.
L'arrivé d'un intérruption ne suspendra pas l'exécution de cette tâche Kernel en cours. Le traitement de l'intérruption sera quelque peu postposé mais sera néanmoins effectuée en des temps raisonnables (~20 ms, mais sans garantie quand au temps de latence).
Pour l'utilisateur du PC, ces 20 ms sont à peine perceptibles.

Pour un système RTOS, ce délai d'exécution de 20 ms peut être beaucoup trop long... à titre d'exemple, un système ABS contrôle, échantillone et modifie la pression hydrolique des quatres freins environ 20 fois par seconde. Ces exigences sont incompatibles avec un système Linux standard qui prendrait 20 ms de temps de réponse.
On le comprendra aisément, le contrôle du temps, et par conséquent le caractère deterministe, est primordial dans les systèmes temps réel.

Hard et Soft real-time
Pour en revenir à cette excellente publication, l'auteur nous introduit également aux notions des systèmes soft real-time et hard real-time. L'on apprendra ainsi que les systèmes soft real-time ne sont pas tenu à des deadlines précises. Une réponse dans un temps moyen donné étant acceptable, la stabilité du système n'étant pas mise en cause en cas de dépassement de la deadline.
Par contre les systèmes hard real-time sont ceux pour lesquels il est primordial d'obtenir la fin du traitement au plus tard à la deadline. Rater une deadline dans un système hard real-time conduira inévitablement ce dernier dans une situation d'échec (instabilité, erreur système).
Déjà évoqué précédemment, le contrôle d'un Airbag est de type hard real-time (déclenché trop tard, l'airbag pourrait même tuer le conducteur).

Implémenter un système temps réel avec Linux
Parmi les approches permettant d'implémenter un système temps réel, l'on retrouve thin-kenel, nano-kernel et resource-kernel (plus d'information dans l'article d'IBM avec référence des OS).
Depuis la version 2.6 du Kernel, Linux inclus une pile d'exécution Real-time Tasks au niveau du kernel lui-même. Il est ainsi possible de développer des tâches du type soft real-time. Ainsi, avec la nouvelle option CONFIG_PREEMPT, le kernel Linux devient également "preemptable". Au prix d'une légère perte de performance, le kernel peut interrompte l'exécution de processus utilisateur (mais également d'appels d'API kernel) pour réallouer les ressources aux tâches temps réel exécutées par la pile Real-time Tasks du kernel.
Les systèmes temps réels étant intimement liés au temps, le Kernel 2.6 implémente également un nouveau scheduler à haute résolution (si le matériel le supporte). Ainsi, selon la configuration matérielle, il est possible d'avoir des timers d'une préçsion allant jusqu'à la micro-seconde.

Le hard real-time avec Linux
Au prix de quelques efforts, il est également possible d'obtenir un Kernel Linux supportant le hard real-time en appliquant le patch PREEMPT_RT sur le kernel Linux.
Ce patch re-implémente certains primitives de locking, l'héritage de priorité dans les mutexes et un gestionnaire d'intéruption alternatif (dans un thread) du kernel afin de pouvoir suspendre leurs exécutions.

Autres ressources:

jeudi 12 novembre 2009

Python et Sql Serveur

Il est possible de connecter Python à différentes bases de données de diverses façon.
Le site python.org propose d'ailleurs une page entièrement dédiée aux projets et packages relatif à la connectivité DB.
Python.org va encore plus loin avec une page spécifique concernant Sql Serveur.

Python et Sql Serveur
Il existe de nombreuses librairies permettant d'attaquer Sql Serveur et le choix est embarrassant tellement les options sont nombreuses. Trop de choix tue le choix :-).
Certaines de ces librairies ne sont d'ailleurs pas "cross-platform", il fait donc faire son choix avec attention.
Ne faisant que quelques tests sans importance stratégique, mon choix s'est porté sur pyODBC.
Il y a plusieurs raisons à cela:
  1. pyODBC est un projet issus du MIT. Ce qui lui donne une excellente références.
  2. pyODBC est un projet distribué sur GoogleCode.
    Jusqu'à ce jour, je n'y ai trouvé que des codes sources d'excellente facture.
  3. pyODBC dispose d'un installeur pour Windows (ce qui est le bien venu pour un débutant).
  4. pyODBC dispose d'un excellent tutorial dans le wiki de GoogleCode.
Finallement, et après quelques minutes, il apparaît que le coding avec pyODBC est une bonheur de simplicité.
Note: le module pyODBC implémente la DB API 2 de Python.

Exemple
>>> import pyodbc
>>> connStr = 'DRIVER={SQL Server};SERVER=localhost;DATABASE=MyTestDB;UID=TheSqlUser;PWD=TheSqlPassword'
>>> conn = pyodbc.connect( connStr )
>>> cursor = conn.execute( "select name from sysobjects where name like '%tblPS%' and xtype='u'" )
>>> for row in cursor:
    print row.name
    
tblPSlnkPIToP
tblPSMaterial
tblPSProcessInstance
tblPSProcessModel
tblPSResource

>>> # The cursor must be re-open to be read again
>>> cursor = conn.execute( "select name from sysobjects where name like '%tblPS%' and xtype='u'" )
>>> print( [ row.name for row in cursor ] )
[u'tblPSlnkPIToP', u'tblPSMaterial', u'tblPSProcessInstance', u'tblPSProcessModel', u'tblPSResource']
plus d'exemple d'utilisation de pyODBC sur la page Getting Started du wiki de pyODBC.

Installer pyODBC
Voir le projet pyODBC sur GoogleCode, il dispose d'un installeur spécifique à la plateforme Windows.

mardi 10 novembre 2009

Installer Python et easy_install sous Windows

Installer Python pour Windows
Python pour Windows peut être installé depuis python.org (voir la section download).
J'ai personnellement installé la version 2.6.4 qui fonctionne à merveille. Cependant, cette installation n'est pas "complète" du point de vue de la configuration. Il est nécessaire d'effectuer quelques manipulations pour initialiser des variables d'environnement (plus loin dans cet article).

Le programme d'installation pour Windows installe également IDLE.
IDLE est une interface utilisateur rudimentaire mais disposant déjà de nombreuses fonctionnalités intéressant. IDLE est un point de départ idéal pour commencer ses expérimentations en Python.
Par contre, pour les développements plus conséquents, il faudra rapidement opter pour un environnement plus évolué comme Wing (excellent éditeur et gestionnaire de projet pour Python avec un code complétion de grande qualité).

PYTHON_HOME
Bien que l'installation de Python pour Windows soit le plus simple du monde, ce dernier ne modifie malheureusement pas les variables d'envrionnement du système d'exploitation.
Cette opération est pourtant nécessaire pour:
  1. Utiliser librement Python en ligne de commande.
  2. Installer easy_install, un script permettant d'installer facilement des packages/libraires python depuis le repository.
En créant une variable system PYTHON_HOME pointant vers le répertoire d'installation de pyhton (c:\python26 dans mon cas) et en ajoutant %PYTHON_HOME% dans la variable d'environnement PATH, Python devient invocable en ligne de commande.
Plus de détails dans cet excellent article "Python development on Windows [Part 1]:Installing Python"

Easy_Install
easy_install est un script d'installation permettant de downloader et d'installer facilement des packages/librairies Python sur un environnement de développement (ou production).
Les packages/librairies Python sont répertoriés sur le repository  Python Package Index (PyPI)

C'est en voulant manipuler des documents XML que j'ai découvert ElementTree (probablement la meilleure implémentation XML sous Python). Ce module lxml est basé sur libxml. Lxml est disponible à l'installation sur le repository Python Package Index (ici http://pypi.python.org/pypi/lxml/2.2.3) et s'installe à l'aide de easy_install!

Malheureusement, easy_install n'est pas disponible, par défaut, dans les installations Windows de Python.
L'article "Python development on Windows [Part 2]: Installing easy_install...could be easier" explique comment mettre en place cet incontournable outil.

Easy_install pour windows require l'installation de SetupTool (disponible sur cette page) également distribué sur PyPI. SetupTool place Easy_Install dans le répertoire %PYTHON_HOME%\scripts .
%PYTHON_HOME%\scripts devra être ajouter à la variable d'environnement PATH pour autoriser l'exécution de easy_install en ligne de commande.

mardi 3 novembre 2009

SqlServeur training - Maintaining Sql2008 database - Jour 4

Cette quatrième journée traite principalement du monitoring et des modèles de réplication.

J'ai pris tellement de retard dans la retranscription de mes notes que j'ai même perdu de vue ce quatrième volet que je publie enfin (précédents articles:  jour 1, jour 2, jour 3). Cependant, la section relative à réplication ne sera pas aussi complète que je l'avais initialement prévu. La réplication est un vaste domaine dont la complexité nécessiterait plusieurs articles. Ne disposant malheureusement pas de ce temps que j'investis plutôt dans Python, je me limiterai donc à une approche introductive.  

Dominique, le 2 novembre 2009

Eléments de monitoring
  • Activity monitor: Seulement disponible dans sql serveur 2008 via le management console, l'activity monitor présente différents graphes (CPU Usage, Waiting tasks, Database IO), des informations complémentaires (data file IO information, ressources waits, recent expensive queries, etc), la liste des processes en auto-refresh. Super pratique pour avoir une vue d'ensemble d'un serveur sql.
  • L'usage de stored procedure: sp_who, sp_lock 
  • L'usage de Dynamic Management View: voir plus loin.
Monitoring - les éléments importants
Les éléments principaux à monitorer sont les suivants:
  • La mémoire
  • Les disques (s'applique diffiicilement au San)
  • Le processeur
  • Le réseau
Monitorer la mémoire
En suivant l'évolution du perfom "Cache Hit Ratio" il est possible de savoir si sql serveur dispose d'assez de mémoire.
Si ce ratio tombe en dessous de 90 %, il faut intervenir (ajout de mémoire ou éventuellement vérifier le data modèle et indexes si déjà assez de mémoire).
Voir SqlServer BufferManager::Cache it ratio

Monitorer les performance disque
Les requêtes de lectures tombent dans une queue de lecture si les disques ne savent pas suivre le flot des demandes d'accès. Pour savoir si les disques deviennent un goulot d'étranglement, il suffit de garder cette queue à l'oeil. En gros, elle ne doit jamais excéder 3 * le nombre de disque physique disponible (même rarement).
Ainsi, pour 3 disques en raid, cette valeur ne peut excéder 15.
Voir perfMon, Physical Disk::Avg Disk Queue length ou Physical Disk::Current Disk Queue length.
Les lecteurs lents peuvent également être détectés via la "dynamic management view" sys.dm_io_pending_io_requests car ils y feront apparaitre des entrées.

Toutes ces considérations n'étant pas applicable au stockage de données sur SAN.
Le seule commentaire reçu concernant le stockage SAN, c'est qu'il serait opportun d'utiliser plusieurs fichiers sur différent lecteurs (virtuels) pour stocker les données; ainsi sql serveur pourra stresser plus fort le système d'accès disque SAN et fournir de meilleurs temps de réponse sql.

Performance processeur
En monitorant les performances du processeur, il est possible de savoir si la machine dipose de cette ressource en suffisance (nbre et fréquence).
Si PerfMon démontre une utilisation continue de 80% à 90% alors les ressources processeurs sont insuffissantes.

Monitoring - Performance monitor et Sql profiler (**)
Voici une méthode de monitoring très intéressante et surtout très partique.
Tout d'abord, il faut savoir qu'il est possible de configurer le "performance monitor" de windows pour qu'il capture les traces et les enregistrer dans un fichier.
En exemple pratique, capturons Hit ratio, Cpu usage, Disk Queue toutes les deux secondes, le tout à enregistrer dans un fichier.
Durant ce temps, on utilise le Sql Profiler pour monitorer les opérations effectuées par sql serveur.

Lorsqu'un événement anormal est détecté dans le profiler (requêtes anormalements lentes, temps de réponse anormal, etc), il est alors possible de comparer ces événements avec les données collectées par le performance monitor.
A cet effet, Sql Profiler dispose d'une option d'import de fichier perfMon (menu File). Une fois les données perfMon chargées, la sélection d'un événement dans le profiler affiche, en regard, l'état des traces de performance. Il est donc possible de connaître l'état des ressources de la machine à l'instant de l'évènement.

Pour bénéficier correctement de cette fonctionalité, il faut bien entendu que la machine exécutant le perfmon d'une part (sql serveur) et le sql profiler (un serveur quelconque) aient tous deux une configuration horaire correcte (la synchronization des horloges systèmes étant ici primodiale).

Monitoring avec l'aide des DMV
Voici quelques notes concernant les dynamic management view qui peuvent aider à monitorer sql server. Il existe beaucoup de DMV disponible dans SQL serveur et seulement quelques-unes seront aborder ici.

sys.dm_exec_session

select * from sys.dm_exec_session where session_id > 50
Retourne une information similaire a sp_who.

sys.dm_db_index_usage_stats
Retourne des information concernant l'usage des indexes.
En autre, il y est possible de savoir si un index est exploité ou scanné (le cluster index scan étant assez cher en ressource).
select * from sys.dm_db_index_usage_stats
Index_id: 1 pour les clustered index, >1 pour autres indexes. 
User_seeks: nbre de fois que l'index a été utilisé pour retrouver des données.
User_scan: nbre de fois que l'index à été entièrement lu.

sys.dm_exec_query_stats
Permet de connaître les query les plus souvents exécutés (via execution_count) ainsi que leurs coûts en opérations disques.  
select total_physical_reads + total_logical_reads + total_physical_writes from sys.dm_exec_query_stats order by 1

L'article "Are you using sql's missing index DMV" du Weblog de Bart Duncan expliquant comment utiliser les DMV pour découvrir les indexes manquant dans Sql Server.

sys.dm_io_pending_io_requests
Cette dynamic management view indique les accès disques en attente dans une queue.
Elle permet donc de savoir si les disques représente ou non un goulot d'étranglement.

LECTURE autour des dynamic management view (**)

Le livre "Inside Sql Server 2005: Query Tuning and optimization" (édt: Microsoft Press) explique et utilise de nombreuses DMVs.


La réplication

La réplication est un procédé permettant de mettre une partie des informations d'une DB à disposition dans une autre DB
Parmis les cas d'utilisation de la réplication, il y a:
  • Mise à disposition de données pour "Reporting".
  • Consolidation des données de différents départements.
    Par exemple, chaque pays (FR, UK, NL) disposant de ses sales orders, le tout consolidé régulièrement à la maison mère (BE).
  • Mettre des données à disposition auprès des utilisateurs finaux.
    Par exemple, la maison mère (BE) "publiant"
    la nouvelle liste des prix dans les différents départements (FR, UK, NL).
  • Mettre des données à disposition en mode déconnecté.
    C'est par exemple le cas des vendeurs itinérants. En utilisant une réplication de type "merge", ils peuvent remplir des bons de commandes sur leur portable (dans une DB locale) pour ensuite la synchroniser avec la DB principale une fois le portable reconnecter sur le réseau d'entreprise.

Mise en garde!

En aucun cas, la réplication peut être assimilée à un procédé permettant de faire du "load balancing" entre serveurs sql. 
Pour être clair, Microsoft ne dispose pas - à l'heure actuelle - de solution de "load balancing" entre plusieurs sql serveurs. 

La réplication - la métaphore

Le modèle de la publication des livres comme métaphore

Pour facilité la compréhension des modèles et procédés de de réplication, Microsoft a bâti son modèle de réplication sql sur le modèle commerciale de la publication des livres/revues.
Ainsi, en suivant ce modèle, l'on retrouve les éléments suivants:
Publisher:

Un publisher sera un serveur sql mettant des publications à disposition (a comprendre comme "des revues contenant des données").
Les publications sont constitués d'articles; les articles étant les éléments d'informations à repliquer (ensemble de tables, partiel ou non, de colonnes, éléments sql, etc).
Subscriber:
A l'identique du modèle commercial, les gens souscrivent (subscribe) des abonnements pour obtenir un exemplaire des revues publiées.
Ainsi donc, un subscriber sera un serveur sql ayant souscrit un abonnement chez un publisher pour obtenir une copie des données (les "articles" dans le langague de la réplication) qu'il stockera dans une de ses propres bases de données.

Distributor:
Toujours en suivant le modèle économique de l'édition, le distributeur (distributor) aura pour mission d'acheminer les informations entre le publisher et le subscriber.



En résumé: 
Un processus de réplication fait intervenir 3 services de sql serveur.
Un publisher (les données à dupliquer), un ou plusieurs subscribers (les destinataires recevant les données) et un ou plusieurs distributors (achéminant les données).

Ces 3 services peuvant fonctionner sur un seul serveur sql ou sur des sql serveurs distincts.
Il est communément admit de faire fonctionner le distributor sur la même serveur sql que le publisher (voir, selon condition décrite ci-après, faire fonctionner le service de distribution sur les subscribers).

S'il y a moins de 3 subscribers:
Le distributor peut être installé sur le publisher. Dans ce cas, le couple publisher-distributor pousse les données sur les subscribers. 
Ce modèle est appellé "push replication".

S'il y a plus de 3 subscribers:
C'est en autre les cas des laptops connectés en intermittence.

Dans ce cas, Microsoft conseille de faire fonctionner un distributor par subscriber.
Dans ce cas, le couple subscriber-distributor extrait les données du publisher lorsqu'ils est connecté. 
Ce modèle est appellé "pull réplication"


La réplication -  Limitation 
En générale, il est possible de répliquer des données entre sql serveurs dans les deux sens.
Cependant, la réplication avec une db oracle n'est possible que dans un seul sens; à savoir uniquement de SqlServer vers Oracle.
 

La réplication - types de réplications

D'une façon générale, il est convenable de concevoir la réplication comme un processus allant dans une seule direction. A savoir, la copie des données du publisher vers les subscribers.
Cependant, il est également possible de concevoir des réplications ou les subscribers font des mises-à-jour de données sur le publisher (Merge réplication, voir plus loin).
 

Sql serveur dispose de plusieurs modèles de réplications: 
  • Snapshot: Ne fonctionne que dans un seul sens. A ne pas utiliser trop souvent en production car cette réplication est très gourmande en ressource. L'utilitaire bcp étant utilisé pour la réplication snapshot, la table est entièrement dupliquée dans un fichier qui est ensuite transmis au subscriber (où il sera ensuite recharger).
  • Merge Replication: Permet de synchroniser des données dans les deux sens. Dans ce cas, des conflits de synchronisation peuvent apparaître si les données ont étés modifiées sur les deux serveurs. Ces conflits sont gérés automatiquement sur base d'une règle de priorité ou règles plus avancées (NB: règle définie pour chaque élément des articles). Un gestionnaire de conflit permet de visualiser les collision de synchronisations et d'éventuellement les corriger.
  • Transactional Replication: Tout comme la réplication snapshot, cette réplication ne fonctionne que dans un seul sens. Le "log reader agent" du distributor inspecte le transaction log du publisher et y collecte les modifications concernant les articles (information stockée localement sur le distributor). Le "distributor agent" du distributor collecte ces informations et les poussent vers les subscribers. 
  • Transactional Replication with update from subscriber: sorte de replication bi-directionnelle basée sur la réplication transactionnelle. Visiblement rien de très intéressant ou spécial, l'instructeur faisant l'impasse sur ce point.
  • Peer to Peer replication:  réplication bi-directionnelle basé sur les modifications du transactional log ou les SQL serveurs sont en contacts directs. 
    Ce type de réplication est utilisé dans des cas plus spéciaux ou il est même possible d'éviter les problèmes de synchronisation (merge error) en partitionnant intelligement les données entre serveurs (voir 8-42). La réplication peer to peer peut aussi être utilisée pour améliorer les performances et la scalabilité, avoir un meilleur contrôle sur le traffic réseau, peut convenir pour les connections intermittentes (mais pas des jours!) ou encore pour implémenter un "load-Balancing" maison (voir 8-40).
La réplication - activation
Par principe, la réplication est schedulée à interval régulier. 
En effet, une réplication continue est bien trop couteuse en ressources.

Lorsqu'il s'agit de laptops itinérants, il est même préférable de lancer la replication depuis le laptop sur action de l'utilisateur.
Dans ce cas, on utilise un bout de code sur l'api SMO qui active le PULL distributor du laptop.

-- fin --