Example #1
0
  @Override
  public Ice.DispatchStatus dispatch(Ice.Request request) {
    Ice.Current current = request.getCurrent();
    _lastOperation = current.operation;

    if (_lastOperation.equals("addWithRetry")) {
      for (int i = 0; i < 10; ++i) {
        try {
          _servant.ice_dispatch(request);
          test(false);
        } catch (RetryException re) {
          //
          // Expected, retry
          //
        }
      }

      current.ctx.put("retry", "no");
    }

    _lastStatus = _servant.ice_dispatch(request);
    return _lastStatus;
  }
  //
  // The interceptor dispatch call
  //
  Ice.DispatchStatus dispatch(Ice.Request request) {
    _deactivateController.lock();
    try {
      Ice.Current current = request.getCurrent();

      ObjectStore store = findStore(current.facet, false);
      if (store == null) {
        servantNotFound(current);
      }

      TransactionalEvictorContext ctx = _dbEnv.getCurrent();

      Ice.Object sample = store.sampleServant();
      Ice.Object cachedServant = null;

      TransactionalEvictorContext.ServantHolder servantHolder = null;
      try {
        if (sample == null) {
          if (ctx != null) {
            try {
              servantHolder = ctx.createServantHolder(current, store);
            } catch (DeadlockException dx) {
              assert dx.tx == ctx.transaction();
              ctx.deadlockException();
              throw new TransactionalEvictorDeadlockException(dx.tx);
            }
            sample = servantHolder.servant();
          } else {
            //
            // find / load read-only servant
            //

            cachedServant = loadCachedServant(current.id, store);

            if (cachedServant == null) {
              servantNotFound(current);
            }
            sample = cachedServant;
          }
        }

        assert sample != null;

        int operationAttributes = sample.ice_operationAttributes(current.operation);

        if (operationAttributes < 0) {
          throw new Ice.OperationNotExistException();
        }

        boolean readOnly = (operationAttributes & 0x1) == 0;

        int txMode = (operationAttributes & 0x6) >> 1;

        boolean ownCtx = false;

        //
        // Establish the proper context
        //
        switch (txMode) {
          case never:
            {
              assert readOnly;
              if (ctx != null) {
                throw new DatabaseException(
                    _errorPrefix + "transaction rejected by 'never' metadata");
              }
              break;
            }
          case supports:
            {
              assert readOnly;
              break;
            }
          case mandatory:
            {
              if (ctx == null) {
                throw new DatabaseException(
                    _errorPrefix + "operation with a mandatory transaction");
              }
              break;
            }
          case required:
            {
              if (ctx == null) {
                ownCtx = true;
              }
              break;
            }
          default:
            {
              assert false;
              throw new Ice.OperationNotExistException();
            }
        }

        if (ctx == null && !ownCtx) {
          //
          // Read-only dispatch
          //
          assert readOnly;
          if (cachedServant == null) {
            cachedServant = loadCachedServant(current.id, store);

            if (cachedServant == null) {
              servantNotFound(current);
            }
          }
          return cachedServant.ice_dispatch(request, null);
        } else {
          boolean tryAgain = false;
          do {
            Transaction tx = null;

            if (ownCtx) {
              ctx = _dbEnv.createCurrent();
            }

            tx = ctx.transaction();

            try {
              try {
                TransactionalEvictorContext.ServantHolder sh;
                if (servantHolder != null) {
                  assert !ownCtx;
                  //
                  // Adopt it
                  //
                  sh = servantHolder;
                  servantHolder = null;
                } else {
                  sh = ctx.createServantHolder(current, store);
                }

                if (sh.servant() == null) {
                  servantNotFound(current);
                }

                if (!readOnly) {
                  sh.markReadWrite();
                }

                try {
                  Ice.DispatchStatus dispatchStatus = sh.servant().ice_dispatch(request, ctx);
                  if (dispatchStatus == Ice.DispatchStatus.DispatchUserException
                      && _rollbackOnUserException) {
                    ctx.rollback();
                  }
                  if (dispatchStatus == Ice.DispatchStatus.DispatchAsync) {
                    //
                    // Can throw DeadlockException or TransactionalEvictorDeadlockException
                    //
                    ctx.checkDeadlockException();

                    if (ctx.clearUserException() && _rollbackOnUserException) {
                      ctx.rollback();
                    }
                  }
                  return dispatchStatus;
                } catch (RuntimeException ex) {
                  ctx.rollback();
                  throw ex;
                } finally {
                  sh.release();
                  if (ownCtx) {
                    ctx.commit();
                  }
                }
              } catch (DeadlockException dx) {
                if (dx.tx == tx) {
                  ctx.deadlockException();
                }
                throw dx;
              } finally {
                if (ownCtx) {
                  ctx.rollback();
                }
              }
            } catch (DeadlockException dx) {
              if (ownCtx && dx.tx == tx) {
                tryAgain = true;
              } else {
                throw new TransactionalEvictorDeadlockException(dx.tx);
              }
            } catch (TransactionalEvictorDeadlockException dx) {
              if (ownCtx && dx.tx == tx) {
                tryAgain = true;
              } else {
                throw dx;
              }
            } finally {
              if (ownCtx) {
                //
                // The commit or rollback above must have cleared it
                //
                assert (_dbEnv.getCurrent() == null);
              }
            }
          } while (tryAgain);
        }
      } finally {
        if (servantHolder != null) {
          //
          // Won't raise anything since it's read-only
          //
          servantHolder.release();
        }
      }

      //
      // Javac does not detect this can't be reached
      //
      assert (false);
      throw new Ice.OperationNotExistException();
    } finally {
      _deactivateController.unlock();
    }
  }