@Override
 public void terminate() {
   INSTANCES.remove(this);
   super.terminate();
   if (osgiManager != null) {
     osgiManager.stop();
     osgiManager = null;
   }
   if (execution != null) execution.shutdownNow();
   if (gc != null) gc.shutdownNow();
 }
  /**
   * Unsubscribe the given subscription id.
   *
   * @see #subscribe(Map, Entity, Sensor, SensorEventListener)
   */
  public synchronized boolean unsubscribe(SubscriptionHandle sh) {
    if (!(sh instanceof Subscription))
      throw new IllegalArgumentException(
          "Only subscription handles of type Subscription supported: sh="
              + sh
              + "; type="
              + (sh != null ? sh.getClass().getCanonicalName() : null));
    Subscription s = (Subscription) sh;
    boolean b1 = allSubscriptions.remove(s.id) != null;
    boolean b2 =
        LanguageUtils.removeFromMapOfCollections(
            subscriptionsByToken, makeEntitySensorToken(s.producer, s.sensor), s);
    assert b1 == b2;
    if (s.subscriber != null) {
      boolean b3 =
          LanguageUtils.removeFromMapOfCollections(subscriptionsBySubscriber, s.subscriber, s);
      assert b3 == b2;
    }

    // TODO Requires code review: why did we previously do exactly same check twice in a row (with
    // no synchronization in between)?
    if ((subscriptionsBySubscriber.size() == 0
            || !groovyTruth(subscriptionsBySubscriber.get(s.subscriber)))
        && !s.subscriberExecutionManagerTagSupplied
        && s.subscriberExecutionManagerTag != null) {
      // if subscriber has gone away forget about his task; but check in synch block to ensure
      // setTaskPreprocessor call above will win in any race
      if ((subscriptionsBySubscriber.size() == 0
          || !groovyTruth(subscriptionsBySubscriber.get(s.subscriber))))
        ((BasicExecutionManager) em).clearTaskPreprocessorForTag(s.subscriberExecutionManagerTag);
    }

    // FIXME ALEX - this seems wrong
    ((BasicExecutionManager) em)
        .setTaskSchedulerForTag(s.subscriberExecutionManagerTag, SingleThreadedScheduler.class);
    return b1;
  }
  /**
   * This implementation handles the following flags, in addition to those described in the {@link
   * SubscriptionManager} interface:
   *
   * <ul>
   *   <li>subscriberExecutionManagerTag - a tag to pass to execution manager (without setting any
   *       execution semantics / TaskPreprocessor); if not supplied and there is a subscriber, this
   *       will be inferred from the subscriber and set up with SingleThreadedScheduler (supply this
   *       flag with value null to prevent any task preprocessor from being set)
   *   <li>eventFilter - a Predicate&lt;SensorEvent&gt; instance to filter what events are delivered
   * </ul>
   *
   * @see SubscriptionManager#subscribe(Map, Entity, Sensor, SensorEventListener)
   */
  public synchronized <T> SubscriptionHandle subscribe(
      Map<String, Object> flags,
      Entity producer,
      Sensor<T> sensor,
      SensorEventListener<? super T> listener) {
    Subscription s = new Subscription(producer, sensor, listener);
    s.subscriber = flags.containsKey("subscriber") ? flags.remove("subscriber") : listener;
    if (flags.containsKey("subscriberExecutionManagerTag")) {
      s.subscriberExecutionManagerTag = flags.remove("subscriberExecutionManagerTag");
      s.subscriberExecutionManagerTagSupplied = true;
    } else {
      s.subscriberExecutionManagerTag =
          s.subscriber instanceof Entity
              ? "subscription-delivery-entity-"
                  + ((Entity) s.subscriber).getId()
                  + "["
                  + s.subscriber
                  + "]"
              : s.subscriber instanceof String
                  ? "subscription-delivery-string[" + s.subscriber + "]"
                  : s != null ? "subscription-delivery-object[" + s.subscriber + "]" : null;
      s.subscriberExecutionManagerTagSupplied = false;
    }
    s.eventFilter = (Predicate) flags.remove("eventFilter");
    s.flags = flags;

    if (LOG.isDebugEnabled())
      LOG.debug(
          "Creating subscription {} for {} on {} {} in {}",
          new Object[] {s, s.subscriber, producer, sensor, this});
    allSubscriptions.put(s.id, s);
    LanguageUtils.addToMapOfSets(
        subscriptionsByToken, makeEntitySensorToken(s.producer, s.sensor), s);
    if (s.subscriber != null) {
      LanguageUtils.addToMapOfSets(subscriptionsBySubscriber, s.subscriber, s);
    }
    if (!s.subscriberExecutionManagerTagSupplied && s.subscriberExecutionManagerTag != null) {
      ((BasicExecutionManager) em)
          .setTaskSchedulerForTag(s.subscriberExecutionManagerTag, SingleThreadedScheduler.class);
    }
    return s;
  }
  @Test(groups = {"Integration", "Acceptance"})
  public void testExecuteWithSingleThreadedScheduler() throws Exception {
    double minRatePerSec = 1000 * PERFORMANCE_EXPECTATION;

    executionManager.setTaskSchedulerForTag("singlethreaded", SingleThreadedScheduler.class);

    final AtomicInteger concurrentCallCount = new AtomicInteger();
    final AtomicInteger submitCount = new AtomicInteger();
    final AtomicInteger counter = new AtomicInteger();
    final CountDownLatch completionLatch = new CountDownLatch(1);
    final List<Exception> exceptions = Lists.newCopyOnWriteArrayList();

    final Runnable work =
        new Runnable() {
          public void run() {
            int numConcurrentCalls = concurrentCallCount.incrementAndGet();
            try {
              if (numConcurrentCalls > 1)
                throw new IllegalStateException("numConcurrentCalls=" + numConcurrentCalls);
              int val = counter.incrementAndGet();
              if (val >= numIterations) completionLatch.countDown();
            } catch (Exception e) {
              exceptions.add(e);
              LOG.warn("Exception in runnable of testExecuteWithSingleThreadedScheduler", e);
              throw Exceptions.propagate(e);
            } finally {
              concurrentCallCount.decrementAndGet();
            }
          }
        };

    measureAndAssert(
        "testExecuteWithSingleThreadedScheduler",
        numIterations,
        minRatePerSec,
        new Runnable() {
          public void run() {
            while (submitCount.get() > counter.get() + 5000) {
              LOG.info(
                  "delaying because "
                      + submitCount.get()
                      + " submitted and only "
                      + counter.get()
                      + " run");
              Time.sleep(500);
            }
            executionManager.submit(
                MutableMap.of("tags", ImmutableList.of("singlethreaded")), work);
            submitCount.incrementAndGet();
          }
        },
        new Runnable() {
          public void run() {
            try {
              completionLatch.await(LONG_TIMEOUT_MS, TimeUnit.MILLISECONDS);
            } catch (InterruptedException e) {
              throw Exceptions.propagate(e);
            }
            assertTrue(completionLatch.getCount() <= 0);
          }
        });

    if (exceptions.size() > 0) throw exceptions.get(0);
  }
 @AfterMethod(alwaysRun = true)
 public void tearDown() throws Exception {
   if (em != null) em.shutdownNow();
 }
示例#6
0
 /**
  * the {@link Task} where the current thread is executing, if executing in a Task, otherwise null
  */
 @SuppressWarnings("rawtypes")
 public static Task current() {
   return BasicExecutionManager.getPerThreadCurrentTask().get();
 }