Search in sources :

Example 1 with InvalidationState

use of com.google.devtools.build.skyframe.InvalidatingNodeVisitor.InvalidationState in project bazel by bazelbuild.

the class EagerInvalidatorTest method interruptChild.

@Test
public void interruptChild() throws Exception {
    graph = new InMemoryGraphImpl();
    // More values than the invalidator has threads.
    int numValues = 50;
    final SkyKey[] family = new SkyKey[numValues];
    final SkyKey child = GraphTester.skyKey("child");
    final StringValue childValue = new StringValue("child");
    tester.set(child, childValue);
    family[0] = child;
    for (int i = 1; i < numValues; i++) {
        SkyKey member = skyKey(Integer.toString(i));
        tester.getOrCreate(member).addDependency(family[i - 1]).setComputedValue(CONCATENATE);
        family[i] = member;
    }
    SkyKey parent = GraphTester.skyKey("parent");
    tester.getOrCreate(parent).addDependency(family[numValues - 1]).setComputedValue(CONCATENATE);
    eval(/*keepGoing=*/
    false, parent);
    final Thread mainThread = Thread.currentThread();
    final AtomicReference<SkyKey> badKey = new AtomicReference<>();
    DirtyTrackingProgressReceiver receiver = new DirtyTrackingProgressReceiver(new EvaluationProgressReceiver() {

        @Override
        public void invalidated(SkyKey skyKey, InvalidationState state) {
            if (skyKey.equals(child)) {
                // Interrupt on the very first invalidate
                mainThread.interrupt();
            } else if (!skyKey.functionName().equals(NODE_TYPE)) {
                // All other invalidations should have the GraphTester's key type.
                // Exceptions thrown here may be silently dropped, so keep track of errors ourselves.
                badKey.set(skyKey);
            }
            try {
                assertTrue(visitor.get().getInterruptionLatchForTestingOnly().await(2, TimeUnit.HOURS));
            } catch (InterruptedException e) {
            // We may well have thrown here because by the time we try to await, the main
            // thread is already interrupted.
            }
        }

        @Override
        public void enqueueing(SkyKey skyKey) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void computed(SkyKey skyKey, long elapsedTimeNanos) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void evaluated(SkyKey skyKey, Supplier<SkyValue> skyValueSupplier, EvaluationState state) {
            throw new UnsupportedOperationException();
        }
    });
    try {
        invalidateWithoutError(receiver, child);
        fail();
    } catch (InterruptedException e) {
    // Expected.
    }
    assertNull(badKey.get());
    assertFalse(state.isEmpty());
    final Set<SkyKey> invalidated = Sets.newConcurrentHashSet();
    assertFalse(isInvalidated(parent));
    assertNotNull(graph.get(null, Reason.OTHER, parent).getValue());
    receiver = new DirtyTrackingProgressReceiver(new EvaluationProgressReceiver() {

        @Override
        public void invalidated(SkyKey skyKey, InvalidationState state) {
            invalidated.add(skyKey);
        }

        @Override
        public void enqueueing(SkyKey skyKey) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void computed(SkyKey skyKey, long elapsedTimeNanos) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void evaluated(SkyKey skyKey, Supplier<SkyValue> skyValueSupplier, EvaluationState state) {
            throw new UnsupportedOperationException();
        }
    });
    invalidateWithoutError(receiver);
    assertTrue(invalidated.contains(parent));
    assertThat(state.getInvalidationsForTesting()).isEmpty();
    // Regression test coverage:
    // "all pending values are marked changed on interrupt".
    assertTrue(isInvalidated(child));
    assertChanged(child);
    for (int i = 1; i < numValues; i++) {
        assertDirtyAndNotChanged(family[i]);
    }
    assertDirtyAndNotChanged(parent);
}
Also used : AtomicReference(java.util.concurrent.atomic.AtomicReference) DirtyingInvalidationState(com.google.devtools.build.skyframe.InvalidatingNodeVisitor.DirtyingInvalidationState) InvalidationState(com.google.devtools.build.skyframe.InvalidatingNodeVisitor.InvalidationState) Supplier(com.google.common.base.Supplier) StringValue(com.google.devtools.build.skyframe.GraphTester.StringValue) Test(org.junit.Test)

Example 2 with InvalidationState

use of com.google.devtools.build.skyframe.InvalidatingNodeVisitor.InvalidationState in project bazel by bazelbuild.

the class EagerInvalidatorTest method interruptThreadInReceiver.

@Test
public void interruptThreadInReceiver() throws Exception {
    Random random = new Random(TestUtils.getRandomSeed());
    int graphSize = 1000;
    int tries = 5;
    graph = new InMemoryGraphImpl();
    SkyKey[] values = constructLargeGraph(graphSize);
    eval(/*keepGoing=*/
    false, values);
    final Thread mainThread = Thread.currentThread();
    for (int run = 0; run < tries; run++) {
        Set<Pair<SkyKey, InvalidationType>> valuesToInvalidate = getValuesToInvalidate(values);
        // Find how many invalidations will actually be enqueued for invalidation in the first round,
        // so that we can interrupt before all of them are done.
        int validValuesToDo = Sets.difference(valuesToInvalidate, state.getInvalidationsForTesting()).size();
        for (Pair<SkyKey, InvalidationType> pair : state.getInvalidationsForTesting()) {
            if (!isInvalidated(pair.first)) {
                validValuesToDo++;
            }
        }
        int countDownStart = validValuesToDo > 0 ? random.nextInt(validValuesToDo) : 0;
        final CountDownLatch countDownToInterrupt = new CountDownLatch(countDownStart);
        final DirtyTrackingProgressReceiver receiver = new DirtyTrackingProgressReceiver(new EvaluationProgressReceiver() {

            @Override
            public void invalidated(SkyKey skyKey, InvalidationState state) {
                countDownToInterrupt.countDown();
                if (countDownToInterrupt.getCount() == 0) {
                    mainThread.interrupt();
                    // Wait for the main thread to be interrupted uninterruptibly, because the main
                    // thread is going to interrupt us, and we don't want to get into an interrupt
                    // fight. Only if we get interrupted without the main thread also being interrupted
                    // will this throw an InterruptedException.
                    TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(visitor.get().getInterruptionLatchForTestingOnly(), "Main thread was not interrupted");
                }
            }

            @Override
            public void enqueueing(SkyKey skyKey) {
                throw new UnsupportedOperationException();
            }

            @Override
            public void computed(SkyKey skyKey, long elapsedTimeNanos) {
                throw new UnsupportedOperationException();
            }

            @Override
            public void evaluated(SkyKey skyKey, Supplier<SkyValue> skyValueSupplier, EvaluationState state) {
                throw new UnsupportedOperationException();
            }
        });
        try {
            invalidate(graph, receiver, Sets.newHashSet(Iterables.transform(valuesToInvalidate, Pair.<SkyKey, InvalidationType>firstFunction())).toArray(new SkyKey[0]));
            assertThat(state.getInvalidationsForTesting()).isEmpty();
        } catch (InterruptedException e) {
        // Expected.
        }
        if (state.isEmpty()) {
            // Ran out of values to invalidate.
            break;
        }
    }
    eval(/*keepGoing=*/
    false, values);
}
Also used : InvalidationType(com.google.devtools.build.skyframe.InvalidatingNodeVisitor.InvalidationType) CountDownLatch(java.util.concurrent.CountDownLatch) Random(java.util.Random) DirtyingInvalidationState(com.google.devtools.build.skyframe.InvalidatingNodeVisitor.DirtyingInvalidationState) InvalidationState(com.google.devtools.build.skyframe.InvalidatingNodeVisitor.InvalidationState) Pair(com.google.devtools.build.lib.util.Pair) Test(org.junit.Test)

Aggregations

DirtyingInvalidationState (com.google.devtools.build.skyframe.InvalidatingNodeVisitor.DirtyingInvalidationState)2 InvalidationState (com.google.devtools.build.skyframe.InvalidatingNodeVisitor.InvalidationState)2 Test (org.junit.Test)2 Supplier (com.google.common.base.Supplier)1 Pair (com.google.devtools.build.lib.util.Pair)1 StringValue (com.google.devtools.build.skyframe.GraphTester.StringValue)1 InvalidationType (com.google.devtools.build.skyframe.InvalidatingNodeVisitor.InvalidationType)1 Random (java.util.Random)1 CountDownLatch (java.util.concurrent.CountDownLatch)1 AtomicReference (java.util.concurrent.atomic.AtomicReference)1