Plug-ins para el mantenimiento de versiones y la comparación de objetos de memoria caché

Utilice el plug-in OptimisticCallback para personalizar las operaciones de creación de versiones y comparación de los objetos de la memoria caché cuando se utiliza la estrategia de bloqueo optimista.

Puede proporcionar un objeto de devolución de llamada optimista conectable que implementa la interfaz com.ibm.websphere.objectgrid.plugins.OptimisticCallback. En el caso de correlaciones de entidad, se configura automáticamente un plug-in OptimisticCallback de alto rendimiento.

Finalidad

Utilice la interfaz OptimisticCallback para proporcionar operaciones de comparación optimista para los valores de una correlación. Es necesario un plug-in OptimisticCallback al utilizar la estrategia de bloqueo optimista. El producto proporciona una implementación de OptimisticCallback predeterminada. Sin embargo, por lo general, la aplicación debe conectar su propia implementación de la interfaz OptimisticCallback.

Implementación predeterminada

La infraestructura de eXtreme Scale proporciona una implementación predeterminada de la interfaz OptimisticCallback que se utiliza si la aplicación no conecta un objeto OptimisticCallback proporcionado para la aplicación. La implementación predeterminada siempre devuelve el valor especial de NULL_OPTIMISTIC_VERSION como el objeto de versión del valor y nunca actualiza el objeto de versión. Esta acción hace que la comparación optimista sea una función "sin operación". En la mayoría de los casos, conviene que no se produzca la función "sin operación" cuando utilice la estrategia de bloqueo optimista. Las aplicaciones deben implementar la interfaz y conectar sus propias implementaciones OptimisticCallback de modo que no se utilice la implementación predeterminada. No obstante, existe un escenario donde resulta útil la implementación OptimisticCallback predeterminada. Observe la situación siguiente:
  • Se ha conectado un cargador para la correlación de respaldo.
  • El cargador sabe cómo realizar la comparación optimista sin ayuda de un plug-in OptimisticCallback.
¿Cómo puede realizar el cargador una creación de versiones optimista sin la ayuda de un objeto OptimisticCallback? El cargador conoce el objeto de clase de valor y sabe qué campo del objeto de valor se utiliza como valor de creación de versiones optimista. Por ejemplo, imagine que se utiliza la interfaz siguiente para el objeto de valor de la correlación de empleados.
public interface Employee
{
    // Número de secuencia utilizado para la creación de versiones optimista.
    public long getSequenceNumber();
    public void setSequenceNumber(long newSequenceNumber);
    // Otros métodos get/set para otros campos del objeto Employee.
}

En este ejemplo, el cargador sabe que puede utilizar el método getSequenceNumber para obtener la información de la versión actual para un objeto de valor Employee. El cargador incrementa el valor devuelto para generar un nuevo número de versión antes de actualizar el almacenamiento persistente con el nuevo valor Employee. Para un cargador JDBC (Java DataBase Connectivity), se utiliza el número de secuencia actual de la cláusula WHERE de una sentencia de SQL UPDATE sobrecualificada, y utiliza el nuevo número de secuencia generado para establecer la columna de número de secuencia en el nuevo valor de número de secuencia. Otra posibilidad es que el cargador utilice una función, que proporciona el programa de fondo, que actualiza automáticamente una columna oculta que puede utilizarse para la creación de versiones optimista.

En algunas situaciones, posiblemente se puede utilizar un procedimiento almacenado o un desencadenante que ayuda a mantener una columna que aloja información sobre la creación de versiones. Si el cargador utiliza una de estas técnicas para mantener la información de la creación de versiones optimista, la aplicación no necesita proporcionar una implementación OptimisticCallback. Se puede utilizar la implementación predeterminada de OptimisticCallback en este escenario porque el cargador puede manejar la creación de versiones optimista sin la ayuda de un objeto OptimisticCallback.

Implementación predeterminada de entidades

Las entidades se almacenan en ObjectGrid mediante objetos de tuple. El comportamiento predeterminado de la implementación OptimisticCallback es similar al comportamiento para las correlaciones sin entidades. Sin embargo, el campo de versión de la entidad se identifica a través del uso de la anotación @Version o el atributo de versión en el archivo XML de descriptor de la entidad.

El atributo de versión puede ser de uno de los tipos siguientes: int, Integer, short, Short, long, Long o java.sql.Timestamp. Una entidad sólo debe tener un atributo de versión definido. Establezca el atributo de versión sólo durante la construcción. Después de persistir la entidad, el valor del atributo de versión no se debe modificar.

Si no se configura el atributo de versión y se utiliza la estrategia de bloqueo optimista, se crea una versión implícitamente de todo el tuple mediante el estado completo del tuple, que es más costoso.

En el ejemplo siguiente, la entidad Employee tiene un atributo de versión de tipo long denominado SequenceNumber:
@Entity
public class Employee
{
private long sequence;
    // Número de secuencia utilizado para la creación de versiones optimista.
    @Version
    public long getSequenceNumber() {
        return sequence;
    }
    public void setSequenceNumber(long newSequenceNumber) {
        this.sequence = newSequenceNumber;
    }
    // Otros métodos get/set para otros campos del objeto Employee.
}

Escritura de un plug-in OptimisticCallback

Un plug-in OptimisticCallback debe implementar la interfaz OptimisticCallback y seguir los convenios comunes de plug-in de ObjectGrid. Consulte Interfaz OptimisticCallback si desea más información.

En la lista siguiente se proporciona una descripción o consideración de cada uno de los métodos de la interfaz OptimisticCallback:

NULL_OPTIMISTIC_VERSION

Este valor especial es devuelto por el método getVersionedObjectForValue si la implementación de OptimisticCallback no requiere ninguna comprobación de versiones. La implementación del plug-in incorporada de la clase com.ibm.websphere.objectgrid.plugins.builtins.NoVersioningOptimisticCallback utiliza este valor porque la creación de versiones está inhabilitada cuando se especifica esta implementación de plug-in.

Método getVersionedObjectForValue

El método getVersionedObjectForValue podría devolver una copia del valor o un atributo del valor que se puede utilizar para la creación de versiones. Este método se llama siempre que se asocia un objeto con una transacción. Si no se conecta ningún cargador a la correlación de respaldo, ésta utiliza este valor durante la fase de confirmación para llevar a cabo una comparación de versiones optimista. La correlación de respaldo utiliza la comparación de versiones optimista para asegurarse de que la versión no ha cambiado desde la primera que vez que esta transacción accedió a la entrada de la correlación que fue modificada por esta transacción. Si otra transacción hubiera modificado la versión de esta entrada de correlación, se produciría una anomalía en la comparación de versiones y la correlación de respaldo mostraría una excepción OptimisticCollisionException que forzaría la retrotracción de la transacción. Si hay un cargador conectado, la correlación de respaldo no utiliza la información de creación de versiones optimista. En su lugar, el cargador deberá realizar una comparación de versiones optimista y actualizar la información de la creación de versiones cuando sea necesario. El cargador suelte obtener el objeto de versiones inicial del LogElement pasado al método batchUpdate del cargador, que se llama cuando se produce una operación de vaciado o se confirma una transacción.

El código siguiente muestra la implementación que utiliza el objeto EmployeeOptimisticCallbackImpl:
public Object getVersionedObjectForValue(Object value)
{
    if (value == null)
    {
        return null;
    }
    else
    {
        Employee emp = (Employee) value;
        return new Long( emp.getSequenceNumber() );
    }
}

Tal como se demuestra en el ejemplo anterior, se devuelve el atributo sequenceNumber en un objeto java.lang.Long tal como espera el cargador, que implica que la misma persona que escribió el cargador, también escribió la implementación de EmployeeOptimisticCallbackImpl, o bien trabajó estrechamente con la persona que implementó el método EmployeeOptimisticCallbackImpl, por ejemplo, acordó el valor devuelto por el método getVersionedObjectForValue. El plug-in predeterminado OptimisticCallback devuelve el valor especial NULL_OPTIMISTIC_VERSION como el objeto de versión.

Método updateVersionedObjectForValue

Este método se llama siempre que una transacción ha actualizado un valor y se necesita un nuevo objeto de versión. Si el método getVersionedObjectForValue devuelve un atributo del valor, este método suele actualizar el valor de atributo con un nuevo objeto de versión. Si el método getVersionedObjectForValue devuelve una copia del valor, este método normalmente no completa ninguna acción. El plug-in predeterminado OptimisticCallback no completa ninguna acción con este método porque la implementación predeterminada de getVersionedObjectForValue siempre devuelve el valor especial NULL_OPTIMISTIC_VERSION como el objeto de la versión. El siguiente ejemplo muestra la implementación utilizada por el objeto EmployeeOptimisticCallbackImpl que se utiliza en la sección OptimisticCallback:
public void updateVersionedObjectForValue(Object value)
{
    if ( value != null )
    {
        Employee emp = (Employee) value;
        long next = emp.getSequenceNumber() + 1;
        emp.updateSequenceNumber( next );
    }
}

Tal como se demuestra en el ejemplo anterior, el atributo sequenceNumber se incrementa por uno, de forma que la próxima vez que se llama al método getVersionedObjectForValue, el valor java.lang.Long devuelto tiene un valor largo que es el valor del número de secuencia original más uno, por ejemplo, es el valor de la siguiente versión para esta instancia de empleado. Este ejemplo implica que la misma persona que escribió el cargador escribió EmployeeOptimisticCallbackImpl o bien trabajó estrechamente con la persona que implementó EmployeeOptimisticCallbackImpl.

Método serializeVersionedValue

Este método escribe el valor con versión en la corriente especificada. En función de la implementación, el valor con versión puede utilizarse para identificar colisiones de actualización optimista. En algunas implementaciones, el valor con versión es una copia del valor original. Otras implementaciones podrían tener un número de secuencia o algún otro objeto para indicar la versión del valor. Puesto que la implementación real se desconoce, este método se proporciona para realizar la serialización apropiada. La implementación predeterminada llama al método writeObject.

Método inflateVersionedValue

Este método toma la versión serializada del valor con versión y devuelve el objeto de valor con versión real. En función de la implementación, el valor con versión puede utilizarse para identificar colisiones de actualización optimista. En algunas implementaciones, el valor con versión es una copia del valor original. Otras implementaciones podrían tener un número de secuencia o algún otro objeto para indicar la versión del valor. Puesto que se desconoce la implementación real, este método se proporciona para realizar la deserialización apropiada. La implementación predeterminada llama al método readObject.

Uso del objeto OptimisticCallback proporcionado por la aplicación

Dispone de dos enfoques para añadir un objeto OptimisticCallback proporcionado por la aplicación en la configuración de BackingMap: configuración de XML y configuración mediante programa.

Conectar mediante programación un objeto OptimisticCallback

El siguiente ejemplo demuestra cómo una aplicación puede conectar mediante programación un objeto OptimisticCallback para la correlación de respaldo del empleado en la instancia local del ObjectGrid grid1.
import com.ibm.websphere.objectgrid.ObjectGridManagerFactory;
import com.ibm.websphere.objectgrid.ObjectGridManager;
import com.ibm.websphere.objectgrid.ObjectGrid;
import com.ibm.websphere.objectgrid.BackingMap;
ObjectGridManager ogManager = ObjectGridManagerFactory.getObjectGridManager();
ObjectGrid og = ogManager.createObjectGrid( "grid1" );
BackingMap bm = dg.defineMap("employees");
EmployeeOptimisticCallbackImpl cb = new EmployeeOptimisticCallbackImpl();
bm.setOptimisticCallback( cb );

Enfoque de configuración de XML para conectar un objeto OptimisticCallback

La aplicación puede utilizar un archivo XML para conectar su objeto OptimisticCallback tal como se muestra en el siguiente ejemplo:
<?xml version="1.0" encoding="UTF-8"?>
<objectGridConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://ibm.com/ws/objectgrid/config ../objectGrid.xsd"
 xmlns="http://ibm.com/ws/objectgrid/config">
<objectGrids>
    <objectGrid name="grid1">
        <backingMap name="employees" pluginCollectionRef="employees" lockStrategy="OPTIMISTIC" />
    </objectGrid>
</objectGrids>

<backingMapPluginCollections>
    <backingMapPluginCollection id="employees">
        <bean id="OptimisticCallback" className="com.xyz.EmployeeOptimisticCallbackImpl" />
    </backingMapPluginCollection>
</backingMapPluginCollections>
</objectGridConfig>