public void commit(Xid xid, boolean isOnePhase) throws XAException {
   // always call prepare() - even if this is just a 1PC!
   if (isOnePhase) prepare(xid);
   if (trace) log.trace("committing TransactionXaAdapter: " + globalTx);
   try {
     LocalTxInvocationContext ctx = icc.createTxInvocationContext();
     ctx.setXaCache(this);
     if (configuration.isOnePhaseCommit()) {
       checkMarkedForRollback();
       if (trace) log.trace("Doing an 1PC prepare call on the interceptor chain");
       PrepareCommand command = commandsFactory.buildPrepareCommand(globalTx, modifications, true);
       try {
         invoker.invoke(ctx, command);
       } catch (Throwable e) {
         log.error("Error while processing 1PC PrepareCommand", e);
         throw new XAException(XAException.XAER_RMERR);
       }
     } else {
       CommitCommand commitCommand = commandsFactory.buildCommitCommand(globalTx);
       try {
         invoker.invoke(ctx, commitCommand);
       } catch (Throwable e) {
         log.error("Error while processing 1PC PrepareCommand", e);
         throw new XAException(XAException.XAER_RMERR);
       }
     }
   } finally {
     txTable.removeLocalTransaction(transaction);
     this.modifications = null;
   }
 }
示例#2
0
  private Object executeCommandAndCommitIfNeeded(InvocationContext ctx, VisitableCommand command) {
    final boolean txInjected =
        ctx.isInTxScope() && ((TxInvocationContext) ctx).isImplicitTransaction();
    Object result;
    try {
      result = invoker.invoke(ctx, command);
    } catch (RuntimeException e) {
      if (txInjected) tryRollback();
      throw e;
    }

    if (txInjected) {
      if (trace)
        log.tracef("Committing transaction as it was implicit: %s", getOngoingTransaction());
      try {
        transactionManager.commit();
      } catch (Throwable e) {
        log.couldNotCompleteInjectedTransaction(e);
        tryRollback();
        throw new CacheException("Could not commit implicit transaction", e);
      }
    }

    return result;
  }
示例#3
0
 @SuppressWarnings("unchecked")
 final V get(Object key, EnumSet<Flag> explicitFlags, ClassLoader explicitClassLoader) {
   assertKeyNotNull(key);
   InvocationContext ctx = getInvocationContextForRead(null, explicitFlags, explicitClassLoader);
   GetKeyValueCommand command = commandsFactory.buildGetKeyValueCommand(key, ctx.getFlags());
   return (V) invoker.invoke(ctx, command);
 }
 private void applyStateInTransaction(XSiteState[] chunk) throws Exception {
   try {
     transactionManager.begin();
     InvocationContext ctx =
         invocationContextFactory.createInvocationContext(
             transactionManager.getTransaction(), true);
     ((TxInvocationContext) ctx)
         .getCacheTransaction()
         .setStateTransferFlag(PUT_FOR_X_SITE_STATE_TRANSFER);
     for (XSiteState siteState : chunk) {
       interceptorChain.invoke(ctx, createPut(siteState));
       if (trace) {
         log.tracef("Successfully applied key'%s'", siteState);
       }
     }
     transactionManager.commit();
     if (debug) {
       log.debugf("Successfully applied state. %s keys inserted", chunk.length);
     }
   } catch (Exception e) {
     log.unableToApplyXSiteState(e);
     safeRollback();
     throw e;
   }
 }
 public static void replicateCommand(Cache cache, VisitableCommand command) throws Throwable {
   ComponentRegistry cr = extractComponentRegistry(cache);
   InterceptorChain ic = cr.getComponent(InterceptorChain.class);
   InvocationContextContainer icc = cr.getComponent(InvocationContextContainer.class);
   InvocationContext ctxt = icc.createInvocationContext(true, -1);
   ic.invoke(ctxt, command);
 }
示例#6
0
 final boolean containsKey(
     Object key, EnumSet<Flag> explicitFlags, ClassLoader explicitClassLoader) {
   assertKeyNotNull(key);
   InvocationContext ctx = getInvocationContextForRead(null, explicitFlags, explicitClassLoader);
   GetKeyValueCommand command = commandsFactory.buildGetKeyValueCommand(key, ctx.getFlags());
   Object response = invoker.invoke(ctx, command);
   return response != null;
 }
示例#7
0
 boolean lock(
     Collection<? extends K> keys, EnumSet<Flag> explicitFlags, ClassLoader explicitClassLoader) {
   if (keys == null || keys.isEmpty()) {
     throw new IllegalArgumentException("Cannot lock empty list of keys");
   }
   InvocationContext ctx = getInvocationContextForWrite(explicitFlags, explicitClassLoader);
   LockControlCommand command =
       commandsFactory.buildLockControlCommand(keys, false, ctx.getFlags());
   return (Boolean) invoker.invoke(ctx, command);
 }
 public void applyRemoteTxLog(List<WriteCommand> commands) {
   for (WriteCommand cmd : commands) {
     try {
       // this is a remotely originating tx
       cf.initializeReplicableCommand(cmd, true);
       InvocationContext ctx = icc.createInvocationContext();
       ctx.setFlags(SKIP_REMOTE_LOOKUP, CACHE_MODE_LOCAL, SKIP_SHARED_CACHE_STORE, SKIP_LOCKING);
       interceptorChain.invoke(ctx, cmd);
     } catch (Exception e) {
       log.exceptionWhenReplaying(cmd, e);
     }
   }
 }
 public void rollback(Xid xid) throws XAException {
   RollbackCommand rollbackCommand = commandsFactory.buildRollbackCommand(globalTx);
   LocalTxInvocationContext ctx = icc.createTxInvocationContext();
   ctx.setXaCache(this);
   try {
     invoker.invoke(ctx, rollbackCommand);
   } catch (Throwable e) {
     log.error("Exception while rollback", e);
     throw new XAException(XAException.XA_HEURHAZ);
   } finally {
     txTable.removeLocalTransaction(transaction);
     this.modifications = null;
   }
 }
  private void applyStateInNonTransaction(XSiteState[] chunk) {
    SingleKeyNonTxInvocationContext ctx =
        (SingleKeyNonTxInvocationContext)
            invocationContextFactory.createSingleKeyNonTxInvocationContext();

    for (XSiteState siteState : chunk) {
      PutKeyValueCommand command = createPut(siteState);
      ctx.setLockOwner(command.getLockOwner());
      interceptorChain.invoke(ctx, command);
      ctx.resetState(); // re-use same context. Old context is not longer needed
      if (trace) {
        log.tracef("Successfully applied key'%s'", siteState);
      }
    }
    if (debug) {
      log.debugf("Successfully applied state. %s keys inserted", chunk.length);
    }
  }
  public int prepare(Xid xid) throws XAException {
    checkMarkedForRollback();
    if (configuration.isOnePhaseCommit()) {
      if (trace)
        log.trace("Received prepare for tx: " + xid + " . Skipping call as 1PC will be used.");
      return XA_OK;
    }

    PrepareCommand prepareCommand =
        commandsFactory.buildPrepareCommand(
            globalTx, modifications, configuration.isOnePhaseCommit());
    if (trace) log.trace("Sending prepare command through the chain: " + prepareCommand);

    LocalTxInvocationContext ctx = icc.createTxInvocationContext();
    ctx.setXaCache(this);
    try {
      invoker.invoke(ctx, prepareCommand);
      return XA_OK;
    } catch (Throwable e) {
      log.error("Error while processing PrepareCommand", e);
      throw new XAException(XAException.XAER_RMERR);
    }
  }
  private Map<Object, InternalCacheValue> applyStateMap(
      Map<Object, InternalCacheValue> state, boolean withRetry) {
    Map<Object, InternalCacheValue> retry =
        withRetry ? new HashMap<Object, InternalCacheValue>() : null;

    for (Map.Entry<Object, InternalCacheValue> e : state.entrySet()) {
      InternalCacheValue v = e.getValue();
      InvocationContext ctx = icc.createInvocationContext();
      // locking not necessary in the case of a join since the node isn't doing anything else
      // TODO what if the node is already running?
      ctx.setFlags(
          CACHE_MODE_LOCAL,
          SKIP_CACHE_LOAD,
          SKIP_REMOTE_LOOKUP,
          SKIP_SHARED_CACHE_STORE,
          SKIP_LOCKING,
          SKIP_OWNERSHIP_CHECK);
      try {
        PutKeyValueCommand put =
            cf.buildPutKeyValueCommand(
                e.getKey(), v.getValue(), v.getLifespan(), v.getMaxIdle(), ctx.getFlags());
        interceptorChain.invoke(ctx, put);
      } catch (Exception ee) {
        if (withRetry) {
          if (trace)
            log.tracef(
                "Problem %s encountered when applying state for key %s. Adding entry to retry queue.",
                ee.getMessage(), e.getKey());
          retry.put(e.getKey(), e.getValue());
        } else {
          log.problemApplyingStateForKey(ee.getMessage(), e.getKey());
        }
      }
    }
    return retry;
  }
示例#13
0
 final int size(EnumSet<Flag> explicitFlags, ClassLoader explicitClassLoader) {
   SizeCommand command = commandsFactory.buildSizeCommand();
   return (Integer)
       invoker.invoke(
           getInvocationContextForRead(null, explicitFlags, explicitClassLoader), command);
 }
示例#14
0
 final void evict(K key, EnumSet<Flag> explicitFlags, ClassLoader explicitClassLoader) {
   assertKeyNotNull(key);
   InvocationContext ctx = createNonTxInvocationContext(explicitFlags, explicitClassLoader);
   EvictCommand command = commandsFactory.buildEvictCommand(key);
   invoker.invoke(ctx, command);
 }
示例#15
0
 @SuppressWarnings("unchecked")
 Set<Map.Entry<K, V>> entrySet(EnumSet<Flag> explicitFlags, ClassLoader explicitClassLoader) {
   InvocationContext ctx = getInvocationContextForRead(null, explicitFlags, explicitClassLoader);
   EntrySetCommand command = commandsFactory.buildEntrySetCommand();
   return (Set<Map.Entry<K, V>>) invoker.invoke(ctx, command);
 }
示例#16
0
 @SuppressWarnings("unchecked")
 Collection<V> values(EnumSet<Flag> explicitFlags, ClassLoader explicitClassLoader) {
   InvocationContext ctx = getInvocationContextForRead(null, explicitFlags, explicitClassLoader);
   ValuesCommand command = commandsFactory.buildValuesCommand();
   return (Collection<V>) invoker.invoke(ctx, command);
 }
示例#17
0
  private void doApplyState(
      Address sender, int segmentId, Collection<InternalCacheEntry> cacheEntries) {
    log.debugf(
        "Applying new state for segment %d of cache %s from node %s: received %d cache entries",
        segmentId, cacheName, sender, cacheEntries.size());
    if (trace) {
      List<Object> keys = new ArrayList<Object>(cacheEntries.size());
      for (InternalCacheEntry e : cacheEntries) {
        keys.add(e.getKey());
      }
      log.tracef(
          "Received keys %s for segment %d of cache %s from node %s",
          keys, segmentId, cacheName, sender);
    }

    // CACHE_MODE_LOCAL avoids handling by StateTransferInterceptor and any potential locks in
    // StateTransferLock
    EnumSet<Flag> flags =
        EnumSet.of(
            PUT_FOR_STATE_TRANSFER,
            CACHE_MODE_LOCAL,
            IGNORE_RETURN_VALUES,
            SKIP_REMOTE_LOOKUP,
            SKIP_SHARED_CACHE_STORE,
            SKIP_OWNERSHIP_CHECK,
            SKIP_XSITE_BACKUP);
    for (InternalCacheEntry e : cacheEntries) {
      try {
        InvocationContext ctx;
        if (transactionManager != null) {
          // cache is transactional
          transactionManager.begin();
          Transaction transaction = transactionManager.getTransaction();
          ctx = icc.createInvocationContext(transaction);
          ((TxInvocationContext) ctx).setImplicitTransaction(true);
        } else {
          // non-tx cache
          ctx = icc.createSingleKeyNonTxInvocationContext();
        }

        PutKeyValueCommand put =
            useVersionedPut
                ? commandsFactory.buildVersionedPutKeyValueCommand(
                    e.getKey(),
                    e.getValue(),
                    e.getLifespan(),
                    e.getMaxIdle(),
                    e.getVersion(),
                    flags)
                : commandsFactory.buildPutKeyValueCommand(
                    e.getKey(), e.getValue(), e.getLifespan(), e.getMaxIdle(), flags);

        boolean success = false;
        try {
          interceptorChain.invoke(ctx, put);
          success = true;
        } finally {
          if (ctx.isInTxScope()) {
            if (success) {
              ((LocalTransaction) ((TxInvocationContext) ctx).getCacheTransaction())
                  .setFromStateTransfer(true);
              try {
                transactionManager.commit();
              } catch (Throwable ex) {
                log.errorf(
                    ex,
                    "Could not commit transaction created by state transfer of key %s",
                    e.getKey());
                if (transactionManager.getTransaction() != null) {
                  transactionManager.rollback();
                }
              }
            } else {
              transactionManager.rollback();
            }
          }
        }
      } catch (Exception ex) {
        log.problemApplyingStateForKey(ex.getMessage(), e.getKey(), ex);
      }
    }
    log.debugf("Finished applying state for segment %d of cache %s", segmentId, cacheName);
  }
示例#18
0
  private void invalidateSegments(Set<Integer> newSegments, Set<Integer> segmentsToL1) {
    // The actual owners keep track of the nodes that hold a key in L1 ("requestors") and
    // they invalidate the key on every requestor after a change.
    // But this information is only present on the owners where the ClusteredGetKeyValueCommand
    // got executed - if the requestor only contacted one owner, and that node is no longer an owner
    // (perhaps because it left the cluster), the other owners will not know to invalidate the key
    // on that requestor. Furthermore, the requestors list is not copied to the new owners during
    // state transfers.
    // To compensate for this, we delete all L1 entries in segments that changed ownership during
    // this topology update. We can't actually differentiate between L1 entries and regular entries,
    // so we delete all entries that don't belong to this node in the current OR previous topology.
    Set<Object> keysToL1 = new HashSet<Object>();
    Set<Object> keysToRemove = new HashSet<Object>();

    // gather all keys from data container that belong to the segments that are being removed/moved
    // to L1
    for (InternalCacheEntry ice : dataContainer) {
      Object key = ice.getKey();
      int keySegment = getSegment(key);
      if (segmentsToL1.contains(keySegment)) {
        keysToL1.add(key);
      } else if (!newSegments.contains(keySegment)) {
        keysToRemove.add(key);
      }
    }

    // gather all keys from cache store that belong to the segments that are being removed/moved to
    // L1
    CacheStore cacheStore = getCacheStore();
    if (cacheStore != null) {
      // todo [anistor] extend CacheStore interface to be able to specify a filter when loading keys
      // (ie. keys should belong to desired segments)
      try {
        Set<Object> storedKeys =
            cacheStore.loadAllKeys(new ReadOnlyDataContainerBackedKeySet(dataContainer));
        for (Object key : storedKeys) {
          int keySegment = getSegment(key);
          if (segmentsToL1.contains(keySegment)) {
            keysToL1.add(key);
          } else if (!newSegments.contains(keySegment)) {
            keysToRemove.add(key);
          }
        }

      } catch (CacheLoaderException e) {
        log.failedLoadingKeysFromCacheStore(e);
      }
    }

    if (configuration.clustering().l1().onRehash()) {
      log.debugf("Moving to L1 state for segments %s of cache %s", segmentsToL1, cacheName);
    } else {
      log.debugf("Removing state for segments %s of cache %s", segmentsToL1, cacheName);
    }
    if (!keysToL1.isEmpty()) {
      try {
        InvalidateCommand invalidateCmd =
            commandsFactory.buildInvalidateFromL1Command(
                true, EnumSet.of(CACHE_MODE_LOCAL, SKIP_LOCKING), keysToL1);
        InvocationContext ctx = icc.createNonTxInvocationContext();
        interceptorChain.invoke(ctx, invalidateCmd);

        log.debugf(
            "Invalidated %d keys, data container now has %d keys",
            keysToL1.size(), dataContainer.size());
        if (trace) log.tracef("Invalidated keys: %s", keysToL1);
      } catch (CacheException e) {
        log.failedToInvalidateKeys(e);
      }
    }

    log.debugf(
        "Removing L1 state for segments not in %s or %s for cache %s",
        newSegments, segmentsToL1, cacheName);
    if (!keysToRemove.isEmpty()) {
      try {
        InvalidateCommand invalidateCmd =
            commandsFactory.buildInvalidateFromL1Command(
                false, EnumSet.of(CACHE_MODE_LOCAL, SKIP_LOCKING), keysToRemove);
        InvocationContext ctx = icc.createNonTxInvocationContext();
        interceptorChain.invoke(ctx, invalidateCmd);

        log.debugf(
            "Invalidated %d keys, data container of cache %s now has %d keys",
            keysToRemove.size(), cacheName, dataContainer.size());
        if (trace) log.tracef("Invalidated keys: %s", keysToRemove);
      } catch (CacheException e) {
        log.failedToInvalidateKeys(e);
      }
    }

    // todo [anistor] call CacheNotifier.notifyDataRehashed
  }