Introducción a las ranuras de plug-in

Una ranura de plug-in es un espacio de almacenamiento transaccional que se reserva para los plug-ins que comparten un contexto transaccional. Estas ranuras proporcionan una forma para que los plug-ins de eXtreme Scale se comuniquen entre sí, compartan el contexto transaccional y garanticen que los recursos transaccionales se utilizan de forma correcta y coherente dentro de una transacción.

Un plug-in puede almacenar el contexto transaccional como, por ejemplo, una conexión de base de datos, una conexión JMS (Java Message Service), etc. en una ranura de plug-in. El contexto transaccional almacenado puede recuperarse mediante cualquier plug-in que conozca el número de ranura de plug-in, que sirve como clave para recuperar el contexto transaccional.

Uso de ranuras de plug-in

Las ranuras de plug-in forman parte de la interfaz TxID. Consulte la documentación de la API si desea más información sobre la interfaz. Las ranuras son entradas en una matriz ArrayList. Los plug-ins pueden reservar una entrada en la matriz ArrayList llamando al método ObjectGrid.reserveSlot e indicando que desea una ranura en todos los objetos TxID. Después de reservar las ranuras, los plug-ins pueden colocar contexto transaccional en las ranuras de cada objeto TxID y recuperar el contexto más adelante. Las operaciones put y get se coordinan a través de números de ranura devueltos por el método ObjectGrid.reserveSlot.

Normalmente, un plug-in tiene un ciclo de vida. El uso de ranuras de plug-in debe ajustarse al ciclo de vida del plug-in. Por lo general, el plug-in debe reservar las ranuras de plug-in durante la fase de inicialización y obtener los números de ranura para cada ranura. Durante la ejecución normal, el plug-in coloca el contexto transaccional en la ranura reservada en el objeto TxID en el punto apropiado. Este punto apropiado suele estar el principio de la transacción. A continuación, el plug-in u otros plug-ins pueden obtener el contexto transaccional almacenado mediante el número de ranura desde TxID dentro de la transacción.

Normalmente, el plug-in realiza una limpieza eliminando el contexto transaccional y las ranuras. El siguiente fragmento de código ilustra cómo utilizar las ranuras de plug-in en un plug-in TransactionCallback:

public class DatabaseTransactionCallback implements TransactionCallback {
    int connectionSlot;
    int autoCommitConnectionSlot;
    int psCacheSlot;
    Properties ivProperties = new Properties();

    public void initialize(ObjectGrid objectGrid) throws TransactionCallbackException {
        // En la fase de inicialización, reservar las ranuras de plug-in deseadas llamando al
        //método reserveSlot de ObjectGrid y
        // pasar el nombre de ranura designado, TxID.SLOT_NAME.
        // Nota: debe pasarlo en este TxID.SLOT_NAME diseñado para
        // la aplicación.
        try {
            // almacenar en memoria caché los números de ranura devueltos
            connectionSlot = objectGrid.reserveSlot(TxID.SLOT_NAME);
            psCacheSlot = objectGrid.reserveSlot(TxID.SLOT_NAME);
            autoCommitConnectionSlot = objectGrid.reserveSlot(TxID.SLOT_NAME);
        }catch (Exception e) {
        }
    }

    public void begin(TxID tx) throws TransactionCallbackException {
        // colocar contextos transaccionales en las ranuras reservadas al
        // principio de la transacción.
        try {
            Connection conn = null;
            conn = DriverManager.getConnection(ivDriverUrl, ivProperties);
            tx.putSlot(connectionSlot, conn);
            conn = DriverManager.getConnection(ivDriverUrl, ivProperties);
            conn.setAutoCommit(true);
            tx.putSlot(autoCommitConnectionSlot, conn);
            tx.putSlot(psCacheSlot, new HashMap());
        } catch (SQLException e) {
            SQLException ex = getLastSQLException(e);
            throw new TransactionCallbackException("unable to get connection", ex);
        }
    }

    public void commit(TxID id) throws TransactionCallbackException {
        // obtener los contextos transaccionales almacenados y utilizarlos
        // después, limpiar todos los recursos transaccionales.
        try {
            Connection conn = (Connection) id.getSlot(connectionSlot);
            conn.commit();
            cleanUpSlots(id);
        } catch (SQLException e) {
            SQLException ex = getLastSQLException(e);
            throw new TransactionCallbackException("commit failure", ex);
        }
    }

    void cleanUpSlots(TxID tx) throws TransactionCallbackException {
        closePreparedStatements((Map) tx.getSlot(psCacheSlot));
        closeConnection((Connection) tx.getSlot(connectionSlot));
        closeConnection((Connection) tx.getSlot(autoCommitConnectionSlot));
    }

    /**
     * @param map
     */
    private void closePreparedStatements(Map psCache) {
        try {
            Collection statements = psCache.values();
            Iterator iter = statements.iterator();
            while (iter.hasNext()) {
                PreparedStatement stmt = (PreparedStatement) iter.next();
                stmt.close();
            }
        } catch (Throwable e) {
        }

    }

    /**
     * Cerrar conexión y aceptar cualquier objeto Throwable que se produzca.
     *
     * @param connection
     */
    private void closeConnection(Connection connection) {
        try {
            connection.close();
        } catch (Throwable e1) {
        }
    }

    public void rollback(TxID id) throws TransactionCallbackException
        // obtener los contextos transaccionales almacenados y utilizarlos
        // después, limpiar todos los recursos transaccionales.
        try {
            Connection conn = (Connection) id.getSlot(connectionSlot);
            conn.rollback();
            cleanUpSlots(id);
        } catch (SQLException e) {
        }
    }

    public boolean isExternalTransactionActive(Session session) {
        return false;
    }

    // Métodos getter para los números de ranura, otro plug-in puede obtener los números de ranura
    // de estos métodos getter.

    public int getConnectionSlot() {
        return connectionSlot;
    }
    public int getAutoCommitConnectionSlot() {
        return autoCommitConnectionSlot;
    }
    public int getPreparedStatementSlot() {
        return psCacheSlot;
    }

El siguiente fragmento de código ilustra cómo un cargador puede obtener el contexto transaccional almacenado colocado por un plug-in de ejemplo TransactionCallback anterior:

public class DatabaseLoader implements Loader
{
    DatabaseTransactionCallback tcb;
    public void preloadMap(Session session, BackingMap backingMap) throws LoaderException
    {
        // El método preload es el método de inicialización de Loader.
        // Obtener el plug-in deseado de la instancia de Session u ObjectGrid.
        tcb = 
			(DatabaseTransactionCallback)session.getObjectGrid().getTransactionCallback();
    }
    public List get(TxID txid, List keyList, boolean forUpdate) throws LoaderException
    {
        // obtener los contextos transaccionales almacenados que coloca el  método begin de tcb.
        Connection conn = (Connection)txid.getSlot(tcb.getConnectionSlot());
        // implementar get aquí
        return null;
    }
    public void batchUpdate(TxID txid, LogSequence sequence) throws LoaderException, 
			OptimisticCollisionException
    {
        // obtener los contextos transaccionales almacenados que coloca el  método begin de tcb.
        Connection conn = (Connection)txid.getSlot(tcb.getConnectionSlot());
        // implementar actualización de proceso por lotes aquí...
    }
}