예제 #1
0
  public void arrayChanged(TCObject source, int startPos, Object array, int length) {
    if (isTransactionLoggingDisabled()) {
      return;
    }
    try {
      disableTransactionLogging();
      Object pojo = source.getPeerObject();
      ClientTransaction tx = getTransaction(pojo);

      if (!ClassUtils.isPrimitiveArray(array)) {
        Object[] objArray = (Object[]) array;
        for (int i = 0; i < length; i++) {

          Object element = objArray[i];
          if (!literalValues.isLiteralInstance(element)) {
            if (element != null)
              objectManager.checkPortabilityOfField(element, String.valueOf(i), pojo);

            TCObject tco = objectManager.lookupOrCreate(element);
            objArray[i] = tco.getObjectID();
            // record the reference in this transaction -- This is to solve the race condition of
            // transactions
            // that reference objects newly "created" in other transactions that may not commit
            // before us
            if (element != null) tx.createObject(tco);
          }
        }
      }
      tx.arrayChanged(source, startPos, array, length);

    } finally {
      enableTransactionLogging();
    }
  }
예제 #2
0
  /**
   * In order to support ReentrantLock, the TransactionContext that is going to be removed when
   * doing a commit may not always be at the top of a stack because an reentrant lock could issue a
   * lock within a synchronized block (although it is highly not recommended). Therefore, when a
   * commit is issued, we need to search back the stack from the top of the stack to find the
   * appropriate TransactionContext to be removed. Most likely, the TransactionContext to be removed
   * will be on the top of the stack. Therefore, the performance should be make must difference.
   * Only in some weird situations where reentrantLock is mixed with synchronized block will the
   * TransactionContext to be removed be found otherwise.
   */
  public void commit(String lockName) throws UnlockedSharedObjectException {
    logCommit0();
    if (isTransactionLoggingDisabled() || objectManager.isCreationInProgress()) {
      return;
    }

    // ClientTransaction tx = popTransaction();
    ClientTransaction tx = getTransaction();
    LockID lockID = lockManager.lockIDFor(lockName);
    if (lockID == null || lockID.isNull()) {
      lockID = tx.getLockID();
    }
    boolean hasCommitted = commit(lockID, tx, false);

    popTransaction(lockManager.lockIDFor(lockName));

    if (peekContext() != null) {
      if (hasCommitted) {
        createTxAndInitContext();
      } else {
        // If the current transaction has not committed, we will reuse the current transaction
        // so that the current changes will have a chance to commit at the next commit point.
        tx.setTransactionContext(peekContext());
        setTransaction(tx);
      }
    }
  }
예제 #3
0
  public boolean tryBegin(String lockName, WaitInvocation timeout, int lockLevel) {
    logTryBegin0(lockName, lockLevel);

    if (isTransactionLoggingDisabled() || objectManager.isCreationInProgress()) {
      return true;
    }

    final TxnType txnType = getTxnTypeFromLockLevel(lockLevel);
    ClientTransaction currentTransaction = getTransactionOrNull();

    if ((currentTransaction != null) && lockLevel == LockLevel.CONCURRENT) {
      // make formatter sane
      throw new AssertionError("Can't acquire concurrent locks in a nested lock context.");
    }

    final LockID lockID = lockManager.lockIDFor(lockName);
    boolean isLocked = lockManager.tryLock(lockID, timeout, lockLevel);
    if (!isLocked) {
      return isLocked;
    }

    pushTxContext(lockID, txnType);

    if (currentTransaction == null) {
      createTxAndInitContext();
    } else {
      currentTransaction.setTransactionContext(this.peekContext());
    }

    return isLocked;
  }
 // This can be overridden by subclass if you want different behavior.
 protected Object getObjectForKey(final ClientObjectManager objectManager, final Object k)
     throws ClassNotFoundException {
   try {
     return (k instanceof ObjectID ? objectManager.lookupObject((ObjectID) k) : k);
   } catch (AbortedOperationException e) {
     throw new TCRuntimeException(e);
   }
 }
 // This can be overridden by subclass if you want different behavior.
 private Object getObjectForValue(final ClientObjectManager objectManager, final Object v)
     throws ClassNotFoundException {
   try {
     return (v instanceof ObjectID ? objectManager.lookupObject((ObjectID) v) : v);
   } catch (AbortedOperationException e) {
     throw new TCRuntimeException(e);
   }
 }
예제 #6
0
  private boolean commitInternal(
      LockID lockID, ClientTransaction currentTransaction, boolean isWaitContext) {
    Assert.assertNotNull("transaction", currentTransaction);

    try {
      disableTransactionLogging();

      // If the current transactionContext is READ_ONLY, there is no need to commit.
      TransactionContext tc = peekContext(lockID);
      if (tc.getType().equals(TxnType.READ_ONLY)) {
        txMonitor.committedReadTransaction();
        return false;
      }

      boolean hasPendingCreateObjects = objectManager.hasPendingCreateObjects();
      if (hasPendingCreateObjects) {
        objectManager.addPendingCreateObjectsToTransaction();
      }

      currentTransaction.setAlreadyCommitted();
      if (currentTransaction.hasChangesOrNotifies() || hasPendingCreateObjects) {
        if (txMonitor.isEnabled()) {
          currentTransaction.updateMBean(txMonitor);
        }
        remoteTxManager.commit(currentTransaction);
      }
      return true;
    } finally {
      enableTransactionLogging();

      // always try to unlock even if we are throwing an exception
      // if (!isWaitContext && !currentTransaction.isNull()) {
      // lockManager.unlock(currentTransaction.getLockID());
      // }
      if (!isWaitContext && !currentTransaction.isNull()) {
        if (lockID != null && !lockID.isNull()) {
          lockManager.unlock(lockID);
        } else {
          throw new AssertionError("Trying to unlock with lockID = null!");
        }
      }
    }
  }
예제 #7
0
  private void basicApply(Collection objectChanges, Map newRoots, boolean force)
      throws DNAException {

    List l = new LinkedList();

    for (Iterator i = objectChanges.iterator(); i.hasNext(); ) {
      DNA dna = (DNA) i.next();
      TCObject tcobj = null;
      Assert.assertTrue(dna.isDelta());
      try {
        // This is a major hack to prevent distributed method calls
        // sent to apps that don't have the right classes from dying
        // This should be fixed in a better way some day :-)
        objectManager.getClassFor(
            Namespace.parseClassNameIfNecessary(dna.getTypeName()),
            dna.getDefiningLoaderDescription());
        tcobj = objectManager.lookup(dna.getObjectID());
      } catch (ClassNotFoundException cnfe) {
        logger.warn("Could not apply change because class not local:" + dna.getTypeName());
        continue;
      }
      // Important to have a hard reference to the object while we apply
      // changes so that it doesn't get gc'd on us
      Object obj = tcobj == null ? null : tcobj.getPeerObject();
      l.add(obj);
      if (obj != null) {
        try {
          tcobj.hydrate(dna, force);
        } catch (ClassNotFoundException cnfe) {
          logger.warn("Could not apply change because class not local:" + cnfe.getMessage());
          throw new TCClassNotFoundException(cnfe);
        }
      }
    }

    for (Iterator i = newRoots.entrySet().iterator(); i.hasNext(); ) {
      Entry entry = (Entry) i.next();
      String rootName = (String) entry.getKey();
      ObjectID newRootID = (ObjectID) entry.getValue();
      objectManager.replaceRootIDIfNecessary(rootName, newRootID);
    }
  }
예제 #8
0
  public void logicalInvoke(TCObject source, int method, String methodName, Object[] parameters) {
    if (isTransactionLoggingDisabled()) {
      return;
    }

    try {
      disableTransactionLogging();

      Object pojo = source.getPeerObject();
      ClientTransaction tx = getTransaction(pojo);

      for (int i = 0; i < parameters.length; i++) {
        Object p = parameters[i];
        boolean isLiteral = literalValues.isLiteralInstance(p);
        if (!isLiteral) {
          if (p != null) {
            objectManager.checkPortabilityOfLogicalAction(parameters, i, methodName, pojo);
          }

          TCObject tco = objectManager.lookupOrCreate(p);
          parameters[i] = tco.getObjectID();
          if (p != null) {
            // record the reference in this transaction -- This is to solve the race condition of
            // transactions
            // that reference objects newly "created" in other transactions that may not commit
            // before us
            tx.createObject(tco);
          }
        }
      }

      tx.logicalInvoke(source, method, parameters, methodName);
    } finally {
      enableTransactionLogging();
    }
  }
예제 #9
0
  public void fieldChanged(
      TCObject source, String classname, String fieldname, Object newValue, int index) {
    if (isTransactionLoggingDisabled()) {
      return;
    }

    try {
      disableTransactionLogging();

      Object pojo = source.getPeerObject();

      ClientTransaction tx = getTransaction(pojo);
      logFieldChanged0(source, classname, fieldname, newValue, tx);

      if (newValue != null && literalValues.isLiteralInstance(newValue)) {
        tx.fieldChanged(source, classname, fieldname, newValue, index);
      } else {
        if (newValue != null) {
          objectManager.checkPortabilityOfField(newValue, fieldname, pojo);
        }

        TCObject tco = objectManager.lookupOrCreate(newValue);
        tx.fieldChanged(source, classname, fieldname, tco.getObjectID(), index);

        // record the reference in this transaction -- This is to solve the race condition of
        // transactions
        // that reference objects newly "created" in other transactions that may not commit before
        // us
        if (newValue != null) {
          tx.createObject(tco);
        }
      }
    } finally {
      enableTransactionLogging();
    }
  }
  protected void apply(
      final ClientObjectManager objectManager,
      final Object po,
      final LogicalOperation method,
      final Object[] params)
      throws ClassNotFoundException {
    final ToolkitMapImpl m = (ToolkitMapImpl) po;
    switch (method) {
      case PUT:
        final Object k = params[0];
        final Object v = params[1];
        final Object pkey = getObjectForKey(objectManager, k);
        final Object value = getObjectForValue(objectManager, v);

        m.internalPut(pkey, value);
        break;
      case REMOVE:
        Object rkey;
        try {
          rkey =
              params[0] instanceof ObjectID
                  ? objectManager.lookupObject((ObjectID) params[0])
                  : params[0];
        } catch (AbortedOperationException e) {
          throw new TCRuntimeException(e);
        }
        m.internalRemove(rkey);

        break;
      case CLEAR:
        m.internalClear();
        break;
      case DESTROY:
        ((DestroyApplicator) m).applyDestroy();
        break;

      default:
        throw new AssertionError("invalid action:" + method);
    }
  }
예제 #11
0
  public boolean begin(String lockName, int lockLevel) {
    logBegin0(lockName, lockLevel);

    if (isTransactionLoggingDisabled() || objectManager.isCreationInProgress()) {
      return false;
    }

    final TxnType txnType = getTxnTypeFromLockLevel(lockLevel);
    ClientTransaction currentTransaction = getTransactionOrNull();

    final LockID lockID = lockManager.lockIDFor(lockName);

    pushTxContext(lockID, txnType);

    if (currentTransaction == null) {
      createTxAndInitContext();
    } else {
      currentTransaction.setTransactionContext(this.peekContext());
    }

    lockManager.lock(lockID, lockLevel);
    return true;
  }