/**
   * Runs the same model many times and ensures it is not creating many threads which would finish
   * blocking the JVM
   */
  @Test
  public void testModelUsageOfThreads() {

    // first runs after which the reference will be taken
    final int HEATING_COUNT = 2;
    final int TEST_COUNT = 10;

    // heading period
    for (int i = 0; i < HEATING_COUNT; i++) runModel();

    // take reference
    final int activeThreads = Thread.activeCount();
    final Set<Thread> activeThreadsSet = collectCurrentThreads();

    // run many
    for (int i = 0; i < TEST_COUNT; i++) {
      System.err.println("exec " + i + " threads " + Thread.activeCount());
      runModel();
    }

    if (Thread.activeCount() > activeThreads) {
      double nbPerIteration = Thread.activeCount() / TEST_COUNT;
      Set<Thread> threadsNow = collectCurrentThreads();
      threadsNow.removeAll(activeThreadsSet);
      for (Thread t : threadsNow) {
        System.err.println("extra thread: " + t);
        t.stop();
      }
      Thread.yield();
      System.out.println("did cleaning help ? " + Thread.activeCount() + " / " + activeThreads);
      threadsNow = collectCurrentThreads();
      threadsNow.removeAll(activeThreadsSet);
      for (Thread t : threadsNow) {
        System.out.println("extra thread: " + t);
      }
      fail(
          "about "
              + nbPerIteration
              + " novel threads are created at each run; this cannot be used in production");
    }
  }
Example #2
0
  @Test
  public void recover_with_interrupt() throws InterruptedException {
    int scale = TT.scale();
    if (scale == 0) return;
    e = openEngine();
    if (!e.canRollback()
        || e instanceof StoreHeap) // TODO engine might have crash recovery, but no rollbacks
    return;

    // fill recids
    final int max = scale * 1000;
    final ArrayList<Long> recids = new ArrayList<Long>();
    final AtomicLong a = new AtomicLong(10);
    final long counterRecid = e.put(a.get(), Serializer.LONG);
    Random r = new Random(a.get());
    for (int j = 0; j < max; j++) {
      byte[] b = new byte[r.nextInt(100000)];
      r.nextBytes(b);
      long recid = e.put(b, Serializer.BYTE_ARRAY_NOSIZE);
      recids.add(recid);
    }

    e.commit();

    long endTime = TT.nowPlusMinutes(10);

    while (endTime > System.currentTimeMillis()) {

      final CountDownLatch latch = new CountDownLatch(1);
      Thread t =
          new Thread() {
            @Override
            public void run() {
              try {
                for (; ; ) {
                  long A = a.incrementAndGet();
                  Random r = new Random(A);
                  e.update(counterRecid, A, Serializer.LONG);

                  for (long recid : recids) {
                    byte[] b = new byte[r.nextInt(100000)];
                    r.nextBytes(b);
                    e.update(recid, b, Serializer.BYTE_ARRAY_NOSIZE);
                  }
                  e.commit();
                }
              } finally {
                latch.countDown();
              }
            }
          };
      t.start();
      Thread.sleep(5000);
      t.stop();
      latch.await();
      if (!e.isClosed()) {
        close();
      }

      // reopen and check the content
      e = openEngine();

      // check if A-1 was commited
      long A = e.get(counterRecid, Serializer.LONG);
      assertTrue("" + A + " - " + a.get(), A == a.get() || A == a.get() - 1);
      r = new Random(A);
      for (long recid : recids) {
        byte[] b = new byte[r.nextInt(100000)];
        r.nextBytes(b);
        byte[] b2 = e.get(recid, Serializer.BYTE_ARRAY_NOSIZE);
        assertTrue("Data were not commited recid=" + recid, Arrays.equals(b, b2));
      }
      a.set(A);
    }
    e.close();
  }