====== Optimiser pacman ======

Vous voulez améliorer la vitesse d'éxécution de pacman, le gestionnaire de paquet d'Archlinux ?
Vous ne comprenez pas pourquoi pacman est si lent ?

Aller : hop, hop, hop, améliorons tout ça.

===== Quelques précisions =====


La base de donnée de pacman repose sur l'utilisation de petits fichiers. Il a été conçu comme ça et est de reste extrêmement puissant pour les tâches auquel il est destiné.

Ces fichiers se fragmentent rapidement et entraîne le ralentissement de pacman, au point d'attendre 30 secondes pour obtenir le résultat d'une recherche faîte à l'aide d'un pacman -Ss. C'est anormal. Voyons comment y remédier.

===== Utiliser une partition de type reiserfs =====

Étant donné que pacman utilise un nombre important de petits fichiers, il est préférable d'utiliser une partition de type **reiserfs**, du moins pour la partition qui accueillera la base de donnée de pacman ( qui se trouve dans /var/lib/pacman ). Le format reiserfs gère en effet mieux les petits fichiers, en évitant que ceux-ci fragmentent le disque, ce qui rend la lecture plus lente. \\
\\
Reiserfs est offert lors de l'installation d'Arch Linux. Sinon, il est possible de formater une partition en reiserfs en suivant ces 2 étapes :
  * Installer le paquet **reiserfsprogs**
  * Formater avec la commande mkreiserfs
    <code> $ mkreiserfs /dev/hda1 </code>
\\
Attention! : Le formatage d'une partition détruira l'ensemble des fichiers qui s'y trouvent, assurez-vous de faire vos sauvegardes avant et de bien désigner la bonne partition. 
\\
===== pacman-optimize =====

**pacman-optimize** est un petit script bash inclus avec pacman depuis la version 3.0 . Celui-ci tente de relocaliser l'ensemble des petits fichiers de la base de donnée de pacman sur une section contigue du disque dur, ce qui diminue les déplacements de la tête de lecture du disque et réduit donc le temps de lecture.\\
\\
Pour utiliser la commande, il suffit de la lancer directement : 
\\
<code>$ pacman-optimize </code>
\\
Il est recommandé de lancer pacman-optimize de façon périodique, par exemple à tous les mois. Pour ce faire, vous pouvez créer un lien vers **/usr/bin/pacman-optimize** dans **/etc/cron.monthly/** 
\\
<code>$ ln -s /usr/bin/pacman-optimize /etc/cron.monthly/ </code>
\\
Assurez-vous aussi que le service cron est activé sur vôtre système. Le service **'cron'** doit être ajouté à la liste DAEMONS= du fichier /etc/rc.conf s'il n'y figure pas déjà.
\\

===== pacman-cage =====

pacman-cage a été écrit par ody. Ce programme publié depuis longtemps sur le [[http://bbs.archlinux.org/viewtopic.php?t=20385|forum anglais]] permet d'accélérer incroyablement le fonctionnement de pacman (et de yaourt).
\\
Vous trouverez une version améliorée sur le dépôt [archlinuxfr]:
<code>[archlinuxfr]
Server = http://repo.archlinux.fr/i686</code>
\\
__**Sauvegarde:**__
Avant de faire quoi que ce soit, il est recommendé d'effectuer une sauvegarde de la base pacman. Pour cela, lancez:
<code>yaourt -B</code>
\\
__**Utilisation:**__
Installez le paquet **'pacman-cage'**.\\
Lancez en root la commande **pacman-cage**\\
=> pacman-cage va sauvegarder les fichiers nécessaires au fonctionnement de pacman et créer une base de données de ces fichiers (un fichier loopback)\\
Vous pouvez tout de suite utiliser pacman et tous les outils habituels (yaourt, pacmenu, srcpac, jacman, gtkpacman etc...) avec une vitesse largement améliorée !!  :) \\

Ajoutez 'pacmandb' à votre fichier /etc/rc.conf dans la liste des daemons (avant 'nvidia' si vous l'utilisez).\\
\\
Les améliorations apportées sont:\\
- vérification du support de loopback device dans le kernel \\
- utilisation d'un démon pour lancer au démarrage une vérification de l'intégrité de la base avant le montage du fichier loopback\\
- vérification de sécurité dans pacman-uncage\\
\\

===== pacman-drive =====


Pacman-drive est un script qui a été écrit par gandalf, un membre du forum anglais d'archlinux

Ce script se charge de sauvegardé la base de donnée de pacmann de lui créer un espace réservé et enfin de l'y copier.

Cela permet de ne plus se préoccuper de la fragmentation
==== Récupération et installation du script ====


Le script peut-être récupéré sur le [[http://bbs.archlinux.org/viewtopic.php?t=22600|sujet]] du forum anglais, sur le [[http://forums.archlinux.fr/viewtopic.php?t=30|dépôt archlinux.fr]] ou ci-dessous.

Il suffit de se connecter en tant que root, de copier le script récupérer dans le répertoire sbin (par exemple) # ''cp /home/user/pacman-drive /sbin/pacman-drive'', de le rendre exécutable par la commande ''# chmod +x /sbin/pacman-drive'', et enfin de l'exécuter : ''# /sbin/pacman-drive create''.


Le script : 
<code bash>
#!/bin/sh
###
#   This script will create a small drive for pacman usage
#   It will increase pacman speed around 60%
#   Copyright (C) 2006, Wael Nasreddine <wael@phoenixlinux.org>
#
#   This program is free software; you can redistribute it and/or
#   modify it under the terms of the GNU General Public License
#   as published by the Free Software Foundation; either version 2
#   of the License, or (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
###

# $Author: wael $
# $Revision: 348 $
# $Date: 2006-06-26 01:54:37 +0200 (Mon, 26 Jun 2006) $

. /etc/rc.conf
. /etc/rc.d/functions
. /etc/makepkg.conf

myver='1.0'
pacman_db="/var/lib/pacman"
pacman_drive="/var/lib/pacman.img"
pacman_backup="/root/pacman-database.tar.bz2"
img_size=200 # In Mega-byte

###
# Ripped from Phoenix pacman-functions
###

plain() {
    local msg i
    for i in ${@}; do
        msg="${msg} ${i}"
    done
    if [ "$USE_COLOR" = "Y" -o "$USE_COLOR" = "y" ]; then
        echo -e "    \033[1;1m${msg}\033[1;0m" >&2
    else
        echo "    ${msg}" >&2
    fi
}

msg() {
    local msg i
    for i in ${@}; do
        msg="${msg} ${i}"
    done
    if [ "$USE_COLOR" = "Y" -o "$USE_COLOR" = "y" ]; then
        echo -e "\033[1;32m==>\033[1;0m \033[1;1m${msg}\033[1;0m" >&2
    else
        echo "==> ${msg}" >&2
    fi
}

warning() {
    local msg i
    for i in ${@}; do
        msg="${msg} ${i}"
    done
    if [ "$USE_COLOR" = "Y" -o "$USE_COLOR" = "y" ]; then
        echo -e "\033[1;33m==> WARNING:\033[1;0m \033[1;1m${msg}\033[1;0m" >&2
    else
        echo "==> WARNING: ${msg}" >&2
    fi
}

error() {
    local msg i
    for i in ${@}; do
        msg="${msg} ${i}"
    done
    if [ "$USE_COLOR" = "Y" -o "$USE_COLOR" = "y" ]; then
        echo -e "\033[1;31m==> ERROR:\033[1;0m \033[1;1m${msg}\033[1;0m" >&2
    else
        echo "==> ERROR: ${msg}" >&2
    fi
}

Pdie()
{
    [[ ! -z $1 ]] && error $@
    exit 2
}

check_root() {
    if [ "$(id -u)" -ne 0 ]; then
        return 1
    fi
}

###
# End alternate copyright
###

die () {
    cleanup
    rm -f /tmp/pacman.lck
    if [ "${action}" = "delete" ]; then
        # If we were trying to delete the pacman-drive
        # we should mount back the database!
        mount -t ext2 -o loop "${pacman_drive}" "${pacman_db}" >/dev/null 2>&1
    fi
    Pdie "$@"
}

usage () {
    echo "pacman-drive $myver"
    echo "usage: $0 <action>"
    echo "action can be:"
    echo "  create  create the pacman-drive and use it."
    echo "  delete  delete the pacman-drive and use the usual folder."
    echo ""
    echo "This script will create a small (200 Mb) image to use it as"
    echo "pacman database, the file will have an ext2 filesystem."
}

### Generate md5sum of a directory and print it into a file
 # @param directory to get the md5 for
 # @param file to put the output in
 ##
get_dir_md5() {
    [ -z "${1}" -o -z "${2}" ] && \
        return 1
    [ ! -d "${1}" -o -f "${2}" ] && \
        return 1

    find "${1}" -type f | sort | xargs md5sum > "${2}" 2>/dev/null || \
        die "Error generating md5sum of ${1}"
    return 0
}

prepare_drive() {
    if [ -f "${pacman_backup}" ]; then
        die "${pacman_backup} file already exists, please remove it first."
    else
        msg "backing up the pacman database."
        tar cjf "${pacman_backup}" "${pacman_db}" >/dev/null 2>&1 || \
            die "Error creating the backup tarball."
    fi
    pacdrivetmp="$(mktemp -d /tmp/pacdrivetmp.XXXX)"
    paclibtmp="$(mktemp -d /tmp/paclibtmp.XXXX)"
    old_md5="$(mktemp /tmp/pac-db-old.XXXX)"
    new_md5="$(mktemp /tmp/pac-db-new.XXXX)"
    touch /tmp/pacman.lck
}


cleanup() {
    if grep -q "${pacdrivetmp}" /proc/mounts &>/dev/null; then
        umount "${pacdrivetmp}" >/dev/null 2>&1
    fi
    rm -rf "${pacdrivetmp}" "${paclibtmp}" "${old_md5}" "${new_md5}" /tmp/pacman.lck
}

create_drive() {
    prepare_drive

    if [ -f "${pacman_drive}" ]; then
        die "${pacman_drive} already exist."
    fi

    msg "creating pacman.img loopback file..." 
    dd if=/dev/zero of="${pacman_drive}" bs=1M count="${img_size}" > /dev/null 2>&1 || \
        die "Error create the pacman image drive."
    yes | mkfs.ext2 -O dir_index -b 1024 -i 1024 -m 0 "${pacman_drive}" > /dev/null 2>&1 || \
        die "Could not create image filesystem."

    msg "mounting pacman-drive to a temporary mount point."
    mount -t ext2 -o loop "${pacman_drive}" "${pacdrivetmp}" >/dev/null 2>&1 || \
        die "Error mounting pacman drive to a temporary mount point."

    msg "Copying pacman database to the temporary mount point."
    cp -a "${pacman_db}/." "${pacdrivetmp}/" >/dev/null 2>&1 || \
        die "Error copying the database."

    msg "Generating md5sum of the old and new database."
    get_dir_md5 "${pacman_db}" "${old_md5}"
    get_dir_md5 "${pacdrivetmp}" "${new_md5}"

    msg "Unmount the temporary mount point."
    umount "${pacdrivetmp}" || \
        die "Error while unmounting the temporary mount point."

    msg "Comparing the old and new database."
    diff "${old_md5}" "${new_md5}" &>/dev/null
    if [ $? -ne 0 ]; then
        rm -f "${pacman_drive}"
        die "md5 of the old and new database does not match, Aborting..."
    fi

    # Ok now let's remove the old database folder, and finishing the task
    msg "removing the old database folder."
    rm -rf "${pacman_db}"

    # mounting the new db
    mkdir -p "${pacman_db}"
    mount -t ext2 -o loop "${pacman_drive}" "${pacman_db}" || \
        die "Error mounting pacman-drive."

    # adding the loop device to fstab
    if ! grep -q "${pacman_drive}" /etc/fstab &>/dev/null; then
        msg "Adding loop device to fstab."
        echo "${pacman_drive} ${pacman_db} ext2 loop,defaults 0 0" >> /etc/fstab
    else
        warning "pacman-drive entry already exist in fstab. Skipping..."
    fi

    msg "Removing leftover files."
    cleanup

    msg "Done..."
}

delete_drive() {
    prepare_drive

    if [ ! -f "${pacman_drive}" ]; then
        die "${pacman_drive} does not exist, aborting..."
    fi

    msg "Unmounting pacman database."
    umount "${pacman_db}" >/dev/null 2>&1 || \
        die "Error while unmounting the old database."

    msg "mounting pacman-drive to a temporary mount point."
    mount -t ext2 -o loop "${pacman_drive}" "${pacdrivetmp}" >/dev/null 2>&1 || \
        die "Error mounting pacman drive to a temporary mount point."

    msg "Copying pacman-database to a new folder."
    cp -a "${pacdrivetmp}/." "${paclibtmp}/" >/dev/null 2>&1 || \
        die "Error while copying pacman-database to a new folder."

    msg "Generating md5 of the old and new database."
    get_dir_md5 "${pacdrivetmp}" "${old_md5}"
    get_dir_md5 "${paclibtmp}" "${new_md5}"

    msg "Unmount the temporary mount point."
    umount "${pacdrivetmp}" || \
        die "Error while unmounting the temporary mount point."

    msg "Comparing the old and new database."
    diff "${old_md5}" "${new_md5}" &>/dev/null
    if [ $? -ne 0 ]; then
        die "md5 of the old and new database does not match, Aborting..."
    fi

    # Ok everything checked let's continue
    msg "Unmounting pacman database (if mounted)"
    umount "${pacman_db}" >/dev/null 2>&1

    msg "Removing the pacman-drive loopback file..."
    rm -rf "${pacman_db}" || \
        die "Couldn't remove the old pacman database..." 
    rm -f "${pacman_drive}" || \
        die "Couldn't remove the pacman-drive loopback file..."

    msg "moving the new one to ${pacman_db}"
    mv "${paclibtmp}" "${pacman_db}" >/dev/null 2>&1 || \
        die "Error while moving the new one to ${pacman_db}."
    # We don't need the lost+found folder
    rm -rf "${pacman_db}/lost+found" >/dev/null 2>&1

    msg "Removing pacman-drive entry from fstab"
    sed -e "s@.*${pacman_drive}.*${pacman_db}.*@@g" -i /etc/fstab

    msg "Removing leftover files."
    cleanup

    msg "Done..."
}

# Sanity checks
check_root || die "You must be root to run pacman-drive"

# Check if kernel has BLK_DEV_LOOP support
if [ -f /proc/config.gz ]; then
    unset temp
    temp="$(zcat /proc/config.gz | grep "BLK_DEV_LOOP")"
    if [ "${temp}" != "CONFIG_BLK_DEV_LOOP=y" -a "${temp}" != "CONFIG_BLK_DEV_LOOP=m" ]; then
        error "Your kernel does not support loopback device, please recompile your kernel"
        plain "and make sure that CONFIG_BLK_DEV_LOOP equal m or y (NOT n)"
        exit 1
    fi
    unset temp
else
    unset agree
    warning "/proc/config.gz does not exist.. Cannot check for BLK_DEV_LOOP support."
    plain "If you are sure that your kernel support loopback device, type :"
    while [ "${agree}" != "I AM SURE THAT MY KERNEL SUPPORT LOOPBACK DEVICE" ]; do
        plain "I AM SURE THAT MY KERNEL SUPPORT LOOPBACK DEVICE"
        read agree
        agree="${agree}" #trim spaces...
    done
    unset agree
fi

if [ -f /tmp/pacman.lck ]; then
    error "Cannot run pacman-drive while using pacman."
    exit 1
fi

action="${1}"

if [ -z "${action}" -o \( "${action}" != "create" -a "${action}" != "delete" \) ]; then
    usage
    exit 1
fi

case "${action}" in
    create) create_drive ;;
    delete) delete_drive ;;
    *)      usage; exit 1 ;;
esac

# End Of File
# vim: set ft=sh ts=4 sts=4 sw=4 expandtab:
</code>

