Einführung in Plug-in-Slots

Ein Plug-in-Slot ist ein transaktionsorientierter Speicherbereich, der für Plug-ins reserviert ist, die einen Transaktionskontext gemeinsam nutzen. Diese Slots bieten eXtreme-Scale-Plug-ins die Möglichkeit, miteinander zu kommunizieren, einen Transaktionskontext gemeinsam zu nutzen und sicherzustellen, dass Transaktionsressourcen innerhalb einer Transaktion korrekt und konsistent verwendet werden.

Ein Plug-in kann einen Transaktionskontext, z. B. eine Datenbankverbindung, eine JMS-Verbindung (Java Message Service) usw., in einem Plug-in-Slot speichern. Der gespeicherte Transaktionskontext kann von jedem Plug-in abgerufen werden, das die Nummer des Plug-in-Slots kennt, die als Schlüssel für den Abruf des Transaktionskontexts dient.

Plug-in-Slots verwenden

Plug-in-Slots gehören zur Schnittstelle "TxID". Weitere Informationen zu dieser Schnittstelle finden Sie in der API-Dokumentation. Diese Slots sind Einträge in einer ArrayList-Feldgruppe. Plug-ins können einen Eintrag in der ArrayList-Feldgruppe reservieren, indem Sie die Methode "ObjectGrid.reserveSlot" aufrufen und anzeigen, dass sie einen Slot in allen TxID-Objekten verwenden möchten. Nachdem die Slots reserviert wurden, können Plug-ins einen Transaktionskontext in den Slots jedes TxID-Objekts speichern und den Kontext später abrufen. Die Operationen "put" und "get" werden über die Slot-Nummern koordiniert, die von der Methode "ObjectGrid.reserveSlot" zurückgegeben werden.

Ein Plug-in hat gewöhnlich einen Lebenszyklus. Die Verwendung von Plug-in-Slots muss in den Lebenszyklus des Plug-ins passen. Gewöhnlich muss das Plug-in Plug-in-Slots in der Initialisierungsphase reservieren und eine Slot-Nummer für jeden Slot anfordern. Zur normalen Laufzeit speichert das Plug-in zum entsprechenden Zeitpunkt einen Transaktionskontext im reservierten Slot im TxID-Objekt. Normalerweise geschieht dies am Anfang der Transaktion. Das Plug-in oder andere Plug-ins können dann den gespeicherten Transaktionskontext über die Slot-Nummer aus dem TxID-Objekt innerhalb der Transaktion abrufen.

Das Plug-in führt gewöhnlich eine Bereinigung durch, indem es den Transaktionskontext und die Slots entfernt. Das folgende Code-Snippet veranschaulicht, wie Plug-in-Slots in einem TransactionCallback-Plug-in verwendet werden:

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

    public void initialize(ObjectGrid objectGrid) throws TransactionCallbackException {
        // In der Initialisierungsphase die gewünschten Plug-in-Slots durch Aufruf
        // der Methode reserveSlot von ObjectGrid reservieren und den
        // gewünschten Slot-Namen mit TxID.SLOT_NAME übergeben.
        // Anmerkung: Sie müssen mit TxID.SLOT_NAME den Slot-Namen übergeben,
        // der für die Anwendung bestimmt ist.
        try {
            // Zurückgegebene Slot-Nummern zwischenspeichern.
            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 {
        // Am Anfang der Transaktion Transaktionskontexte in den reservierten
        // Slots speichern.
        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 {
        // Gespeicherte Transaktionskontexte abrufen, verwenden und anschließend
        // alle Transaktionsressourcen bereinigen.
        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) {
        }

    }

    /**
     * Verbindung schließen und alle Throwable-Objekte abfangen.
     *
     * @param connection
     */
    private void closeConnection(Connection connection) {
        try {
            connection.close();
        } catch (Throwable e1) {
        }
    }

    public void rollback(TxID id) throws TransactionCallbackException
        // Gespeicherte Transaktionskontexte abrufen, verwenden und anschließend
        // alle Transaktionsressourcen bereinigen.
        try {
            Connection conn = (Connection) id.getSlot(connectionSlot);
            conn.rollback();
            cleanUpSlots(id);
        } catch (SQLException e) {
        }
    }

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

    // Getter-Methoden für die Slot-Nummern. Andere Plug-ins können die Slot-Nummern
    // über diese Getter-Methoden anfordern.

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

Das folgende Code-Snippet veranschaulicht, wie ein Loader (Ladeprogramm) den gespeicherten Transaktionskontext abrufen kann, der mit dem vorherigen TransactionCallback-Plug-in-Beispielcode gespeichert wurde:

public class DatabaseLoader implements Loader
{
    DatabaseTransactionCallback tcb;
    public void preloadMap(Session session, BackingMap backingMap) throws LoaderException
    {
        // Die Methode "preload" ist die Initialisierungsmethode des Loaders.
        // Gewünschtes Plug-in von der Session- bzw. ObjectGrid-Instanz anfordern.
        tcb = 
			(DatabaseTransactionCallback)session.getObjectGrid().getTransactionCallback();
    }
    public List get(TxID txid, List keyList, boolean forUpdate) throws LoaderException
    {
                // Gespeicherte Transaktionskontexte abrufen, die mit der TCB-Methode "begin" gespeichert wurden.
        Connection conn = (Connection)txid.getSlot(tcb.getConnectionSlot());
        // Abruf hier implementieren.
        	        return null;
    }
    public void batchUpdate(TxID txid, LogSequence sequence) throws LoaderException, 
			OptimisticCollisionException
    {
        // Gespeicherte Transaktionskontexte abrufen, die mit der TCB-Methode "begin" gespeichert wurden.
        Connection conn = (Connection)txid.getSlot(tcb.getConnectionSlot());
        // Aktualisierung im Stapelbetrieb hier implementieren.
    }
}