Esempio n. 1
0
  /**
   * Removes candidate from the list of near local candidates.
   *
   * @param cand Candidate to remove.
   */
  public void removeExplicitLock(GridCacheMvccCandidate cand) {
    GridCacheExplicitLockSpan span = pendingExplicit.get(cand.threadId());

    if (span == null) return;

    if (span.removeCandidate(cand)) pendingExplicit.remove(cand.threadId(), span);
  }
Esempio n. 2
0
  /**
   * Local release.
   *
   * @param threadId ID of the thread.
   * @return Removed candidate.
   */
  @Nullable
  public GridCacheMvccCandidate releaseLocal(long threadId) {
    CacheLockCandidates owners = localOwners();

    // Release had no effect.
    if (owners == null) return null;

    GridCacheMvccCandidate owner = null;

    for (int i = 0; i < owners.size(); i++) {
      GridCacheMvccCandidate owner0 = owners.candidate(i);

      if (owner0.threadId() == threadId) {
        owner = owner0;

        break;
      }
    }

    if (owner != null) {
      owner.setUsed();

      remove0(owner.version(), true);

      return owner;
    } else return null;
  }
Esempio n. 3
0
  /**
   * Near local candidate.
   *
   * @param nodeId Node ID.
   * @param threadId Thread ID.
   * @return Remote candidate.
   */
  @Nullable
  public GridCacheMvccCandidate localCandidate(UUID nodeId, long threadId) {
    if (locs != null)
      for (GridCacheMvccCandidate c : locs)
        if (c.nodeId().equals(nodeId) && c.threadId() == threadId) return c;

    return null;
  }
Esempio n. 4
0
  /**
   * @param nodeId Node ID.
   * @param threadId Thread ID.
   * @return Remote candidate.
   */
  @Nullable
  GridCacheMvccCandidate remoteCandidate(UUID nodeId, long threadId) {
    if (rmts != null)
      for (GridCacheMvccCandidate c : rmts)
        if (c.nodeId().equals(nodeId) && c.threadId() == threadId) return c;

    return null;
  }
Esempio n. 5
0
  /**
   * @param threadId Thread ID.
   * @param reentry Reentry flag.
   * @return Local candidate for the thread.
   */
  @Nullable
  private GridCacheMvccCandidate localCandidate(long threadId, boolean reentry) {
    if (locs != null)
      for (GridCacheMvccCandidate cand : locs) {
        if (cand.threadId() == threadId) {
          if (cand.reentry() && !reentry) continue;

          return cand;
        }
      }

    return null;
  }
Esempio n. 6
0
  /**
   * @param lockVer Lock ID.
   * @param threadId Thread ID.
   * @return {@code True} if locked by lock ID or thread ID.
   */
  boolean isLocallyOwnedByIdOrThread(GridCacheVersion lockVer, long threadId) {
    CacheLockCandidates owners = localOwners();

    if (owners != null) {
      for (int i = 0; i < owners.size(); i++) {
        GridCacheMvccCandidate owner = owners.candidate(i);

        if ((owner.version().equals(lockVer) || owner.threadId() == threadId)) return true;
      }
    }

    return false;
  }
Esempio n. 7
0
  /**
   * Removes explicit lock for given thread id, key and optional version.
   *
   * @param threadId Thread id.
   * @param key Key.
   * @param ver Optional version.
   * @return Candidate.
   */
  public GridCacheMvccCandidate removeExplicitLock(
      long threadId, KeyCacheObject key, @Nullable GridCacheVersion ver) {
    assert threadId > 0;

    GridCacheExplicitLockSpan span = pendingExplicit.get(threadId);

    if (span == null) return null;

    GridCacheMvccCandidate cand = span.removeCandidate(key, ver);

    if (cand != null && span.isEmpty()) pendingExplicit.remove(cand.threadId(), span);

    return cand;
  }
Esempio n. 8
0
  /**
   * @param threadId Thread ID to check.
   * @param exclude Versions to ignore.
   * @return {@code True} if lock is owned by the thread with given ID.
   */
  boolean isLocallyOwnedByThread(long threadId, boolean allowDhtLoc, GridCacheVersion... exclude) {
    CacheLockCandidates owners = localOwners();

    if (owners != null) {
      for (int i = 0; i < owners.size(); i++) {
        GridCacheMvccCandidate owner = owners.candidate(i);

        if (owner.threadId() == threadId
            && owner.nodeId().equals(cctx.nodeId())
            && (allowDhtLoc || !owner.dhtLocal())
            && !U.containsObjectArray(exclude, owner.version())) return true;
      }
    }

    return false;
  }
Esempio n. 9
0
  /**
   * Adds candidate to the list of near local candidates.
   *
   * @param threadId Thread ID.
   * @param cand Candidate to add.
   * @param topVer Topology version.
   */
  public void addExplicitLock(
      long threadId, GridCacheMvccCandidate cand, AffinityTopologyVersion topVer) {
    while (true) {
      GridCacheExplicitLockSpan span = pendingExplicit.get(cand.threadId());

      if (span == null) {
        span = new GridCacheExplicitLockSpan(topVer, cand);

        GridCacheExplicitLockSpan old = pendingExplicit.putIfAbsent(threadId, span);

        if (old == null) break;
        else span = old;
      }

      // Either span was not empty, or concurrent put did not succeed.
      if (span.addCandidate(topVer, cand)) break;
      else pendingExplicit.remove(threadId, span);
    }
  }
Esempio n. 10
0
  /**
   * @param parent Parent entry.
   * @param nearNodeId Near node ID.
   * @param nearVer Near version.
   * @param threadId Thread ID.
   * @param ver Lock version.
   * @param timeout Lock acquisition timeout.
   * @param serOrder Version for serializable transactions ordering.
   * @param reenter Reentry flag ({@code true} if reentry is allowed).
   * @param tx Transaction flag.
   * @param implicitSingle Implicit flag.
   * @param dhtLoc DHT local flag.
   * @param read Read lock flag.
   * @return New lock candidate if lock was added, or current owner if lock was reentered, or
   *     <tt>null</tt> if lock was owned by another thread and timeout is negative.
   */
  @Nullable
  public GridCacheMvccCandidate addLocal(
      GridCacheEntryEx parent,
      @Nullable UUID nearNodeId,
      @Nullable GridCacheVersion nearVer,
      long threadId,
      GridCacheVersion ver,
      long timeout,
      @Nullable GridCacheVersion serOrder,
      boolean reenter,
      boolean tx,
      boolean implicitSingle,
      boolean dhtLoc,
      boolean read) {
    if (log.isDebugEnabled())
      log.debug(
          "Adding local candidate [mvcc="
              + this
              + ", parent="
              + parent
              + ", threadId="
              + threadId
              + ", ver="
              + ver
              + ", timeout="
              + timeout
              + ", reenter="
              + reenter
              + ", tx="
              + tx
              + "]");

    // Don't check reenter for DHT candidates.
    if (!dhtLoc && !reenter) {
      GridCacheMvccCandidate owner = localOwner();

      if (owner != null && owner.threadId() == threadId) return null;
    }

    // If there are pending locks and timeout is negative,
    // then we give up right away.
    if (timeout < 0) {
      if (locs != null || rmts != null) {
        GridCacheMvccCandidate owner = localOwner();

        // Only proceed if this is a re-entry.
        if (owner == null || owner.threadId() != threadId) return null;
      }
    }

    UUID locNodeId = cctx.nodeId();

    // If this is a reentry, then reentry flag will be flipped within 'add0(..)' method.
    GridCacheMvccCandidate cand =
        new GridCacheMvccCandidate(
            parent,
            locNodeId,
            nearNodeId,
            nearVer,
            threadId,
            ver,
            /*local*/ true,
            /*reenter*/ false,
            tx,
            implicitSingle,
            /*near-local*/ false,
            dhtLoc,
            serOrder,
            read);

    if (serOrder == null) {
      boolean add = add0(cand);

      assert add : cand;
    } else {
      if (!add0(cand)) return null;
    }

    return cand;
  }
Esempio n. 11
0
  /**
   * @param cand Candidate to add.
   * @return {@code False} if failed to add candidate and transaction should be cancelled.
   */
  private boolean add0(GridCacheMvccCandidate cand) {
    assert cand != null;

    // Local.
    if (cand.local()) {
      if (locs == null) locs = new LinkedList<>();

      if (!cand.nearLocal()) {
        if (!locs.isEmpty()) {
          if (cand.serializable()) {
            Iterator<GridCacheMvccCandidate> it = locs.descendingIterator();

            if (cand.read()) {
              while (it.hasNext()) {
                GridCacheMvccCandidate c = it.next();

                if (!c.serializable()) return false;

                if (!c.read()) {
                  if (compareSerializableVersion(c, cand)) break;
                  else return false;
                }
              }
            } else {
              while (it.hasNext()) {
                GridCacheMvccCandidate c = it.next();

                if (!c.serializable() || !compareSerializableVersion(c, cand)) return false;

                if (!c.read()) break;
              }
            }

            locs.addLast(cand);

            return true;
          }

          GridCacheMvccCandidate first = locs.getFirst();

          if (first.owner()) {
            // If reentry, add at the beginning. Note that
            // no reentry happens for DHT-local candidates.
            if (!cand.dhtLocal() && first.threadId() == cand.threadId()) {
              assert !first.serializable();

              cand.setOwner();
              cand.setReady();
              cand.setReentry();

              locs.addFirst(cand);

              return true;
            }
          }

          // Iterate in reverse order.
          for (ListIterator<GridCacheMvccCandidate> it = locs.listIterator(locs.size());
              it.hasPrevious(); ) {
            GridCacheMvccCandidate c = it.previous();

            assert !c.version().equals(cand.version())
                : "Versions can't match [existing=" + c + ", new=" + cand + ']';

            // Add after the owner or serializable tx.
            if (c.owner() || c.serializable()) {
              // Threads are checked above.
              assert cand.dhtLocal() || c.threadId() != cand.threadId();

              // Reposition.
              it.next();

              it.add(cand);

              return true;
            }

            // If not the owner, add after the lesser version.
            if (c.version().isLess(cand.version())) {
              // Reposition.
              it.next();

              it.add(cand);

              return true;
            }
          }
        }

        // Either list is empty or candidate is first.
        locs.addFirst(cand);
      } else
        // For near local candidates just add it to the end of list.
        locs.add(cand);
    }
    // Remote.
    else {
      assert !cand.serializable() && !cand.read() : cand;

      if (rmts == null) rmts = new LinkedList<>();

      assert !cand.owner() || localOwners() == null
          : "Cannot have local and remote owners "
              + "at the same time [cand="
              + cand
              + ", locs="
              + locs
              + ", rmts="
              + rmts
              + ']';

      GridCacheMvccCandidate cur = candidate(rmts, cand.version());

      // For existing candidates, we only care about owners and keys.
      if (cur != null) {
        if (cand.owner()) cur.setOwner();

        return true;
      }

      // Either list is empty or candidate is last.
      rmts.add(cand);
    }

    return true;
  }