Esempio n. 1
0
  /**
   * @param cand Candidate to check.
   * @return First predecessor that is owner or is not used.
   */
  @Nullable
  private GridCacheMvccCandidate nonRollbackPrevious(GridCacheMvccCandidate cand) {
    for (GridCacheMvccCandidate c = cand.previous(); c != null; c = c.previous()) {
      if (c.owner() || !c.used()) return c;
    }

    return null;
  }
Esempio n. 2
0
  /**
   * @param cacheCtx Cache context.
   * @param cand Cache lock candidate to add.
   * @return {@code True} if added as a result of this operation, {@code false} if was previously
   *     added.
   */
  public boolean addNext(GridCacheContext cacheCtx, GridCacheMvccCandidate cand) {
    assert cand != null;
    assert !cand.reentry() : "Lock reentries should not be linked: " + cand;

    // Don't order near candidates by thread as they will be ordered on
    // DHT node. Also, if candidate is implicit, no point to order him.
    if (cacheCtx.isNear() || cand.singleImplicit()) return true;

    LinkedList<GridCacheMvccCandidate> queue = pending.get();

    GridCacheMvccCandidate prev = null;

    if (!queue.isEmpty()) prev = queue.getLast();

    queue.add(cand);

    if (prev != null) {
      prev.next(cand);

      cand.previous(prev);
    }

    if (log.isDebugEnabled()) log.debug("Linked new candidate: " + cand);

    return true;
  }
Esempio n. 3
0
  /** Assigns local lock. */
  private void reassign() {
    GridCacheMvccCandidate firstRmt = null;

    if (rmts != null) {
      for (GridCacheMvccCandidate cand : rmts) {
        if (firstRmt == null) firstRmt = cand;

        // If there is a remote owner, then local cannot be an owner,
        // so no reassignment happens.
        if (cand.owner()) return;
      }
    }

    if (locs != null) {
      boolean first = true;

      ListIterator<GridCacheMvccCandidate> it = locs.listIterator();

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

        if (first) {
          if (cand.read()) {
            if (cand.ready() && !cand.owner()) cand.setOwner();

            while (it.hasNext()) {
              cand = it.next();

              if (!cand.read()) break;

              if (cand.ready() && !cand.owner()) cand.setOwner();
            }

            return;
          } else if (cand.serializable()) {
            if (cand.owner() || !cand.ready()) return;

            cand.setOwner();

            return;
          }

          first = false;
        }

        if (cand.owner()) return;

        if (cand.ready()) {
          GridCacheMvccCandidate prev = nonRollbackPrevious(cand);

          // If previous has not been acquired, this candidate cannot acquire lock either,
          // so we move on to the next one.
          if (prev != null && !prev.owner()) continue;

          boolean assigned = false;

          if (!cctx.isNear() && firstRmt != null && cand.version().isGreater(firstRmt.version())) {
            // Check previous candidates for 2 cases:
            // 1. If this candidate is waiting for a smaller remote version,
            //    then we must check if previous candidate is the owner and
            //    has the same remote candidate version. In that case, we can
            //    safely set this candidate to owner as well.
            // 2. If this candidate is waiting for a smaller remote version,
            //    then we must check if previous candidate is the owner and
            //    any of the local candidates with versions smaller than first
            //    remote version have the same key as the previous owner. In
            //    that case, we can safely set this candidate to owner as well.
            while (prev != null && prev.owner()) {
              for (GridCacheMvccCandidate c : prev.parent().remoteMvccSnapshot()) {
                if (c.version().equals(firstRmt.version())) {
                  cand.setOwner();

                  assigned = true;

                  break; // For.
                }
              }

              if (!assigned) {
                for (GridCacheMvccCandidate c : locs) {
                  if (c == cand || c.version().isGreater(firstRmt.version())) break;

                  for (GridCacheMvccCandidate p = c.previous(); p != null; p = p.previous()) {
                    if (p.key().equals(prev.key())) {
                      cand.setOwner();

                      assigned = true;

                      break; // For.
                    }
                  }

                  if (assigned) break; // For.
                }
              }

              if (assigned) break; // While.

              prev = prev.previous();
            }
          }

          if (!assigned) {
            if (!cctx.isNear() && firstRmt != null) {
              if (cand.version().isLess(firstRmt.version())) {
                assert !cand.nearLocal();

                cand.setOwner();

                assigned = true;
              }
            } else {
              cand.setOwner();

              assigned = true;
            }
          }

          if (assigned) {
            assert !cand.serializable() : cand;

            it.remove();

            // Owner must be first in the list.
            locs.addFirst(cand);
          }

          return;
        }
      }
    }
  }