Seguimiento de las actualizaciones de correlación de una aplicación

Cuando una aplicación está realizando cambios en una Correlación durante una transacción, un objeto LogSequence rastrea estos cambios. Si la aplicación cambia una entrada en la correlación, un objeto LogElement correspondiente proporciona los detalles del cambio.

Se proporciona a los cargadores un objeto LogSequence para una correlación particular siempre que una aplicación llama a un método para desechar o confirmar la transacción. El cargador se repite en los objetos LogElement dentro del objeto LogSequence y aplica cada objeto LogElement al programa de fondo.

Los receptores de ObjectGridEventListener que se han registrado con un ObjectGrid también utilizan objetos LogSequence. Se proporciona a estos receptores un objeto LogSequence para cada correlación en una transacción confirmada. Las aplicaciones pueden utilizar estos receptores para esperar a que cambien determinadas entradas, como un desencadenante en una base de datos convencional.

Las siguientes interfaces o clases relacionadas con el registro son proporcionadas por la infraestructura de eXtreme Scale:

Interfaz LogElement

Un LogElement representa una operación o una entrada durante una transacción. Un objeto LogElement tiene varios métodos para obtener sus distintos atributos. Los atributos utilizados de forma más habitual son los atributos de valor de tipo y actual capturados por getType() y getCurrentValue().

El tipo está representado por una de las constantes definidas en la interfaz LogElement: INSERT, UPDATE, DELETE, EVICT, FETCH o TOUCH.

El valor actual representa el nuevo valor para la operación si es INSERT, UPDATE o FETCH. Si la operación es TOUCH, DELETE o EVICT, el valor actual es nulo. Este valor se puede convertir a ValueProxyInfo cuando se utiliza ValueInterface.

Consulte la documentación de la API si desea más detalles sobre la interfaz LogElement.

Interfaz LogSequence

En la mayoría de las transacciones, las operaciones que se producen en más de una entrada de la correlación, así pues se crean varios objetos LogElement. Debe crear un objeto que se comporte como un compuesto de varios objetos LogElement. La interfaz LogSequence debe servir a este propósito incluyendo una lista de objetos LogElement.

Consulte la documentación de la API si desea más detalles sobre la interfaz LogSequence.

Utilización de LogElement y LogSequence

LogElement y LogSequence se utilizan ampliamente en eXtreme Scale y por los plug-ins de ObjectGrid que se han escrito por usuarios cuando se propagan las operaciones de un componente o servidor a otro componente o servidor. Por ejemplo, un objeto LogSequence puede ser utilizado por la función de propagación de transacción de ObjectGrid distribuido para propagar los cambios en otros servidores, o el cargador lo puede aplicar en el almacén de persistencia. LogSequence es utilizado principalmente por las siguientes interfaces.

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

Ejemplo de cargador

Esta sección demuestra cómo se utilizan los objetos LogSequence y LogElement en un cargador. Un cargador se utiliza para cargar datos y persistirlos en un almacén persistente. El método batchUpdate de la interfaz Loader utiliza el objeto LogSequence:

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

Se llama al método batchUpdate cuando un ObjectGrid debe aplicar todos los cambios actuales a Loader. Se proporciona a Loader una lista de objetos LogElement para la correlación, encapsulados en un objeto LogSequence. La implementación del método batchUpdate debe repetir los cambios y aplicarlos en el programa de fondo. El siguiente fragmento de código demuestra cómo Loader utiliza un objeto LogSequence. El fragmento de código se repite en el conjunto de cambios y genera tres sentencias de proceso por lotes JDBC (Java DataBase Connectivity): inserts, updates y deletes:

public void batchUpdate(TxID tx, LogSequence sequence) throws LoaderException {
    // Obtener una conexión SQL que vaya a utilizarse.
    Connection conn = getConnection(tx);
    try
    {
    // Procesar la lista de cambios y crear un conjunto de
    // sentencias preparadas para ejecutar una
    // operación SQL. Las sentencias se almacenan en la memoria caché
    // en 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;
        }
    }
    // Ejecute las sentencias de proceso por lotes que se crearon mediante
    // el bucle anterior.
    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;
}
}

El ejemplo anterior ilustra la lógica de alto nivel de proceso del argumento LogSequence. Sin embargo, el ejemplo no ilustra los detalles sobre cómo se crean una sentencia SQL insert, update o delete. Se llama al método getPendingChanges en el argumento LogSequence para obtener un iterador de objetos LogElement que un Loader debe procesar y se utiliza el método LogElement.getType().getCode() para determinar si un LogElement es para una operación SQL insert, update o delete.

Ejemplo de desalojador

También puede utilizar los objetos LogSequence y LogElement con un Evictor. Un Evictor se utiliza para desalojar las entradas de correlación de la correlación de respaldo basándose en determinados criterios. El método apply de la interfaz Evictor utiliza LogSequence.

/**
* Se llama a éste durante la confirmación de la memoria caché para permitir
* al desalojador rastrear el uso de objetos en una correlación de respaldo.
* También se informará sobre las entradas que se hayan desalojado
* correctamente.
*
* @param secuencia LogSequence de cambios en la correlación
*/
void apply(LogSequence sequence);

Si desea más información sobre cómo el método apply utiliza LogSequence, consulte el código de ejemplo en el tema Cómo escribir un desalojador personalizado.

Interfaces LogSequenceFilter y LogSequenceTransformer

A veces, es necesario filtrar los objetos LogElement de forma que sólo se aceptan los objetos LogElement con determinados criterios y se rechazan los otros objetos. Por ejemplo, es posible que desee serializar un LogElement determinado basándose en algún criterio.

LogSequenceFilter resuelve este problema con el siguiente método.

public boolean accept (LogElement logElement);

Este método devuelve el valor true si el LogElement determinado se debe utilizar en la operación, y devuelve el valor false si no se debe utilizar el LogElement proporcionado.

LogSequenceTransformer es una clase que utiliza la función LogSequenceFilter. Utiliza el LogSequenceFilter para filtrar algunos objetos LogElement y, a continuación, serializa los objetos LogElement aceptados. Esta clase tiene dos métodos. El primer método es el siguiente.

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

Este método permite al interlocutor proporcionar un filtro para determinar qué LogElements incluir en el proceso de serialización. El parámetro DistributionMode permite al interlocutor controlar el proceso de serialización. Por ejemplo, si la modalidad de distribución sólo es la invalidación, no es necesario serializar el valor. El segundo método de esta clase es el método inflate, del modo siguiente.

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

El método inflate lee el formulario serializado de la secuencia de registro, que se ha sido creado por el método serialize, desde la corriente de datos de entrada de objeto proporcionada.