Search in sources :

Example 16 with TransactionContext

use of org.teiid.dqp.service.TransactionContext in project teiid by teiid.

the class Request method getTransactionContext.

TransactionContext getTransactionContext(boolean startAutoWrap) throws TeiidComponentException {
    if (this.transactionContext != null) {
        return this.transactionContext;
    }
    TransactionContext tc = transactionService.getOrCreateTransactionContext(workContext.getSessionId());
    if (tc.getTransactionType() == TransactionContext.Scope.REQUEST && this.workContext.isDerived()) {
        // to a sub-request, request scope should appear as global - which means associated and non-suspendable
        tc = tc.clone();
        tc.setTransactionType(TransactionContext.Scope.INHERITED);
    }
    // $NON-NLS-1$
    Assertion.assertTrue(tc.getTransactionType() != TransactionContext.Scope.REQUEST, "Transaction already associated with request.");
    // If local or global transaction is not started.
    if (tc.getTransactionType() == Scope.NONE && !requestMsg.isNoExec()) {
        if (!startAutoWrap) {
            return null;
        }
        Boolean startAutoWrapTxn = false;
        if (RequestMessage.TXN_WRAP_ON.equals(requestMsg.getTxnAutoWrapMode())) {
            startAutoWrapTxn = true;
        } else if (RequestMessage.TXN_WRAP_DETECT.equals(requestMsg.getTxnAutoWrapMode())) {
            boolean transactionalRead = requestMsg.getTransactionIsolation() == Connection.TRANSACTION_REPEATABLE_READ || requestMsg.getTransactionIsolation() == Connection.TRANSACTION_SERIALIZABLE;
            startAutoWrapTxn = processPlan.requiresTransaction(transactionalRead);
            if (startAutoWrapTxn == null) {
                startAutoWrapTxn = false;
            }
        }
        if (startAutoWrapTxn) {
            try {
                transactionService.begin(tc);
            } catch (XATransactionException err) {
                throw new TeiidComponentException(QueryPlugin.Event.TEIID30493, err);
            }
        }
    }
    tc.setIsolationLevel(requestMsg.getTransactionIsolation());
    this.transactionContext = tc;
    return this.transactionContext;
}
Also used : TransactionContext(org.teiid.dqp.service.TransactionContext) TeiidComponentException(org.teiid.core.TeiidComponentException) XATransactionException(org.teiid.client.xa.XATransactionException)

Example 17 with TransactionContext

use of org.teiid.dqp.service.TransactionContext in project teiid by teiid.

the class RequestWorkItem method processNew.

protected void processNew() throws TeiidProcessingException, TeiidComponentException {
    planningStart = System.currentTimeMillis();
    SessionAwareCache<CachedResults> rsCache = dqpCore.getRsCache();
    boolean cachable = false;
    CacheID cacheId = null;
    if (rsCache != null) {
        boolean canUseCache = true;
        if (requestMsg.getRequestOptions().isContinuous()) {
            canUseCache = false;
            // $NON-NLS-1$
            LogManager.logDetail(LogConstants.CTX_DQP, requestID, "Command is continuous, result set caching will not be used");
        } else if (!requestMsg.useResultSetCache() && getCacheHint() == null) {
            canUseCache = false;
            // $NON-NLS-1$
            LogManager.logDetail(LogConstants.CTX_DQP, requestID, "Command has no cache hint and result set cache mode is not on.");
        }
        if (canUseCache) {
            ParseInfo pi = Request.createParseInfo(requestMsg, this.dqpWorkContext.getSession());
            cacheId = new CacheID(this.dqpWorkContext, pi, requestMsg.getCommandString());
            cachable = cacheId.setParameters(requestMsg.getParameterValues());
            if (cachable) {
                // allow cache to be transactionally aware
                if (rsCache.isTransactional()) {
                    TransactionContext tc = request.getTransactionContext(false);
                    if (tc != null && tc.getTransactionType() != Scope.NONE) {
                        initTransactionState(tc);
                        resume();
                    }
                }
                CachedResults cr = rsCache.get(cacheId);
                // TODO: possibly ignore max rows for caching
                if (cr != null && (cr.getRowLimit() == 0 || (requestMsg.getRowLimit() != 0 && requestMsg.getRowLimit() <= cr.getRowLimit()))) {
                    request.initMetadata();
                    this.originalCommand = cr.getCommand(requestMsg.getCommandString(), request.metadata, pi);
                    if (!request.validateAccess(requestMsg.getCommands(), this.originalCommand, CommandType.CACHED)) {
                        // $NON-NLS-1$
                        LogManager.logDetail(LogConstants.CTX_DQP, requestID, "Using result set cached results", cacheId);
                        this.resultsBuffer = cr.getResults();
                        doneProducingBatches();
                        return;
                    }
                    // $NON-NLS-1$
                    LogManager.logDetail(LogConstants.CTX_DQP, requestID, "Cached result command to be modified, will not use the cached results", cacheId);
                }
            } else {
                // $NON-NLS-1$
                LogManager.logDetail(LogConstants.CTX_DQP, requestID, "Parameters are not serializable - cache cannot be used for", cacheId);
            }
        }
    } else {
        // $NON-NLS-1$
        LogManager.logDetail(LogConstants.CTX_DQP, requestID, "Result set caching is disabled.");
    }
    try {
        request.processRequest();
    } finally {
        analysisRecord = request.analysisRecord;
    }
    originalCommand = request.userCommand;
    if (cachable && (requestMsg.useResultSetCache() || originalCommand.getCacheHint() != null) && rsCache != null && originalCommand.areResultsCachable()) {
        this.cid = cacheId;
        // turn on the collection of data objects used
        request.processor.getContext().setDataObjects(new HashSet<Object>(4));
    }
    request.processor.getContext().setWorkItem(this);
    processor = request.processor;
    planningEnd = System.currentTimeMillis();
    this.dqpCore.logMMCommand(this, Event.PLAN, null, null);
    collector = new BatchCollector(processor, processor.getBufferManager(), this.request.context, isForwardOnly()) {

        int maxRows = 0;

        @Override
        protected void flushBatchDirect(TupleBatch batch, boolean add) throws TeiidComponentException, TeiidProcessingException {
            resultsBuffer = getTupleBuffer();
            if (maxRows == 0) {
                maxRows = OUTPUT_BUFFER_MAX_BATCHES * resultsBuffer.getBatchSize();
            }
            if (cid != null) {
                super.flushBatchDirect(batch, add);
            }
            synchronized (lobStreams) {
                if (cid == null && resultsBuffer.isLobs()) {
                    super.flushBatchDirect(batch, false);
                }
                if (batch.getTerminationFlag()) {
                    done();
                }
                add = sendResultsIfNeeded(batch);
                if (cid != null) {
                    return;
                }
                super.flushBatchDirect(batch, add);
                if (!add && !processor.hasBuffer()) {
                    resultsBuffer.setRowCount(batch.getEndRow());
                }
                if (transactionState != TransactionState.ACTIVE && (requestMsg.getRequestOptions().isContinuous() || (useCallingThread && isForwardOnly()))) {
                    synchronized (this) {
                        if (resultsReceiver == null) {
                            // $NON-NLS-1$
                            throw BlockedException.block(requestID, "Blocking to allow asynch processing");
                        }
                    }
                    if (add && !returnsUpdateCount) {
                        // $NON-NLS-1$
                        throw new AssertionError("Should not add batch to buffer");
                    }
                }
                if (add) {
                    flowControl(batch);
                }
            }
        }

        private void flowControl(TupleBatch batch) throws BlockedException {
            if (processor.hasBuffer() || batch.getTerminationFlag() || transactionState == TransactionState.ACTIVE) {
                return;
            }
            synchronized (this) {
                if (!isForwardOnly() && resultsReceiver != null && begin > resultsBuffer.getRowCount()) {
                    // a valid request beyond the processed range
                    return;
                }
            }
            if (resultsBuffer.getManagedRowCount() < maxRows) {
                // continue to buffer
                return;
            }
            int timeOut = 500;
            if (!connectorInfo.isEmpty()) {
                if (explicitSourceClose) {
                    for (DataTierTupleSource ts : getConnectorRequests()) {
                        if (!ts.isExplicitClose()) {
                            timeOut = 100;
                            break;
                        }
                    }
                } else {
                    timeOut = 100;
                }
            }
            if (dqpCore.blockOnOutputBuffer(RequestWorkItem.this)) {
                if (moreWorkTask != null) {
                    moreWorkTask.cancel(false);
                    moreWorkTask = null;
                }
                if (getThreadState() != ThreadState.MORE_WORK) {
                    // we schedule the work to ensure that an idle client won't just indefinitely hold resources
                    moreWorkTask = scheduleWork(timeOut);
                }
                throw // $NON-NLS-1$
                BlockedException.block(// $NON-NLS-1$
                requestID, // $NON-NLS-1$
                "Blocking due to full results TupleBuffer", this.getTupleBuffer(), "rows", this.getTupleBuffer().getManagedRowCount(), "batch size", // $NON-NLS-1$ //$NON-NLS-2$
                this.getTupleBuffer().getBatchSize());
            }
            if (LogManager.isMessageToBeRecorded(LogConstants.CTX_DQP, MessageLevel.DETAIL)) {
                // $NON-NLS-1$
                LogManager.logDetail(LogConstants.CTX_DQP, requestID, "Exceeding buffer limit since there are pending active plans or this is using the calling thread.");
            }
        }
    };
    if (!request.addedLimit && this.requestMsg.getRowLimit() > 0 && this.requestMsg.getRowLimit() < Integer.MAX_VALUE) {
        // covers maxrows for commands that already have a limit, are prepared, or are a stored procedure
        this.collector.setRowLimit(this.requestMsg.getRowLimit());
        this.collector.setSaveLastRow(request.isReturingParams());
    }
    this.resultsBuffer = collector.getTupleBuffer();
    if (this.resultsBuffer == null) {
        // This is just a dummy result it will get replaced by collector source
        resultsBuffer = this.processor.getBufferManager().createTupleBuffer(this.originalCommand.getProjectedSymbols(), this.request.context.getConnectionId(), TupleSourceType.FINAL);
    } else if (this.requestMsg.getRequestOptions().isContinuous()) {
        // TODO: this is based upon continuous being an embedded connection otherwise we have to do something like
        // forcing inlining, but truncating or erroring over a given size (similar to odbc handling)
        resultsBuffer.removeLobTracking();
    }
    initTransactionState(request.transactionContext);
    if (requestMsg.isNoExec()) {
        doneProducingBatches();
        resultsBuffer.close();
        this.cid = null;
    }
    this.returnsUpdateCount = request.returnsUpdateCount;
    if (this.returnsUpdateCount && this.requestMsg.getRequestOptions().isContinuous()) {
        // $NON-NLS-1$
        throw new IllegalStateException("Continuous requests are not allowed to be updates.");
    }
    request = null;
}
Also used : ParseInfo(org.teiid.query.parser.ParseInfo) BlockedException(org.teiid.common.buffer.BlockedException) CacheHint(org.teiid.query.sql.lang.CacheHint) TeiidProcessingException(org.teiid.core.TeiidProcessingException) CacheID(org.teiid.dqp.internal.process.SessionAwareCache.CacheID) TransactionContext(org.teiid.dqp.service.TransactionContext) TeiidComponentException(org.teiid.core.TeiidComponentException) BatchCollector(org.teiid.query.processor.BatchCollector) TupleBatch(org.teiid.common.buffer.TupleBatch)

Example 18 with TransactionContext

use of org.teiid.dqp.service.TransactionContext in project teiid by teiid.

the class TransactionServerImpl method getTransactions.

@Override
public Collection<TransactionMetadata> getTransactions() {
    Set<TransactionContext> txnSet = Collections.newSetFromMap(new IdentityHashMap<TransactionContext, Boolean>());
    synchronized (this.transactions) {
        txnSet.addAll(this.transactions.threadToTransactionContext.values());
        txnSet.addAll(this.transactions.xidToTransactionContext.values());
    }
    Collection<TransactionMetadata> result = new ArrayList<TransactionMetadata>(txnSet.size());
    for (TransactionContext transactionContext : txnSet) {
        if (transactionContext.getTransactionType() == Scope.NONE) {
            continue;
        }
        TransactionMetadata txnImpl = new TransactionMetadata();
        txnImpl.setAssociatedSession(transactionContext.getThreadId());
        txnImpl.setCreatedTime(transactionContext.getCreationTime());
        txnImpl.setScope(transactionContext.getTransactionType().toString());
        txnImpl.setId(transactionContext.getTransactionId());
        result.add(txnImpl);
    }
    return result;
}
Also used : TransactionContext(org.teiid.dqp.service.TransactionContext) ArrayList(java.util.ArrayList) TransactionMetadata(org.teiid.adminapi.impl.TransactionMetadata)

Example 19 with TransactionContext

use of org.teiid.dqp.service.TransactionContext in project teiid by teiid.

the class TransactionServerImpl method rollback.

/**
 * Local Transaction
 */
public void rollback(String threadId) throws XATransactionException {
    TransactionContext tc = checkLocalTransactionState(threadId, true);
    rollbackDirect(tc);
}
Also used : TransactionContext(org.teiid.dqp.service.TransactionContext)

Example 20 with TransactionContext

use of org.teiid.dqp.service.TransactionContext in project teiid by teiid.

the class TransactionServerImpl method getOrCreateTransactionContext.

public TransactionContext getOrCreateTransactionContext(final String threadId) {
    TransactionContext tc = transactions.getOrCreateTransactionContext(threadId);
    if (detectTransactions) {
        try {
            Transaction tx = transactionManager.getTransaction();
            if (tx != null && tx != tc.getTransaction()) {
                tx.registerSynchronization(new Synchronization() {

                    @Override
                    public void beforeCompletion() {
                    }

                    @Override
                    public void afterCompletion(int status) {
                        transactions.removeTransactionContext(threadId);
                    }
                });
                tc.setTransaction(tx);
                tc.setTransactionType(Scope.INHERITED);
            }
        // TODO: it may be appropriate to throw an up-front exception
        } catch (SystemException e) {
        } catch (IllegalStateException e) {
        } catch (RollbackException e) {
        }
    }
    return tc;
}
Also used : Transaction(javax.transaction.Transaction) SystemException(javax.transaction.SystemException) TransactionContext(org.teiid.dqp.service.TransactionContext) Synchronization(javax.transaction.Synchronization) RollbackException(javax.transaction.RollbackException) HeuristicRollbackException(javax.transaction.HeuristicRollbackException)

Aggregations

TransactionContext (org.teiid.dqp.service.TransactionContext)34 Test (org.junit.Test)15 CommandContext (org.teiid.query.util.CommandContext)7 TransactionService (org.teiid.dqp.service.TransactionService)6 XATransactionException (org.teiid.client.xa.XATransactionException)5 TeiidProcessingException (org.teiid.core.TeiidProcessingException)5 VariableContext (org.teiid.query.sql.util.VariableContext)5 List (java.util.List)4 SystemException (javax.transaction.SystemException)4 Transaction (javax.transaction.Transaction)4 TeiidComponentException (org.teiid.core.TeiidComponentException)4 TupleBatch (org.teiid.common.buffer.TupleBatch)3 AtomicRequestMessage (org.teiid.dqp.message.AtomicRequestMessage)3 QueryMetadataInterface (org.teiid.query.metadata.QueryMetadataInterface)3 TransformationMetadata (org.teiid.query.metadata.TransformationMetadata)3 BatchedUpdateCommand (org.teiid.query.sql.lang.BatchedUpdateCommand)3 Command (org.teiid.query.sql.lang.Command)3 ArrayList (java.util.ArrayList)2 RollbackException (javax.transaction.RollbackException)2 Synchronization (javax.transaction.Synchronization)2