Emplacements de plug-in - Présentation

Un emplacement de plug-in est un espace de stockage de transactions qui est réservé aux plug-in partageant un contexte transactionnel. Ces emplacements permettent aux plug-in eXtreme Scale de communiquer entre eux, de partager un contexte transactionnel et de s'assurer que les ressources transactionnelles sont correctement utilisées de manière cohérente au sein de la transaction.

Dans un emplacement, un plug-in peut stocker un contexte transactionnel (connexion à la base de données, connexion Java Message Service (JMS), etc.). Le contexte transactionnel qui est stocké peut être extrait par tout plug-in qui connaît le numéro de l'emplacement, lequel sert de clé pour l'extraction du contexte transactionnel.

Utiliser des emplacements de plug-in

Les emplacements de plug-in font partie de l'interface TxID. Voir la documentation de l'API pour plus d'informations sur cette interface.Les emplacements sont des entrées d'un tableau ArrayList. Les plug-in peuvent réserver une entrée dans ce tableau en appelant la méthode ObjectGrid.reserveSlot et en indiquant qu'ils souhaitent un emplacement sur tous les objets TxID. Une fois la réservation effectuée, les plug-in peuvent placer du contexte transactionnel dans les emplacements de chacun des objets TxID pour pouvoir extraire ultérieurement ce contexte. Les opérations put et get sont coordonnées par les numéros d'emplacements qui sont retournés par la méthode ObjectGrid.reserveSlot.

Un plug-in a normalement un cycle de vie. L'utilisation d'emplacements de plug-in doit donc se faire en tenant compte de ce cycle de vie. En principe, le plug-in doit réserver des emplacements pendant la phase d'initialisation et obtenir un numéro pour chacun des emplacements. Pendant l'exécution normale, le plug-in place au moment approprié du contexte transactionnel dans l'emplacement réservé sur l'objet TxID. Ce moment approprié se situe en général au début de la transaction. Au sein de la transaction, le plug-in (ou d'autres plug-in) peut alors récupérer dans le TxID, à partir du numéro de l'emplacement, le contexte transactionnel qui a été stocké de la sorte.

Normalement, le plug-in procède à un nettoyage en supprimant le contexte transactionnel et les emplacements. Le fragment suivant de code montre comment utiliser des emplacements dans 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 {
        // In initialization stage, reserve desired plug-in slots by calling the 
        //reserveSlot method of ObjectGrid and
        // passing in the designated slot name, TxID.SLOT_NAME.
        // Note: you have to pass in this TxID.SLOT_NAME that is designated 
        // for application.
        try {
            // cache the returned slot numbers
            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 {
        // put transactional contexts into the reserved slots at the 
        // beginning of the transaction.
        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 {
        // get the stored transactional contexts and use them
        // then, clean up all transactional resources.
        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) {
        }

    }

    /**
     * Close connection and swallow any Throwable that occurs.
     *
     * @param connection
     */
    private void closeConnection(Connection connection) {
        try {
            connection.close();
        } catch (Throwable e1) {
        }
    }

    public void rollback(TxID id) throws TransactionCallbackException
        // get the stored transactional contexts and use them
        // then, clean up all transactional resources.
        try {
            Connection conn = (Connection) id.getSlot(connectionSlot);
            conn.rollback();
            cleanUpSlots(id);
        } catch (SQLException e) {
        }
    }

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

    // Getter methods for the slot numbers, other plug-in can obtain the slot numbers 
    // from these getter methods.

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

Le fragment suivant de code montre comment le chargeur peut récupérer le contexte transactionnel qui a été stocké par l'exemple précédent de plug-in TransactionCallback :

public class DatabaseLoader implements Loader
{
    DatabaseTransactionCallback tcb;
    public void preloadMap(Session session, BackingMap backingMap) throws LoaderException
    {
        // The preload method is the initialization method of the Loader.
        // Obtain interested plug-in from Session or ObjectGrid instance.
        tcb = 
			(DatabaseTransactionCallback)session.getObjectGrid().getTransactionCallback();
    }
    public List get(TxID txid, List keyList, boolean forUpdate) throws LoaderException
    {
        // get the stored transactional contexts that is put by tcb's begin method.
        Connection conn = (Connection)txid.getSlot(tcb.getConnectionSlot());
        // implement get here
        return null;
    }
    public void batchUpdate(TxID txid, LogSequence sequence) throws LoaderException, 
			OptimisticCollisionException
    {
        // get the stored transactional contexts that is put by tcb's begin method.
        Connection conn = (Connection)txid.getSlot(tcb.getConnectionSlot());
        // implement batch update here ...
    }
}