Suivi par une application des mises à jour des mappes

Lorsqu'une application apporte des modifications à une mappe pendant une transaction, un objet LogSequence assure le suivi de ces modifications. Si l'application modifie une entrée de la mappe, un objet LogElement correspondant détaille la modification.

Les chargeurs reçoivent un objet LogSequence pour une mappe particulière dès qu'une application appelle une méthode flush ou commit dans la transaction. Le chargeur itère sur les objets LogElement dans l'objet LogSequence et applique chaque objet LogElement au dorsal.

Les écouteurs ObjectGridEventListener enregistrés auprès d'une ObjectGrid utilisent également les objets LogSequence. Ces écouteurs reçoivent un objet LogSequence pour chaque mappe dans une transaction validée. Les applications peuvent utiliser ces écouteurs pour attendre la modification de certaines entrées, comme un déclencheur dans une base de données traditionnelle.

Les interfaces ou classes liées aux journaux présentées ci-dessous sont fournies par la structure d'eXtreme Scale :

Interface LogElement

Un objet LogElement représente une opération effectuée sur une entrée pendant une transaction. Un objet LogElement comporte plusieurs méthodes permettant d'obtenir les divers attributs associés. Les attributs les plus couramment utilisés sont les attributs type et valeur actuelle extraits par les méthodes getType() et getCurrentValue().

Le type est représenté par une des constantes définies dans l'interface LogElement : INSERT, UPDATE, DELETE, EVICT, FETCH ou TOUCH.

La valeur actuelle représente la nouvelle valeur pour l'opération si cette dernière est INSERT, UPDATE ou FETCH. Si l'opération est TOUCH, DELETE ou EVICT, la valeur actuelle est égale à null. Cette valeur peut être transtypée en ValueProxyInfo lorsqu'une interface ValueInterface est utilisée.

Pour plus de détails sur l'interface LogElement, consultez la documentation relative à l'API.

Interface LogSequence

Dans la plupart des transactions, des opérations sont effectuées sur plusieurs entrées d'une mappe, ce qui implique la création de plusieurs objets LogElement. Il est conseillé de créer un objet qui se comporte en tant que composite de plusieurs objets LogElement. L'interface LogSequence remplit cette fonction en contenant une liste d'objets LogElement.

Pour plus de détails sur l'interface LogSequence, consultez la documentation relative à l'API.

Utilisation des objets LogElement et LogSequence

Les objets LogElement et LogSequence sont fréquemment utilisés dans eXtreme Scale et par les plug-in ObjectGrid écrits par les utilisateurs lorsque des opérations sont propagées d'un composant ou d'un serveur sur un autre composant ou serveur. Par exemple, un objet LogSequence peut être utilisé par la fonction de propagation de la transaction ObjectGrid répartie afin de propager les modifications sur les autres serveurs, ou il peut être mis en oeuvre au niveau du stockage de persistance par le chargeur. L'objet LogSequence est principalement utilisé par les interfaces suivantes.

  • com.ibm.websphere.objectgrid.plugins.ObjectGridEventListener
  • com.ibm.websphere.objectgrid.plugins.Loader
  • com.ibm.websphere.objectgrid.plugins.Evictor
  • com.ibm.websphere.objectgrid.Session

Exemple de chargeur

Cette section illustre l'utilisation des objets LogSequence et LogElement dans un chargeur. Un chargeur permet de charger des données à partir d'un stockage de persistance et de les y conserver. La méthode batchUpdate de l'interface Loader utilise l'objet LogSequence :

void batchUpdate(TxID txid, LogSequence sequence) throws
			LoaderException, OptimisticCollisionException;

La méthode batchUpdate est appelée lorsqu'une ObjectGrid doit refléter toutes les modifications en cours dans le chargeur. Le chargeur obtient une liste des objets LogElement pour la mappe, encapsulés dans un objet LogSequence. L'implémentation de la méthode batchUpdate doit parcourir les modifications et les appliquer au programme d'arrière plan. Le fragment de code suivant montre comment un chargeur utilise un objet LogSequence. Le fragment de code parcourt l'ensemble des modifications et traite par lots trois instructions JDBC (Java Database Connectivity) : inserts, updates et deletes :

public void batchUpdate(TxID tx, LogSequence sequence) throws LoaderException
{
    // Etablissez une connexion SQL à utiliser.
    Connection conn = getConnection(tx);
    try
    {
    // Traitez la liste des modifications et créez un ensemble d'instructions
    // préparées pour l'exécution d'une opération SQL par lots update, insert
    // // ou delete. Les instructions sont mises en cache dans stmtCache.
    Iterator iter = sequence.getPendingChanges();
    while(iter.hasNext())
    {
        LogElement logElement = (LogElement)iter.next();
        Object key = logElement.getCacheEntry().getKey();
        Object value = logElement.getCurrentValue();
        switch ( logElement.getType().getCode() )
        {
            case LogElement.CODE_INSERT:
                buildBatchSQLInsert( key, value, conn );
                break;
            case LogElement.CODE_UPDATE:
                buildBatchSQLUpdate( key, value, conn );
                break;
            case LogElement.CODE_DELETE:
                buildBatchSQLDelete( key, conn );
                break;
        }
    }
    // Exécutez les instructions par lots créées par la boucle au-dessus.
    Collection statements = getPreparedStatementCollection( tx, conn );
    iter = statements.iterator();
    while(iter.hasNext())
    {
        PreparedStatement pstmt = (PreparedStatement) iter.next();
        pstmt.executeBatch();
    }
} catch (SQLException e)
{
    LoaderException ex = new LoaderException(e);
    throw ex;
}
}

L'exemple précédent illustre la logique de niveau supérieur du traitement de l'argument LogSequence. Toutefois, les détails de la création d'une instruction SQL insert, update ou delete ne sont pas illustrés. La méthode getPendingChanges est appelée sur l'argument LogSequence pour obtenir un itérateur des objets LogElement qu'un chargeur doit traiter et la méthode LogElement.getType().getCode() sert à déterminer si un objet LogElement correspond à une opération SQL insert, update, ou delete.

Exemple d'expulseur

Les objets LogSequence et LogElement peuvent également être utilisés en tant qu'expulseur. Un expulseur permet d'expulser les entrées de mappe de la mappe de sauvegarde en fonction de certains critères. La méthode apply de l'interface Evictor utilise l'objet LogSequence.

/**
* Elle est appelée lors de la validation du cache pour permettre à l'expulseur de contrôler l'utilisation des objets
* dans une mappe de sauvegarde. Toutes les entrées correctement expulsées sont également
* signalées.
*
* @param sequence LogSequence des modifications apportées à la mappe
*/
void apply(LogSequence sequence);

Pour plus d'informations sur l'utilisation de l'objet LogSequence par la méthode apply, reportez-vous à l'exemple de code présenté dans la rubrique Ecriture d'un expulseur personnalisé.

Interfaces LogSequenceFilter et LogSequenceTransformer

Il est parfois nécessaire de filtrer les objets LogElement de façon à en accepter uniquement certains répondant à des critères spécifiques et à rejeter les autres. Par exemple, il est conseillé de sérialiser un objet LogElement donné en fonction de certains critères.

L'interface LogSequenceFilter résout ce problème à l'aide de la méthode suivante.

public boolean accept (LogElement logElement);

Cette méthode renvoie la valeur true si l'objet LogElement donné doit être utilisé dans l'opération et renvoie la valeur false si l'objet LogElement donné ne doit pas être utilisé.

LogSequenceTransformer est une classe qui utilise la fonction LogSequenceFilter. Elle utilise l'interface LogSequenceFilter pour filtrer certains objets LogElement, puis pour sérialiser les objets LogElement acceptés. Cette classe comprend deux méthodes. La première méthode est la suivante.

public static void serialize(Collection logSequences, ObjectOutputStream stream,
			LogSequenceFilter filter, DistributionMode mode) throws IOException

Cette méthode permet au demandeur de fournir un filtre pour déterminer les objets LogElements à inclure dans le processus de sérialisation. Le paramètre DistributionMode permet au demandeur de contrôler le processus de sérialisation. Par exemple, si le mode de distribution est invalidation uniquement, la valeur n'a pas besoin d'être sérialisée. La deuxième méthode de cette classe est la méthode inflate, telle que décrite ci-après.

public static Collection inflate(ObjectInputStream stream, ObjectGrid
			objectGrid) throws IOException, ClassNotFoundException

La méthode inflate lit le formulaire sérialisé de la séquence de journal qui a été créé par la méthode à partir du flux d'entrée de l'objet fourni.