void CassandraStorage::commitTransaction(const Bucket& bucket, const CommitCallback& cb, const String& timestamp) { Transaction* trans = getTransaction(bucket); //can remove from mTransactions mTransactions.erase(bucket); // Short cut for empty transactions. Or maybe these should cause exceptions? if(trans->empty()) { ReadSet* rs = NULL; completeCommit(trans, cb, false, rs); return; } mIOService->post( std::tr1::bind(&CassandraStorage::executeCommit, this, bucket, trans, cb, timestamp) ); }
Transaction* IncrementalParser::beginTransaction(const CompilationOptions& Opts) { Transaction* OldCurT = m_Consumer->getTransaction(); Transaction* NewCurT = 0; // If we are in the middle of transaction and we see another begin // transaction - it must be nested transaction. if (OldCurT && OldCurT->getState() <= Transaction::kCommitting) { // If the last nested was empty just reuse it. Transaction* LastNestedT = OldCurT->getLastNestedTransaction(); if (LastNestedT && LastNestedT->empty()) { assert(LastNestedT->getState() == Transaction::kCommitted && "Broken"); NewCurT = LastNestedT; NewCurT->reset(); NewCurT->setCompilationOpts(Opts); } else { NewCurT = new Transaction(Opts); OldCurT->addNestedTransaction(NewCurT); // takes the ownership } m_Consumer->setTransaction(NewCurT); return NewCurT; } if (getLastTransaction() && getLastTransaction()->empty()) { NewCurT = getLastTransaction(); NewCurT->reset(); NewCurT->setCompilationOpts(Opts); } else NewCurT = new Transaction(Opts); m_Consumer->setTransaction(NewCurT); if (!m_FirstTransaction) { m_FirstTransaction = NewCurT; m_LastTransaction = NewCurT; } else if (NewCurT != m_LastTransaction){ m_LastTransaction->setNext(NewCurT); m_LastTransaction = NewCurT; // takes the ownership } return NewCurT; }
void IncrementalParser::commitTransaction(ParseResultTransaction& PRT, bool ClearDiagClient) { Transaction* T = PRT.getPointer(); if (!T) { if (PRT.getInt() != kSuccess) { // Nothing has been emitted to Codegen, reset the Diags. DiagnosticsEngine& Diags = getCI()->getSema().getDiagnostics(); Diags.Reset(/*soft=*/true); if (ClearDiagClient) Diags.getClient()->clear(); } return; } assert(T->isCompleted() && "Transaction not ended!?"); assert(T->getState() != Transaction::kCommitted && "Committing an already committed transaction."); assert((T->getIssuedDiags() == Transaction::kErrors || !T->empty()) && "Valid Transactions must not be empty;"); // If committing a nested transaction the active one should be its parent // from now on. if (T->isNestedTransaction()) m_Consumer->setTransaction(T->getParent()); // Check for errors... if (T->getIssuedDiags() == Transaction::kErrors) { // Make module visible to TransactionUnloader. bool MustStartNewModule = false; if (!T->isNestedTransaction() && hasCodeGenerator()) { MustStartNewModule = true; std::unique_ptr<llvm::Module> M(getCodeGenerator()->ReleaseModule()); if (M) { T->setModule(std::move(M)); } } // Module has been released from Codegen, reset the Diags now. DiagnosticsEngine& Diags = getCI()->getSema().getDiagnostics(); Diags.Reset(/*soft=*/true); if (ClearDiagClient) Diags.getClient()->clear(); PRT.setPointer(nullptr); PRT.setInt(kFailed); m_Interpreter->unload(*T); // Create a new module if necessary. if (MustStartNewModule) StartModule(); return; } if (T->hasNestedTransactions()) { Transaction* TopmostParent = T->getTopmostParent(); EParseResult PR = kSuccess; if (TopmostParent->getIssuedDiags() == Transaction::kErrors) PR = kFailed; else if (TopmostParent->getIssuedDiags() == Transaction::kWarnings) PR = kSuccessWithWarnings; for (Transaction::const_nested_iterator I = T->nested_begin(), E = T->nested_end(); I != E; ++I) if ((*I)->getState() != Transaction::kCommitted) { ParseResultTransaction PRT(*I, PR); commitTransaction(PRT); } } // If there was an error coming from the transformers. if (T->getIssuedDiags() == Transaction::kErrors) { m_Interpreter->unload(*T); return; } // Here we expect a template instantiation. We need to open the transaction // that we are currently work with. { Transaction* prevConsumerT = m_Consumer->getTransaction(); m_Consumer->setTransaction(T); Transaction* nestedT = beginTransaction(T->getCompilationOpts()); // Pull all template instantiations in that came from the consumers. getCI()->getSema().PerformPendingInstantiations(); ParseResultTransaction nestedPRT = endTransaction(nestedT); commitTransaction(nestedPRT); m_Consumer->setTransaction(prevConsumerT); } m_Consumer->HandleTranslationUnit(getCI()->getASTContext()); // The static initializers might run anything and can thus cause more // decls that need to end up in a transaction. But this one is done // with CodeGen... if (T->getCompilationOpts().CodeGeneration && hasCodeGenerator()) { Transaction* prevConsumerT = m_Consumer->getTransaction(); m_Consumer->setTransaction(T); codeGenTransaction(T); T->setState(Transaction::kCommitted); if (!T->getParent()) { if (m_Interpreter->executeTransaction(*T) >= Interpreter::kExeFirstError) { // Roll back on error in initializers. // T maybe pointing to freed memory after this call: // Interpreter::unload // IncrementalParser::deregisterTransaction // TransactionPool::releaseTransaction m_Interpreter->unload(*T); return; } } m_Consumer->setTransaction(prevConsumerT); } T->setState(Transaction::kCommitted); if (InterpreterCallbacks* callbacks = m_Interpreter->getCallbacks()) callbacks->TransactionCommitted(*T); }