Exemple #1
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: private void verifyUpdateResults(int filePages, PagedFile pagedFile, java.util.List<java.util.concurrent.Future<UpdateResult>> futures) throws InterruptedException, java.util.concurrent.ExecutionException, java.io.IOException
        private void VerifyUpdateResults(int filePages, PagedFile pagedFile, IList <Future <UpdateResult> > futures)
        {
            UpdateResult[] results = new UpdateResult[futures.Count];
            for (int i = 0; i < results.Length; i++)
            {
                results[i] = futures[i].get();
            }
            foreach (UpdateResult result in results)
            {
                using (PageCursor cursor = pagedFile.Io(0, PF_SHARED_READ_LOCK))
                {
                    for (int i = 0; i < filePages; i++)
                    {
                        assertTrue(cursor.Next());

                        int threadId      = result.ThreadId;
                        int expectedCount = result.PageCounts[i];
                        int actualCount;
                        do
                        {
                            cursor.Offset = threadId * 4;
                            actualCount   = cursor.Int;
                        } while (cursor.ShouldRetry());

                        assertThat("wrong count for threadId:" + threadId + ", aka. real threadId:" + result.RealThreadId + ", filePageId:" + i, actualCount, @is(expectedCount));
                    }
                }
            }
        }
Exemple #2
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: private void verifyAdversarialPagedContent(PagedFile pagedFile) throws java.io.IOException
        private void VerifyAdversarialPagedContent(PagedFile pagedFile)
        {
            using (PageCursor cursor = pagedFile.Io(0, PF_SHARED_READ_LOCK))
            {
                while (cursor.Next())
                {
                    ReadAndVerifyAdversarialPage(cursor, pagedFile.PageSize());
                }
            }
        }
Exemple #3
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: private void performConsistentAdversarialRead(PageCursor cursor, long maxPageId, long startingPage, int pageSize) throws java.io.IOException
        private void PerformConsistentAdversarialRead(PageCursor cursor, long maxPageId, long startingPage, int pageSize)
        {
            long pagesToLookAt = Math.Min(maxPageId, startingPage + 3) - startingPage + 1;

            for (int j = 0; j < pagesToLookAt; j++)
            {
                assertTrue(cursor.Next());
                ReadAndVerifyAdversarialPage(cursor, pageSize);
            }
        }
Exemple #4
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: private void ensureAllPagesExists(int filePages, PagedFile pagedFile) throws java.io.IOException
        private void EnsureAllPagesExists(int filePages, PagedFile pagedFile)
        {
            using (PageCursor cursor = pagedFile.Io(0, PF_SHARED_WRITE_LOCK))
            {
                for (int i = 0; i < filePages; i++)
                {
                    assertTrue(cursor.Next(), "failed to initialise file page " + i);
                }
            }
            pageCache.flushAndForce();
        }
Exemple #5
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: private void performConsistentAdversarialWrite(PageCursor cursor, java.util.concurrent.ThreadLocalRandom rng, int pageSize) throws java.io.IOException
        private void PerformConsistentAdversarialWrite(PageCursor cursor, ThreadLocalRandom rng, int pageSize)
        {
            for (int j = 0; j < 3; j++)
            {
                assertTrue(cursor.Next());
                // Avoid generating zeros, so we can tell them apart from the
                // absence of a write:
                sbyte b = ( sbyte )rng.Next(1, 127);
                for (int k = 0; k < pageSize; k++)
                {
                    cursor.PutByte(b);
                }
                assertFalse(cursor.ShouldRetry());
            }
        }
Exemple #6
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test void mustNotRunOutOfSwapperAllocationSpace() throws Exception
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        internal virtual void MustNotRunOutOfSwapperAllocationSpace()
        {
            assumeTrue(fs is EphemeralFileSystemAbstraction, "This test is file system agnostic, and too slow on a real file system");
            configureStandardPageCache();

            File file       = file("a");
            int  iterations = short.MaxValue * 3;

            for (int i = 0; i < iterations; i++)
            {
                PagedFile pagedFile = pageCache.map(file, filePageSize);
                using (PageCursor cursor = pagedFile.Io(0, PF_SHARED_WRITE_LOCK))
                {
                    assertTrue(cursor.Next());
                }
                pagedFile.Close();
            }
        }
Exemple #7
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: protected void performReadOrUpdate(java.util.concurrent.ThreadLocalRandom rng, boolean updateCounter, int pf_flags) throws java.io.IOException
            protected internal override void performReadOrUpdate(ThreadLocalRandom rng, bool updateCounter, int pfFlags)
            {
                int pageId = rng.Next(0, _filePages);

                using (PageCursor cursor = _pagedFile.io(pageId, pfFlags))
                {
                    int counter;
                    try
                    {
                        assertTrue(cursor.Next());
                        do
                        {
                            cursor.Offset = offset;
                            counter       = cursor.Int;
                        } while (cursor.ShouldRetry());
                        string lockName = updateCounter ? "PF_SHARED_WRITE_LOCK" : "PF_SHARED_READ_LOCK";
                        string reason   = string.Format("inconsistent page read from filePageId:{0}, with {1}, threadId:{2}", pageId, lockName, Thread.CurrentThread.Id);
                        assertThat(reason, counter, @is(pageCounts[pageId]));
                    }
                    catch (Exception throwable)
                    {
                        _shouldStop.set(true);
                        throw throwable;
                    }
                    if (updateCounter)
                    {
                        counter++;
                        pageCounts[pageId]++;
                        cursor.Offset = offset;
                        cursor.PutInt(counter);
                    }
                    if (cursor.CheckAndClearBoundsFlag())
                    {
                        _shouldStop.set(true);
                        throw new System.IndexOutOfRangeException("offset = " + offset + ", filPageId:" + pageId + ", threadId: " + threadId + ", updateCounter = " + updateCounter);
                    }
                }
            }
Exemple #8
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @RepeatedTest(20) void pageCacheMustRemainInternallyConsistentWhenGettingRandomFailures()
        internal virtual void PageCacheMustRemainInternallyConsistentWhenGettingRandomFailures()
        {
            assertTimeout(ofMillis(LONG_TIMEOUT_MILLIS), () =>
            {
                // NOTE: This test is inherently non-deterministic. This means that every failure must be
                // thoroughly investigated, since they have a good chance of being a real issue.
                // This is effectively a targeted robustness test.

                RandomAdversary adversary   = new RandomAdversary(0.5, 0.2, 0.2);
                adversary.ProbabilityFactor = 0.0;
                FileSystemAbstraction fs    = new AdversarialFileSystemAbstraction(adversary, this.fs);
                ThreadLocalRandom rng       = ThreadLocalRandom.current();

                // Because our test failures are non-deterministic, we use this tracer to capture a full history of the
                // events leading up to any given failure.
                LinearTracers linearTracers = LinearHistoryTracerFactory.pageCacheTracer();
                getPageCache(fs, maxPages, linearTracers.PageCacheTracer, linearTracers.CursorTracerSupplier);

                PagedFile pfA = pageCache.map(existingFile("a"), filePageSize);
                PagedFile pfB = pageCache.map(existingFile("b"), filePageSize / 2 + 1);
                adversary.ProbabilityFactor = 1.0;

                for (int i = 0; i < 1000; i++)
                {
                    PagedFile pagedFile = rng.nextBoolean() ? pfA : pfB;
                    long maxPageId      = pagedFile.LastPageId;
                    bool performingRead = rng.nextBoolean() && maxPageId != -1;
                    long startingPage   = maxPageId < 0 ? 0 : rng.nextLong(maxPageId + 1);
                    int pfFlags         = performingRead ? PF_SHARED_READ_LOCK : PF_SHARED_WRITE_LOCK;
                    int pageSize        = pagedFile.PageSize();

                    try
                    {
                        using (PageCursor cursor = pagedFile.Io(startingPage, pfFlags))
                        {
                            if (performingRead)
                            {
                                PerformConsistentAdversarialRead(cursor, maxPageId, startingPage, pageSize);
                            }
                            else
                            {
                                PerformConsistentAdversarialWrite(cursor, rng, pageSize);
                            }
                        }
                    }
                    catch (AssertionError error)
                    {
                        // Capture any exception that might have hit the eviction thread.
                        adversary.ProbabilityFactor = 0.0;
                        try
                        {
                            using (PageCursor cursor = pagedFile.Io(0, PF_SHARED_WRITE_LOCK))
                            {
                                for (int j = 0; j < 100; j++)
                                {
                                    cursor.Next(rng.nextLong(maxPageId + 1));
                                }
                            }
                        }
                        catch (Exception throwable)
                        {
                            error.addSuppressed(throwable);
                        }

                        throw error;
                    }
                    catch (Exception)
                    {
                        // Don't worry about it... it's fine!
//                throwable.printStackTrace(); // only enable this when debugging test failures.
                    }
                }

                // Unmapping will cause pages to be flushed.
                // We don't want that to fail, since it will upset the test tear-down.
                adversary.ProbabilityFactor = 0.0;
                try
                {
                    // Flushing all pages, if successful, should clear any internal
                    // exception.
                    pageCache.flushAndForce();

                    // Do some post-chaos verification of what has been written.
                    VerifyAdversarialPagedContent(pfA);
                    VerifyAdversarialPagedContent(pfB);

                    pfA.Close();
                    pfB.Close();
                }
                catch (Exception e)
                {
                    linearTracers.printHistory(System.err);
                    throw e;
                }
            });
        }
Exemple #9
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @RepeatedTest(50) void writeLockingCursorMustThrowWhenLockingPageRacesWithUnmapping()
        internal virtual void WriteLockingCursorMustThrowWhenLockingPageRacesWithUnmapping()
        {
            assertTimeout(ofMillis(SEMI_LONG_TIMEOUT_MILLIS), () =>
            {
                // Even if we block in pin, waiting to grab a lock on a page that is
                // already locked, and the PagedFile is concurrently closed, then we
                // want to have an exception thrown, such that we race and get a
                // page that is writable after the PagedFile has been closed.
                // This is important because closing a PagedFile implies flushing, thus
                // ensuring that all changes make it to storage.
                // Conversely, we don't have to go to the same lengths for read locked
                // pages, because those are never changed. Not by us, anyway.

                File file = file("a");
                generateFileWithRecords(file, recordsPerFilePage * 2, recordSize);

                getPageCache(fs, maxPages, PageCacheTracer.NULL, PageCursorTracerSupplier.NULL);

                PagedFile pf = pageCache.map(file, filePageSize);
                System.Threading.CountdownEvent hasLockLatch             = new System.Threading.CountdownEvent(1);
                System.Threading.CountdownEvent unlockLatch              = new System.Threading.CountdownEvent(1);
                System.Threading.CountdownEvent secondThreadGotLockLatch = new System.Threading.CountdownEvent(1);
                AtomicBoolean doneWriteSignal = new AtomicBoolean();
                AtomicBoolean doneCloseSignal = new AtomicBoolean();

                executor.submit(() =>
                {
                    using (PageCursor cursor = pf.Io(0, PF_SHARED_WRITE_LOCK))
                    {
                        cursor.Next();
                        hasLockLatch.countDown();
                        unlockLatch.await();
                    }
                    return(null);
                });

                hasLockLatch.await();                 // A write lock is now held on page 0.

                Future <object> takeLockFuture = executor.submit(() =>
                {
                    using (PageCursor cursor = pf.Io(0, PF_SHARED_WRITE_LOCK))
                    {
                        cursor.Next();
                        doneWriteSignal.set(true);
                        secondThreadGotLockLatch.await();
                    }
                    return(null);
                });

                Future <object> closeFuture = executor.submit(() =>
                {
                    pf.Close();
                    doneCloseSignal.set(true);
                    return(null);
                });

                try
                {
                    Thread.yield();
                    closeFuture.get(50, TimeUnit.MILLISECONDS);
                    fail("Expected a TimeoutException here");
                }
                catch (TimeoutException)
                {
                    // As expected, the close cannot not complete while an write
                    // lock is held
                }

                // Now, both the close action and a grab for an write page lock is
                // waiting for our first thread.
                // When we release that lock, we should see that either close completes
                // and our second thread, the one blocked on the write lock, gets an
                // exception, or we should see that the second thread gets the lock,
                // and then close has to wait for that thread as well.

                unlockLatch.countDown();                 // The race is on.

                bool anyDone;
                do
                {
                    Thread.yield();
                    anyDone = doneWriteSignal.get() | doneCloseSignal.get();
                } while (!anyDone);

                if (doneCloseSignal.get())
                {
                    closeFuture.get(1000, TimeUnit.MILLISECONDS);
                    // The closeFuture got it first, so the takeLockFuture should throw.
                    try
                    {
                        secondThreadGotLockLatch.countDown();                           // only to prevent incorrect programs from deadlocking
                        takeLockFuture.get();
                        fail("Expected takeLockFuture.get() to throw an ExecutionException");
                    }
                    catch (ExecutionException e)
                    {
                        Exception cause = e.InnerException;
                        assertThat(cause, instanceOf(typeof(FileIsNotMappedException)));
                        assertThat(cause.Message, startsWith("File has been unmapped"));
                    }
                }
                else
                {
                    assertTrue(doneWriteSignal.get());
                    // The takeLockFuture got it first, so the closeFuture should
                    // complete when we release the latch.
                    secondThreadGotLockLatch.countDown();
                    closeFuture.get(20000, TimeUnit.MILLISECONDS);
                }
            });
        }