summaryrefslogtreecommitdiff
path: root/cpp
diff options
context:
space:
mode:
authorBernard Normier <bernard@zeroc.com>2007-07-06 15:14:06 -0400
committerBernard Normier <bernard@zeroc.com>2007-07-06 15:14:06 -0400
commit3a5a3740e06b15d27badc3a000e174f01403bc60 (patch)
tree8ea1e9abebfd82e996b6b90cfcf635ff74c00bb9 /cpp
parentAMD testing + AMD "rollback on user exception" fix (diff)
downloadice-3a5a3740e06b15d27badc3a000e174f01403bc60.tar.bz2
ice-3a5a3740e06b15d27badc3a000e174f01403bc60.tar.xz
ice-3a5a3740e06b15d27badc3a000e174f01403bc60.zip
AMD testing + minimal rollback on user exception support in AMD
Diffstat (limited to 'cpp')
-rw-r--r--cpp/src/Freeze/TransactionalEvictorContext.cpp14
-rw-r--r--cpp/src/Freeze/TransactionalEvictorContext.h8
-rw-r--r--cpp/src/Freeze/TransactionalEvictorI.cpp5
-rw-r--r--cpp/test/Freeze/evictor/Client.cpp41
-rw-r--r--cpp/test/Freeze/evictor/Test.ice8
-rw-r--r--cpp/test/Freeze/evictor/TestI.cpp119
-rw-r--r--cpp/test/Freeze/evictor/TestI.h4
7 files changed, 191 insertions, 8 deletions
diff --git a/cpp/src/Freeze/TransactionalEvictorContext.cpp b/cpp/src/Freeze/TransactionalEvictorContext.cpp
index 395203ed805..ac9466d017e 100644
--- a/cpp/src/Freeze/TransactionalEvictorContext.cpp
+++ b/cpp/src/Freeze/TransactionalEvictorContext.cpp
@@ -119,11 +119,23 @@ Freeze::TransactionalEvictorContext::checkDeadlockException()
}
}
+bool
+Freeze::TransactionalEvictorContext::clearUserException()
+{
+ bool result = _userExceptionDetected;
+ _userExceptionDetected = false;
+ return result;
+}
+
bool
-Freeze::TransactionalEvictorContext::response(bool)
+Freeze::TransactionalEvictorContext::response(bool ok)
{
if(_owner == IceUtil::ThreadControl())
{
+ if(!ok)
+ {
+ _userExceptionDetected = true;
+ }
return true;
}
else
diff --git a/cpp/src/Freeze/TransactionalEvictorContext.h b/cpp/src/Freeze/TransactionalEvictorContext.h
index f9bcb1aa375..12b2a2e8765 100644
--- a/cpp/src/Freeze/TransactionalEvictorContext.h
+++ b/cpp/src/Freeze/TransactionalEvictorContext.h
@@ -112,6 +112,8 @@ public:
void checkDeadlockException();
+ bool clearUserException();
+
void commit();
void rollback();
@@ -145,12 +147,16 @@ private:
bool _rollbackOnly;
std::auto_ptr<DeadlockException> _deadlockException;
-
+
//
// Protected by this
//
bool _deadlockExceptionDetected;
+ //
+ // Not protected (used only by dispatch thread)
+ //
+ bool _userExceptionDetected;
};
typedef IceUtil::Handle<TransactionalEvictorContext> TransactionalEvictorContextPtr;
diff --git a/cpp/src/Freeze/TransactionalEvictorI.cpp b/cpp/src/Freeze/TransactionalEvictorI.cpp
index f9629432ec6..eb359c22368 100644
--- a/cpp/src/Freeze/TransactionalEvictorI.cpp
+++ b/cpp/src/Freeze/TransactionalEvictorI.cpp
@@ -543,6 +543,11 @@ Freeze::TransactionalEvictorI::dispatch(Request& request)
// May throw DeadlockException
//
ctx->checkDeadlockException();
+
+ if(ctx->clearUserException() && _rollbackOnUserException)
+ {
+ ctx->rollback();
+ }
}
return dispatchStatus;
diff --git a/cpp/test/Freeze/evictor/Client.cpp b/cpp/test/Freeze/evictor/Client.cpp
index 0d090a33e80..a11d4cc23a3 100644
--- a/cpp/test/Freeze/evictor/Client.cpp
+++ b/cpp/test/Freeze/evictor/Client.cpp
@@ -371,6 +371,8 @@ public:
void
run()
{
+ int transferOp = 0;
+
for(int i = 0; i < 1000; i++)
{
//
@@ -385,9 +387,36 @@ public:
}
while(from == to);
+
try
{
- from->transfer(100, to);
+ //
+ // Alternate between transfer methods
+ //
+ switch(transferOp)
+ {
+ case 0:
+ {
+ from->transfer(100, to);
+ break;
+ }
+ case 1:
+ {
+ from->transfer2(100, to);
+ break;
+ }
+ case 2:
+ {
+ from->transfer3(100, to);
+ break;
+ }
+ default:
+ {
+ test(false);
+ }
+ };
+ transferOp++;
+ transferOp = transferOp % 3;
}
catch(const Test::InsufficientFundsException&)
{
@@ -403,12 +432,12 @@ public:
//
test(false);
}
-
+
/*
- if(i % 100 == 0)
- {
- cerr << "." << flush;
- }
+ if(i % 100 == 0)
+ {
+ cerr << "." << flush;
+ }
*/
}
}
diff --git a/cpp/test/Freeze/evictor/Test.ice b/cpp/test/Freeze/evictor/Test.ice
index adfc5827bf7..4770603c8da 100644
--- a/cpp/test/Freeze/evictor/Test.ice
+++ b/cpp/test/Freeze/evictor/Test.ice
@@ -38,6 +38,14 @@ class Account
["freeze:write"] void transfer(int amount, Account* toAccount) throws InsufficientFundsException;
//
+ // Other implementations of transfer that we want to test as well
+ //
+ ["freeze:write", "amd"] void transfer2(int amount, Account* toAccount) throws InsufficientFundsException;
+ ["freeze:write", "amd"] void transfer3(int amount, Account* toAccount) throws InsufficientFundsException;
+
+
+
+ //
// "Internal" operation
//
["freeze:write:mandatory"] void deposit(int amount) throws InsufficientFundsException;
diff --git a/cpp/test/Freeze/evictor/TestI.cpp b/cpp/test/Freeze/evictor/TestI.cpp
index ba64434c0aa..df6c87176ac 100644
--- a/cpp/test/Freeze/evictor/TestI.cpp
+++ b/cpp/test/Freeze/evictor/TestI.cpp
@@ -45,6 +45,125 @@ Test::AccountI::transfer(int amount, const Test::AccountPrx& toAccount, const Cu
deposit(-amount, current); // direct call
}
+void
+Test::AccountI::transfer2_async(const AMD_Account_transfer2Ptr& cb, int amount, const Test::AccountPrx& toAccount, const Current& current)
+{
+ //
+ // Here the dispatch thread does everything
+ //
+ test(_evictor->getCurrentTransaction() != 0);
+
+ try
+ {
+ toAccount->deposit(amount); // collocated call
+ deposit(-amount, current); // direct call
+ }
+ catch(const InsufficientFundsException& ex)
+ {
+ cb->ice_exception(ex);
+ return;
+ }
+
+ cb->ice_response();
+}
+
+
+class ResponseThread : public IceUtil::Thread, private IceUtil::Monitor<IceUtil::Mutex>
+{
+public:
+
+ ResponseThread(const Test::AMD_Account_transfer3Ptr& cb) :
+ _cb(cb),
+ _response(false)
+ {
+ }
+
+ void response()
+ {
+ Lock sync(*this);
+ _response = true;
+ notify();
+ }
+
+ void exception(const Ice::UserException& e)
+ {
+ Lock sync(*this);
+ _exception.reset(dynamic_cast<Ice::UserException*>(e.ice_clone()));
+ notify();
+ }
+
+
+ virtual void run()
+ {
+ Lock sync(*this);
+
+ bool timedOut = false;
+
+ while(!timedOut && _response == false && _exception.get() == 0)
+ {
+ timedOut = !timedWait(IceUtil::Time::seconds(1));
+ }
+
+ if(timedOut)
+ {
+ return;
+ }
+
+ if(_response)
+ {
+ _cb->ice_response();
+ }
+ else if(_exception.get() != 0)
+ {
+ _cb->ice_exception(*_exception.get());
+ }
+ else
+ {
+ _cb->ice_exception(Ice::TimeoutException(__FILE__, __LINE__));
+ }
+ }
+
+private:
+ Test::AMD_Account_transfer3Ptr _cb;
+ bool _response;
+ std::auto_ptr<Ice::UserException> _exception;
+};
+typedef IceUtil::Handle<ResponseThread> ResponseThreadPtr;
+
+
+void
+Test::AccountI::transfer3_async(const AMD_Account_transfer3Ptr& cb, int amount, const Test::AccountPrx& toAccount, const Current& current)
+{
+ //
+ // Here the dispatch thread does the actual work, but a separate thread sends the response
+ //
+
+ ResponseThreadPtr thread = new ResponseThread(cb);
+ thread->start(33000).detach();
+
+ test(_evictor->getCurrentTransaction() != 0);
+
+ try
+ {
+ toAccount->deposit(amount); // collocated call
+ deposit(-amount, current); // direct call
+ }
+ catch(const Ice::UserException& e)
+ {
+ //
+ // Need to rollback here -- "rollback on user exception" does not work
+ // when the dispatch commits before it gets any response!
+ //
+ _evictor->getCurrentTransaction()->rollback();
+
+ thread->exception(e);
+ return;
+ }
+
+ thread->response();
+}
+
+
Test::AccountI::AccountI(int initialBalance, const Freeze::TransactionalEvictorPtr& evictor) :
Account(initialBalance),
_evictor(evictor)
diff --git a/cpp/test/Freeze/evictor/TestI.h b/cpp/test/Freeze/evictor/TestI.h
index 9f39463a190..adcf6664ad0 100644
--- a/cpp/test/Freeze/evictor/TestI.h
+++ b/cpp/test/Freeze/evictor/TestI.h
@@ -33,6 +33,10 @@ public:
virtual void transfer(int, const Test::AccountPrx&, const Ice::Current&);
+ virtual void transfer2_async(const AMD_Account_transfer2Ptr&, int, const Test::AccountPrx&, const Ice::Current&);
+
+ virtual void transfer3_async(const AMD_Account_transfer3Ptr&, int, const Test::AccountPrx&, const Ice::Current&);
+
AccountI(int, const Freeze::TransactionalEvictorPtr&);
AccountI();