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;
}
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;
}
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;
}
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);
}
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;
}
Aggregations