private void AbortPageFault(Exception throwable, int[] chunk, long chunkOffset, LatchMap.Latch latch, PageFaultEvent faultEvent) { UnsafeUtil.putIntVolatile(chunk, chunkOffset, UNMAPPED_TTE); latch.Release(); faultEvent.Done(throwable); PinEvent.done(); }
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: //ORIGINAL LINE: private boolean uncommonPin(long filePageId, long chunkOffset, int[] chunk) throws java.io.IOException private bool UncommonPin(long filePageId, long chunkOffset, int[] chunk) { if (NoFault) { // The only page state that needs to be cleared is the currentPageId, since it was set prior to pin. CurrentPageIdConflict = UNBOUND_PAGE_ID; return(true); } // Looks like there's no mapping, so we'd like to do a page fault. LatchMap.Latch latch = PagedFile.pageFaultLatches.takeOrAwaitLatch(filePageId); if (latch != null) { // We managed to inject our latch, so we now own the right to perform the page fault. We also // have a duty to eventually release and remove the latch, no matter what happens now. // However, we first have to double-check that a page fault did not complete in-between our initial // check in the translation table, and us getting a latch. if (UnsafeUtil.getIntVolatile(chunk, chunkOffset) == UNMAPPED_TTE) { // Sweet, we didn't race with any other fault on this translation table entry. long pageRef = PageFault(filePageId, Swapper, chunkOffset, chunk, latch); PinCursorToPage(pageRef, filePageId, Swapper); return(true); } // Oops, looks like we raced with another page fault on this file page. // Let's release our latch and retry the pin. latch.Release(); } // We found a latch, so someone else is already doing a page fault for this page. // The `takeOrAwaitLatch` already waited for this latch to be released on our behalf, // so now we just have to do another iteration of the loop to see what's in the translation table now. return(false); }
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: //ORIGINAL LINE: private long pageFault(long filePageId, org.neo4j.io.pagecache.PageSwapper swapper, long chunkOffset, int[] chunk, LatchMap.Latch latch) throws java.io.IOException private long PageFault(long filePageId, PageSwapper swapper, long chunkOffset, int[] chunk, LatchMap.Latch latch) { // We are page faulting. This is a critical time, because we currently have the given latch in the chunk array // slot that we are faulting into. We MUST make sure to release that latch, and remove it from the chunk, no // matter what happens. Otherwise other threads will get stuck waiting forever for our page fault to finish. // If we manage to get a free page to fault into, then we will also be taking a write lock on that page, to // protect it against concurrent eviction as we assigning a binding to the page. If anything goes wrong, then // we must make sure to release that write lock as well. PageFaultEvent faultEvent = PinEvent.beginPageFault(); long pageRef; try { // The grabFreePage method might throw. pageRef = PagedFile.grabFreeAndExclusivelyLockedPage(faultEvent); // We got a free page, and we know that we have race-free access to it. Well, it's not entirely race // free, because other paged files might have it in their translation tables (or rather, their reads of // their translation tables might race with eviction) and try to pin it. // However, they will all fail because when they try to pin, because the page will be exclusively locked // and possibly bound to our page. } catch (Exception throwable) { // Make sure to unstuck the page fault latch. AbortPageFault(throwable, chunk, chunkOffset, latch, faultEvent); throw throwable; } try { // Check if we're racing with unmapping. We have the page lock // here, so the unmapping would have already happened. We do this // check before page.fault(), because that would otherwise reopen // the file channel. AssertPagedFileStillMappedAndGetIdOfLastPage(); PagedFile.initBuffer(pageRef); PagedFile.fault(pageRef, swapper, PagedFile.swapperId, filePageId, faultEvent); } catch (Exception throwable) { // Make sure to unlock the page, so the eviction thread can pick up our trash. PagedFile.unlockExclusive(pageRef); // Make sure to unstuck the page fault latch. AbortPageFault(throwable, chunk, chunkOffset, latch, faultEvent); throw throwable; } // Put the page in the translation table before we undo the exclusive lock, as we could otherwise race with // eviction, and the onEvict callback expects to find a MuninnPage object in the table. UnsafeUtil.putIntVolatile(chunk, chunkOffset, PagedFile.toId(pageRef)); // Once we page has been published to the translation table, we can convert our exclusive lock to whatever we // need for the page cursor. ConvertPageFaultLock(pageRef); latch.Release(); faultEvent.Done(); return(pageRef); }