/** {@inheritDoc} */
        @SuppressWarnings({"unchecked"})
        @Override
        public void onOwnerChanged(
            GridCacheEntryEx entry, GridCacheMvccCandidate prev, GridCacheMvccCandidate owner) {
          assert entry != null;
          assert owner != prev : "New and previous owner are identical instances: " + owner;
          assert owner == null || prev == null || !owner.version().equals(prev.version())
              : "New and previous owners have identical versions [owner="
                  + owner
                  + ", prev="
                  + prev
                  + ']';

          if (log.isDebugEnabled())
            log.debug(
                "Received owner changed callback ["
                    + entry.key()
                    + ", owner="
                    + owner
                    + ", prev="
                    + prev
                    + ']');

          if (owner != null && (owner.local() || owner.nearLocal())) {
            Collection<? extends GridCacheFuture> futCol = futs.get(owner.version());

            if (futCol != null) {
              for (GridCacheFuture fut : futCol) {
                if (fut instanceof GridCacheMvccFuture && !fut.isDone()) {
                  GridCacheMvccFuture<Boolean> mvccFut = (GridCacheMvccFuture<Boolean>) fut;

                  // Since this method is called outside of entry synchronization,
                  // we can safely invoke any method on the future.
                  // Also note that we don't remove future here if it is done.
                  // The removal is initiated from within future itself.
                  if (mvccFut.onOwnerChanged(entry, owner)) return;
                }
              }
            }
          }

          if (log.isDebugEnabled())
            log.debug(
                "Lock future not found for owner change callback (will try transaction futures) [owner="
                    + owner
                    + ", prev="
                    + prev
                    + ", entry="
                    + entry
                    + ']');

          // If no future was found, delegate to transaction manager.
          if (cctx.tm().onOwnerChanged(entry, owner)) {
            if (log.isDebugEnabled()) log.debug("Found transaction for changed owner: " + owner);
          } else if (log.isDebugEnabled())
            log.debug("Failed to find transaction for changed owner: " + owner);

          for (FinishLockFuture f : finishFuts) f.recheck(entry);
        }
Exemple #2
0
  /**
   * @param cand Local candidate added in any of the {@code addLocal(..)} methods.
   * @return Current lock owner.
   */
  @Nullable
  public CacheLockCandidates readyLocal(GridCacheMvccCandidate cand) {
    assert cand.local();

    cand.setReady();

    reassign();

    return allOwners();
  }
Exemple #3
0
  /**
   * @param ver Lock version to acquire or set to ready.
   * @return Current owner.
   */
  @Nullable
  public CacheLockCandidates readyLocal(GridCacheVersion ver) {
    GridCacheMvccCandidate cand = candidate(ver);

    if (cand == null) return allOwners();

    assert cand.local();

    return readyLocal(cand);
  }
Exemple #4
0
  /** @param cand Remote candidate. */
  private void addRemote(GridCacheMvccCandidate cand) {
    assert !cand.local();

    if (log.isDebugEnabled())
      log.debug("Adding remote candidate [mvcc=" + this + ", cand=" + cand + "]");

    cctx.versions().onReceived(cand.nodeId(), cand.version());

    add0(cand);
  }
  /**
   * @param cand Local candidate to remove.
   * @return {@code True} if removed.
   */
  public boolean removeLocal(GridCacheMvccCandidate cand) {
    assert cand.key() != null;
    assert cand.local();

    if (cand.dhtLocal() && dhtLocCands.remove(cand)) {
      if (log.isDebugEnabled()) log.debug("Removed local candidate: " + cand);

      return true;
    }

    return false;
  }
Exemple #6
0
  /**
   * Sets remote candidate to done.
   *
   * @param ver Version.
   * @param pending Pending versions.
   * @param committed Committed versions.
   * @param rolledback Rolledback versions.
   * @return Lock owner.
   */
  @Nullable
  public CacheLockCandidates doneRemote(
      GridCacheVersion ver,
      Collection<GridCacheVersion> pending,
      Collection<GridCacheVersion> committed,
      Collection<GridCacheVersion> rolledback) {
    assert ver != null;

    if (log.isDebugEnabled())
      log.debug("Setting remote candidate to done [mvcc=" + this + ", ver=" + ver + "]");

    // Check remote candidate.
    GridCacheMvccCandidate cand = candidate(rmts, ver);

    if (cand != null) {
      assert rmts != null;
      assert !rmts.isEmpty();
      assert !cand.local() : "Remote candidate is marked as local: " + cand;
      assert !cand.nearLocal() : "Remote candidate is marked as near local: " + cand;

      cand.setOwner();
      cand.setUsed();

      List<GridCacheMvccCandidate> mvAfter = null;

      for (ListIterator<GridCacheMvccCandidate> it = rmts.listIterator(); it.hasNext(); ) {
        GridCacheMvccCandidate c = it.next();

        assert !c.nearLocal() : "Remote candidate marked as near local: " + c;

        if (c == cand) {
          if (mvAfter != null) for (GridCacheMvccCandidate mv : mvAfter) it.add(mv);

          break;
        } else if (!committed.contains(c.version())
            && !rolledback.contains(c.version())
            && pending.contains(c.version())) {
          it.remove();

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

          mvAfter.add(c);
        }
      }
    }

    return allOwners();
  }
Exemple #7
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;
  }