/**
   * Adds group reservation to this partition.
   *
   * @param r Reservation.
   * @return {@code false} If such reservation already added.
   */
  public boolean addReservation(GridDhtPartitionsReservation r) {
    assert state.getReference() != EVICTED : "we can reserve only active partitions";
    assert state.getStamp() != 0
        : "partition must be already reserved before adding group reservation";

    return reservations.addIfAbsent(r);
  }
  /**
   * @param updateSeq Update sequence.
   * @return {@code True} if entry has been transitioned to state EVICTED.
   */
  boolean tryEvict(boolean updateSeq) {
    if (state.getReference() != RENTING || state.getStamp() != 0 || groupReserved()) return false;

    // Attempt to evict partition entries from cache.
    clearAll();

    if (map.isEmpty() && state.compareAndSet(RENTING, EVICTED, 0, 0)) {
      if (log.isDebugEnabled()) log.debug("Evicted partition: " + this);

      if (!GridQueryProcessor.isEnabled(cctx.config())) clearSwap();

      if (cctx.isDrEnabled()) cctx.dr().partitionEvicted(id);

      cctx.dataStructures().onPartitionEvicted(id);

      rent.onDone();

      ((GridDhtPreloader) cctx.preloader()).onPartitionEvicted(this, updateSeq);

      clearDeferredDeletes();

      return true;
    }

    return false;
  }
 /** attemptStamp succeeds in single thread */
 public void testAttemptStamp() {
   int[] mark = new int[1];
   AtomicStampedReference ai = new AtomicStampedReference(one, 0);
   assertEquals(0, ai.getStamp());
   assertTrue(ai.attemptStamp(one, 1));
   assertEquals(1, ai.getStamp());
   assertSame(one, ai.get(mark));
   assertEquals(1, mark[0]);
 }
  /**
   * Reserves a partition so it won't be cleared.
   *
   * @return {@code True} if reserved.
   */
  @Override
  public boolean reserve() {
    while (true) {
      int reservations = state.getStamp();

      GridDhtPartitionState s = state.getReference();

      if (s == EVICTED) return false;

      if (state.compareAndSet(s, s, reservations, reservations + 1)) return true;
    }
  }
  /**
   * @param updateSeq Update sequence.
   * @return Future for evict attempt.
   */
  IgniteInternalFuture<Boolean> tryEvictAsync(boolean updateSeq) {
    if (map.isEmpty()
        && !GridQueryProcessor.isEnabled(cctx.config())
        && state.compareAndSet(RENTING, EVICTED, 0, 0)) {
      if (log.isDebugEnabled()) log.debug("Evicted partition: " + this);

      clearSwap();

      if (cctx.isDrEnabled()) cctx.dr().partitionEvicted(id);

      cctx.dataStructures().onPartitionEvicted(id);

      rent.onDone();

      ((GridDhtPreloader) cctx.preloader()).onPartitionEvicted(this, updateSeq);

      clearDeferredDeletes();

      return new GridFinishedFuture<>(true);
    }

    return cctx.closures()
        .callLocalSafe(
            new GPC<Boolean>() {
              @Override
              public Boolean call() {
                return tryEvict(true);
              }
            }, /*system pool*/
            true);
  }
  /** compareAndSet in one thread enables another waiting for reference value to succeed */
  public void testCompareAndSetInMultipleThreads() throws Exception {
    final AtomicStampedReference ai = new AtomicStampedReference(one, 0);
    Thread t =
        new Thread(
            new CheckedRunnable() {
              public void realRun() {
                while (!ai.compareAndSet(two, three, 0, 0)) Thread.yield();
              }
            });

    t.start();
    assertTrue(ai.compareAndSet(one, two, 0, 0));
    t.join(LONG_DELAY_MS);
    assertFalse(t.isAlive());
    assertSame(three, ai.getReference());
    assertEquals(0, ai.getStamp());
  }
  /** Releases previously reserved partition. */
  @Override
  public void release() {
    while (true) {
      int reservations = state.getStamp();

      if (reservations == 0) return;

      GridDhtPartitionState s = state.getReference();

      assert s != EVICTED;

      // Decrement reservations.
      if (state.compareAndSet(s, s, reservations, --reservations)) {
        tryEvict(true);

        break;
      }
    }
  }
 public void revertRestartRequired(Object stamp) {
   // If 'state' still has the state we last set in restartRequired(), change to RUNNING
   Integer theirStamp = Integer.class.cast(stamp);
   synchronized (service) {
     if (state.compareAndSet(
         State.RESTART_REQUIRED, State.RUNNING, theirStamp, this.stamp.incrementAndGet())) {
       service.stateChanged(State.RUNNING);
     }
   }
 }
 public Object setRestartRequired() {
   AtomicStampedReference<State> stateRef = state;
   int newStamp = stamp.incrementAndGet();
   int[] receiver = new int[1];
   // Keep trying until stateRef is RESTART_REQUIRED with our stamp
   for (; ; ) {
     State was = stateRef.get(receiver);
     if (was == State.STARTING || was == State.STOPPING) {
       break;
     }
     synchronized (service) {
       if (stateRef.compareAndSet(was, State.RESTART_REQUIRED, receiver[0], newStamp)) {
         service.stateChanged(State.RESTART_REQUIRED);
         break;
       }
     }
   }
   return Integer.valueOf(newStamp);
 };
  /**
   * @param updateSeq Update sequence.
   * @return Future to signal that this node is no longer an owner or backup.
   */
  IgniteInternalFuture<?> rent(boolean updateSeq) {
    while (true) {
      int reservations = state.getStamp();

      GridDhtPartitionState s = state.getReference();

      if (s == RENTING || s == EVICTED) return rent;

      if (state.compareAndSet(s, RENTING, reservations, reservations)) {
        if (log.isDebugEnabled()) log.debug("Moved partition to RENTING state: " + this);

        // Evict asynchronously, as the 'rent' method may be called
        // from within write locks on local partition.
        tryEvictAsync(updateSeq);

        break;
      }
    }

    return rent;
  }
  /** @return {@code True} if transitioned to OWNING state. */
  boolean own() {
    while (true) {
      int reservations = state.getStamp();

      GridDhtPartitionState s = state.getReference();

      if (s == RENTING || s == EVICTED) return false;

      if (s == OWNING) return true;

      assert s == MOVING;

      if (state.compareAndSet(MOVING, OWNING, reservations, reservations)) {
        if (log.isDebugEnabled()) log.debug("Owned partition: " + this);

        // No need to keep history any more.
        evictHist = null;

        return true;
      }
    }
  }
 /** constructor initializes to given reference and stamp */
 public void testConstructor() {
   AtomicStampedReference ai = new AtomicStampedReference(one, 0);
   assertSame(one, ai.getReference());
   assertEquals(0, ai.getStamp());
   AtomicStampedReference a2 = new AtomicStampedReference(null, 1);
   assertNull(a2.getReference());
   assertEquals(1, a2.getStamp());
 }
  /**
   * compareAndSet succeeds in changing values if equal to expected reference and stamp else fails
   */
  public void testCompareAndSet() {
    int[] mark = new int[1];
    AtomicStampedReference ai = new AtomicStampedReference(one, 0);
    assertSame(one, ai.get(mark));
    assertEquals(0, ai.getStamp());
    assertEquals(0, mark[0]);

    assertTrue(ai.compareAndSet(one, two, 0, 0));
    assertSame(two, ai.get(mark));
    assertEquals(0, mark[0]);

    assertTrue(ai.compareAndSet(two, m3, 0, 1));
    assertSame(m3, ai.get(mark));
    assertEquals(1, mark[0]);

    assertFalse(ai.compareAndSet(two, m3, 1, 1));
    assertSame(m3, ai.get(mark));
    assertEquals(1, mark[0]);
  }
Example #14
0
 public boolean attemptModifyASR() {
   boolean modified = false;
   IntendedModification currentlyOngoingMod = ongoingMod.getReference();
   int stamp = ongoingMod.getStamp();
   if (currentlyOngoingMod == null) {
     // copy data structure state - for use
     // in intended modification
     // prepare intended modification
     IntendedModification newMod = new IntendedModification();
     // compareAndSet(V expectedReference, V newReference, int expectedStamp, int newStamp) {}
     boolean modSubmitted = ongoingMod.compareAndSet(null, newMod, stamp, stamp + 1);
     if (modSubmitted) {
       // complete modification via a series of compare-and-swap operations.
       // note: other threads may assist in completing the compare-and-swap
       // operations, so some CAS may fail
       modified = true;
     }
   } else {
     // attempt to complete ongoing modification, so the data structure is fired up
     // to allow access from this thread.
     modified = false;
   }
   return modified;
 }
  /** repeated weakCompareAndSet succeeds in changing values when equal to expected */
  public void testWeakCompareAndSet() {
    int[] mark = new int[1];
    AtomicStampedReference ai = new AtomicStampedReference(one, 0);
    assertSame(one, ai.get(mark));
    assertEquals(0, ai.getStamp());
    assertEquals(0, mark[0]);

    do {} while (!ai.weakCompareAndSet(one, two, 0, 0));
    assertSame(two, ai.get(mark));
    assertEquals(0, mark[0]);

    do {} while (!ai.weakCompareAndSet(two, m3, 0, 1));
    assertSame(m3, ai.get(mark));
    assertEquals(1, mark[0]);
  }
 public State getState() {
   return state.getReference();
 }
 public void setStarting() {
   synchronized (service) {
     state.set(State.STARTING, stamp.incrementAndGet());
     service.stateChanged(State.STARTING);
   }
 }
 /** get returns the last values of reference and stamp set */
 public void testGetSet() {
   int[] mark = new int[1];
   AtomicStampedReference ai = new AtomicStampedReference(one, 0);
   assertSame(one, ai.getReference());
   assertEquals(0, ai.getStamp());
   assertSame(one, ai.get(mark));
   assertEquals(0, mark[0]);
   ai.set(two, 0);
   assertSame(two, ai.getReference());
   assertEquals(0, ai.getStamp());
   assertSame(two, ai.get(mark));
   assertEquals(0, mark[0]);
   ai.set(one, 1);
   assertSame(one, ai.getReference());
   assertEquals(1, ai.getStamp());
   assertSame(one, ai.get(mark));
   assertEquals(1, mark[0]);
 }
 public void setRunning() {
   synchronized (service) {
     state.set(State.RUNNING, stamp.incrementAndGet());
     service.stateChanged(State.RUNNING);
   }
 }
 /** @return Reservations. */
 public int reservations() {
   return state.getStamp();
 }
 /** @return Partition state. */
 public GridDhtPartitionState state() {
   return state.getReference();
 }