summaryrefslogtreecommitdiff
path: root/cpp/src/Freeze/TransactionalEvictorI.cpp
diff options
context:
space:
mode:
authorBernard Normier <bernard@zeroc.com>2007-06-27 16:27:24 -0400
committerBernard Normier <bernard@zeroc.com>2007-06-27 16:27:24 -0400
commit85a70987f18610fb4d4eac2eded8155a9b2a6031 (patch)
treebba146de64978f6804149bfe524c53f6b5c0bc97 /cpp/src/Freeze/TransactionalEvictorI.cpp
parentminor edits (diff)
downloadice-85a70987f18610fb4d4eac2eded8155a9b2a6031.tar.bz2
ice-85a70987f18610fb4d4eac2eded8155a9b2a6031.tar.xz
ice-85a70987f18610fb4d4eac2eded8155a9b2a6031.zip
Freeze transaction attributes + new Freeze/casino demo
Diffstat (limited to 'cpp/src/Freeze/TransactionalEvictorI.cpp')
-rw-r--r--cpp/src/Freeze/TransactionalEvictorI.cpp358
1 files changed, 195 insertions, 163 deletions
diff --git a/cpp/src/Freeze/TransactionalEvictorI.cpp b/cpp/src/Freeze/TransactionalEvictorI.cpp
index 273eb4c6216..f9629432ec6 100644
--- a/cpp/src/Freeze/TransactionalEvictorI.cpp
+++ b/cpp/src/Freeze/TransactionalEvictorI.cpp
@@ -20,6 +20,19 @@ using namespace std;
using namespace Freeze;
using namespace Ice;
+namespace
+{
+
+//
+// Must be in sync with Parser.cpp
+//
+
+const int supports = 0;
+const int mandatory = 1;
+const int required = 2;
+const int never = 3;
+}
+
//
// createEvictor functions
@@ -76,7 +89,7 @@ Freeze::TransactionalEvictorI::TransactionalEvictorI(const ObjectAdapterPtr& ada
{
}
- virtual Ice::DispatchStatus dispatch(Ice::Request& request)
+ virtual DispatchStatus dispatch(Request& request)
{
return _evictor->dispatch(request);
}
@@ -119,7 +132,7 @@ Freeze::TransactionalEvictorI::setCurrentTransaction(const TransactionPtr& tx)
}
-Ice::ObjectPrx
+ObjectPrx
Freeze::TransactionalEvictorI::addFacet(const ObjectPtr& servant, const Identity& ident, const string& facet)
{
checkIdentity(ident);
@@ -146,7 +159,7 @@ Freeze::TransactionalEvictorI::addFacet(const ObjectPtr& servant, const Identity
if(!store->insert(ident, rec, tx))
{
- Ice::AlreadyRegisteredException ex(__FILE__, __LINE__);
+ AlreadyRegisteredException ex(__FILE__, __LINE__);
ex.kindOfObject = "servant";
ex.id = _communicator->identityToString(ident);
if(!facet.empty())
@@ -164,7 +177,7 @@ Freeze::TransactionalEvictorI::addFacet(const ObjectPtr& servant, const Identity
return obj;
}
-Ice::ObjectPtr
+ObjectPtr
Freeze::TransactionalEvictorI::removeFacet(const Identity& ident, const string& facet)
{
checkIdentity(ident);
@@ -318,14 +331,15 @@ Freeze::TransactionalEvictorI::finished(const Current&, const ObjectPtr&, const
//
}
-Ice::DispatchStatus
-Freeze::TransactionalEvictorI::dispatch(Ice::Request& request)
+DispatchStatus
+Freeze::TransactionalEvictorI::dispatch(Request& request)
{
class CtxHolder
{
public:
- CtxHolder(const TransactionalEvictorContextPtr& ctx, const SharedDbEnvPtr& dbEnv) :
+ CtxHolder(bool ownCtx, const TransactionalEvictorContextPtr& ctx, const SharedDbEnvPtr& dbEnv) :
+ _ownCtx(ownCtx),
_ctx(ctx),
_dbEnv(dbEnv)
{
@@ -333,20 +347,24 @@ Freeze::TransactionalEvictorI::dispatch(Ice::Request& request)
~CtxHolder()
{
- try
- {
- _ctx->commit();
- }
- catch(...)
+ if(_ownCtx)
{
+ try
+ {
+ _ctx->commit();
+ }
+ catch(...)
+ {
+ _dbEnv->setCurrentTransaction(0);
+ throw;
+ }
_dbEnv->setCurrentTransaction(0);
- throw;
}
- _dbEnv->setCurrentTransaction(0);
}
private:
- TransactionalEvictorContextPtr _ctx;
+ const bool _ownCtx;
+ const TransactionalEvictorContextPtr _ctx;
const SharedDbEnvPtr& _dbEnv;
};
@@ -360,205 +378,219 @@ Freeze::TransactionalEvictorI::dispatch(Ice::Request& request)
{
servantNotFound(__FILE__, __LINE__, current);
}
-
- //
- // Is there an existing context?
- //
+
TransactionalEvictorContextPtr ctx = _dbEnv->getCurrent();
-
- if(ctx != 0)
+
+ ObjectPtr sample = store->sampleServant();
+ ObjectPtr cachedServant = 0;
+
+ TransactionalEvictorContext::ServantHolder servantHolder;
+
+ if(sample == 0)
{
- try
+ if(ctx != 0)
+ {
+ try
+ {
+ servantHolder.init(ctx, current, store);
+ }
+ catch(const DeadlockException&)
+ {
+ ctx->deadlockException();
+ throw;
+ }
+ sample = servantHolder.servant();
+ }
+ else
{
//
- // If yes, use this context; there is no retrying
+ // find / load read-only servant
//
- TransactionalEvictorContext::ServantHolder servantHolder(ctx, current, store, _useNonmutating);
-
- if(servantHolder.servant() == 0)
+
+ cachedServant = loadCachedServant(current.id, store);
+
+ if(cachedServant == 0)
{
servantNotFound(__FILE__, __LINE__, current);
}
-
- try
- {
- DispatchStatus dispatchStatus = servantHolder.servant()->ice_dispatch(request, ctx);
+ sample = cachedServant;
+ }
+ }
+
+ assert(sample != 0);
+
+ int operationAttributes = sample->ice_operationAttributes(current.operation);
- if(dispatchStatus == DispatchUserException && _rollbackOnUserException)
- {
- ctx->rollback();
- }
+ bool readOnly = (_useNonmutating && current.mode == Nonmutating)
+ || (!_useNonmutating && (operationAttributes & 0x1) == 0);
+
+ int txMode = (operationAttributes & 0x6) >> 1;
+
+ bool ownCtx = false;
- if(dispatchStatus == DispatchAsync)
- {
- //
- // May throw DeadlockException
- //
- ctx->checkDeadlockException();
- }
- return dispatchStatus;
+ //
+ // Establish the proper context
+ //
+ switch(txMode)
+ {
+ case never:
+ {
+ assert(readOnly);
+ if(ctx != 0)
+ {
+ throw DatabaseException(__FILE__, __LINE__, "transaction rejected by 'never' metadata");
}
- catch(...)
+ break;
+ }
+ case supports:
+ {
+ assert(readOnly);
+ break;
+ }
+ case mandatory:
+ {
+ if(ctx == 0)
{
- //
- // Important: this rollback() ensures that servant holder destructor won't perform
- // any database operation, and hence will not throw.
- //
- ctx->rollback();
- throw;
+ throw DatabaseException(__FILE__, __LINE__, "operation with a mandatory transaction");
}
- //
- // servantHolder destructor runs here and may throw (if tx was not rolled back)
- //
+ break;
}
- catch(const DeadlockException&)
+ case required:
{
- ctx->deadlockException();
- throw;
+ if(ctx == 0)
+ {
+ ownCtx = true;
+ }
+ break;
}
- catch(...)
+ default:
{
- ctx->rollback();
- throw;
+ assert(0);
}
}
- else
+
+ if(ctx == 0 && !ownCtx)
{
- ObjectPtr servant = 0;
-
//
- // Otherwise, first figure out if it's a read or write operation
+ // Read-only dispatch
//
- bool readOnly = true;
-
- if(_useNonmutating)
- {
- readOnly = (current.mode == Ice::Nonmutating);
- }
- else
+ assert(readOnly);
+ if(cachedServant == 0)
{
- //
- // Is there a sample-servant associated with this store?
- //
+ cachedServant = loadCachedServant(current.id, store);
- ObjectPtr sample = store->sampleServant();
- if(sample != 0)
+ if(cachedServant == 0)
{
- readOnly = (sample->ice_operationAttributes(current.operation) & 0x1) == 0;
- }
- else
- {
- //
- // Otherwise find / load read-only servant
- //
- servant = loadCachedServant(current.id, store);
- if(servant == 0)
- {
- servantNotFound(__FILE__, __LINE__, current);
- }
- else
- {
- readOnly = (servant->ice_operationAttributes(current.operation) & 0x1) == 0;
- }
+ servantNotFound(__FILE__, __LINE__, current);
}
}
-
+ return cachedServant->ice_dispatch(request);
+ }
+ else
+ {
//
- // readOnly is now set properly
+ // Create a new transaction; retry on DeadlockException
//
- if(readOnly)
+
+ bool tryAgain = false;
+
+ do
{
- if(servant == 0)
+ try
{
- servant = loadCachedServant(current.id, store);
- if(servant == 0)
+ if(ownCtx)
{
- servantNotFound(__FILE__, __LINE__, current);
+ ctx = _dbEnv->createCurrent();
}
- }
- // otherwise reuse servant loaded above
-
- //
- // Non-transactional, read-only dispatch
- //
- return servant->ice_dispatch(request);
- }
- else
- {
- //
- // Create a new transaction; retry on DeadlockException
- //
-
- bool tryAgain = false;
-
- do
- {
+
+ CtxHolder ctxHolder(ownCtx, ctx, _dbEnv);
+
try
- {
- ctx = _dbEnv->createCurrent();
- CtxHolder ctxHolder(ctx, _dbEnv);
-
- try
- {
- TransactionalEvictorContext::ServantHolder servantHolder(ctx, current, store, _useNonmutating);
-
- if(servantHolder.servant() == 0)
- {
- servantNotFound(__FILE__, __LINE__, current);
- }
+ {
+ TransactionalEvictorContext::ServantHolder sh;
+ if(servantHolder.initialized())
+ {
+ //
+ // Adopt it
+ //
+ sh.adopt(servantHolder);
+ }
+ else
+ {
+ sh.init(ctx, current, store);
+ }
+
+ if(sh.servant() == 0)
+ {
+ servantNotFound(__FILE__, __LINE__, current);
+ }
+
+ if(!readOnly)
+ {
+ sh.markReadWrite();
+ }
- try
+ try
+ {
+ DispatchStatus dispatchStatus = sh.servant()->ice_dispatch(request, ctx);
+ if(dispatchStatus == DispatchUserException && _rollbackOnUserException)
{
- DispatchStatus dispatchStatus = servantHolder.servant()->ice_dispatch(request, ctx);
- if(dispatchStatus == DispatchUserException && _rollbackOnUserException)
- {
- ctx->rollback();
- }
- if(dispatchStatus == DispatchAsync)
- {
- //
- // May throw DeadlockException
- //
- ctx->checkDeadlockException();
- }
-
- return dispatchStatus;
+ ctx->rollback();
}
- catch(...)
+ if(dispatchStatus == DispatchAsync)
{
//
- // Important: this rollback() ensures that servant holder destructor won't perform
- // any database operation, and hence will not throw.
+ // May throw DeadlockException
//
- ctx->rollback();
- throw;
+ ctx->checkDeadlockException();
}
- //
- // servant holder destructor runs here and may throw (if !rolled back)
- //
- }
- catch(const DeadlockException&)
- {
- ctx->deadlockException();
- throw;
+
+ return dispatchStatus;
}
catch(...)
{
+ //
+ // Important: this rollback() ensures that servant holder destructor won't perform
+ // any database operation, and hence will not throw.
+ //
ctx->rollback();
throw;
}
-
- //
- // commit occurs here!
//
+ // servant holder destructor runs here and may throw (if !rolled back)
+ //
}
catch(const DeadlockException&)
{
- tryAgain = true;
+ ctx->deadlockException();
+ throw;
+ }
+ catch(...)
+ {
+ if(ownCtx)
+ {
+ ctx->rollback();
+ }
+ throw;
}
- } while(tryAgain);
- }
+ //
+ // commit occurs here (when ownCtx)
+ //
+ }
+ catch(const DeadlockException&)
+ {
+ if(ownCtx)
+ {
+ tryAgain = true;
+ }
+ else
+ {
+ throw;
+ }
+ }
+
+ } while(tryAgain);
}
//
@@ -633,7 +665,7 @@ Freeze::TransactionalEvictorI::evict()
}
-Ice::ObjectPtr
+ObjectPtr
Freeze::TransactionalEvictorI::loadCachedServant(const Identity& ident, ObjectStore<TransactionalEvictorElement>* store)
{
for(;;)
@@ -664,7 +696,7 @@ Freeze::TransactionalEvictorI::loadCachedServant(const Identity& ident, ObjectSt
}
}
-Ice::ObjectPtr
+ObjectPtr
Freeze::TransactionalEvictorI::evict(const Identity& ident, ObjectStore<TransactionalEvictorElement>* store)
{
//