Michael Blow has uploaded a new change for review.

  https://asterix-gerrit.ics.uci.edu/780

Change subject: BufferCache Concurrency Fixes
......................................................................

BufferCache Concurrency Fixes

1. Fix thread-safety issues in ClockPageReplacementStrategy.findVictimByEviction
2. Fix race-condition between page evicition & file deletion

Change-Id: Ife86104c5d1dde597e1a990b7207fda4d4bef039
---
M 
hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/BufferCache.java
M 
hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/ClockPageReplacementStrategy.java
M 
hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/IBufferCacheInternal.java
M 
hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/IPageReplacementStrategy.java
4 files changed, 70 insertions(+), 12 deletions(-)


  git pull ssh://asterix-gerrit.ics.uci.edu:29418/hyracks refs/changes/80/780/1

diff --git 
a/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/BufferCache.java
 
b/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/BufferCache.java
index 27d0423..0b80233 100644
--- 
a/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/BufferCache.java
+++ 
b/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/BufferCache.java
@@ -246,7 +246,7 @@
              * If we got here, the page was not in the hash table. Now we ask
              * the page replacement strategy to find us a victim.
              */
-            CachedPage victim = (CachedPage) 
pageReplacementStrategy.findVictim();
+            CachedPage victim = (CachedPage) 
pageReplacementStrategy.findVictim(dpid);
             if (victim != null) {
                 /*
                  * We have a victim with the following invariants. 1. The dpid
@@ -956,6 +956,52 @@
     }
 
     @Override
+    public boolean pinIfGoodVictim(ICachedPageInternal cPage, long newDpid) {
+        CachedPage victim = (CachedPage)cPage;
+        long dpid = victim.getDiskPageId();
+        if (dpid < 0 || BufferedFileHandle.getFileId(dpid) == 
BufferedFileHandle.getFileId(newDpid)) {
+            return victim.pinIfGoodVictim();
+        } else {
+            // prevent race condition with invalidateIfFileIdMatch, lock 
bucket before pinning, invalidate dpid
+            // before unlock
+            int pageHash = hash(victim.getDiskPageId());
+            CacheBucket bucket = pageMap[pageHash];
+            bucket.bucketLock.lock();
+            try {
+                if (victim.pinIfGoodVictim()) {
+                    boolean found = false;
+                    if (bucket.cachedPage == victim) {
+                        bucket.cachedPage = victim.next;
+                        found = true;
+                    } else {
+                        CachedPage prev = bucket.cachedPage;
+                        CachedPage curr = bucket.cachedPage.next;
+                        // traverse the bucket's linked list to find the 
victim.
+                        while (curr != null) {
+                            if (curr == victim) { // we found where the victim 
resides in the hash table
+                            // if this is the first page in the bucket
+                                prev.next = curr.next;
+                                curr.next = null;
+                                found = true;
+                                break;
+                            }
+                            // go to the next entry
+                            prev = curr;
+                            curr = curr.next;
+                        }
+                    }
+                    assert found;
+                    victim.dpid = -1;
+                    return true;
+                }
+            } finally {
+                bucket.bucketLock.unlock();
+            }
+        }
+        return false;
+    }
+
+    @Override
     public void dumpState(OutputStream os) throws IOException {
         os.write(dumpState().getBytes());
     }
@@ -984,7 +1030,7 @@
         while (true) {
             int startCleanedCount = cleanerThread.cleanedCount;
             ICachedPage returnPage = null;
-            CachedPage victim = (CachedPage) 
pageReplacementStrategy.findVictim();
+            CachedPage victim = (CachedPage) 
pageReplacementStrategy.findVictim(dpid);
             if (victim != null) {
                 if(DEBUG) {
                     assert !victim.confiscated.get();
diff --git 
a/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/ClockPageReplacementStrategy.java
 
b/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/ClockPageReplacementStrategy.java
index 6a82b97..0d205cd 100644
--- 
a/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/ClockPageReplacementStrategy.java
+++ 
b/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/ClockPageReplacementStrategy.java
@@ -62,23 +62,28 @@
     }
 
     @Override
-    public ICachedPageInternal findVictim() {
+    public ICachedPageInternal findVictim(long newDpid) {
         ICachedPageInternal cachedPage = null;
         if (numPages.get() >= maxAllowedNumPages) {
-            cachedPage = findVictimByEviction();
+            cachedPage = findVictimByEviction(newDpid);
         } else {
             cachedPage = allocatePage();
         }
         return cachedPage;
     }
 
-    private ICachedPageInternal findVictimByEviction() {
+    private ICachedPageInternal findVictimByEviction(long newDpid) {
         //check if we're starved from confiscation
         assert (maxAllowedNumPages > 0);
-        int startClockPtr = clockPtr.get();
+        int startClockPtr = -1;
+        int clockPtr = -1;
+        int lastClockPtr;
         int cycleCount = 0;
+        boolean looped = false;
         do {
-            ICachedPageInternal cPage = bufferCache.getPage(clockPtr.get());
+            lastClockPtr = clockPtr;
+            clockPtr = advanceClock();
+            ICachedPageInternal cPage = bufferCache.getPage(clockPtr);
 
             /*
              * We do two things here:
@@ -90,13 +95,18 @@
              */
             AtomicBoolean accessedFlag = getPerPageObject(cPage);
             if (!accessedFlag.compareAndSet(true, false)) {
-                if (cPage.pinIfGoodVictim()) {
-                        return cPage;
+                if (bufferCache.pinIfGoodVictim(cPage, newDpid)) {
+                    return cPage;
                 }
             }
-            advanceClock();
-            if (clockPtr.get() == startClockPtr) {
+
+            if (startClockPtr == -1) {
+                startClockPtr = clockPtr;
+            } else if (clockPtr < lastClockPtr) {
+                looped = true;
+            } else if (looped && clockPtr >= startClockPtr) {
                 ++cycleCount;
+                looped = false;
             }
         } while (cycleCount < MAX_UNSUCCESSFUL_CYCLE_COUNT);
         return null;
diff --git 
a/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/IBufferCacheInternal.java
 
b/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/IBufferCacheInternal.java
index ec05542..f3dc8a4 100644
--- 
a/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/IBufferCacheInternal.java
+++ 
b/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/IBufferCacheInternal.java
@@ -24,4 +24,6 @@
     public ICachedPageInternal getPage(int cpid);
 
     public void addPage(ICachedPageInternal page);
+
+    boolean pinIfGoodVictim(ICachedPageInternal cPage, long newDpid);
 }
diff --git 
a/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/IPageReplacementStrategy.java
 
b/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/IPageReplacementStrategy.java
index 661d363..be1ae37 100644
--- 
a/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/IPageReplacementStrategy.java
+++ 
b/hyracks/hyracks-storage-common/src/main/java/org/apache/hyracks/storage/common/buffercache/IPageReplacementStrategy.java
@@ -29,7 +29,7 @@
 
     public void adviseWontNeed(ICachedPageInternal cPage);
 
-    public ICachedPageInternal findVictim();
+    public ICachedPageInternal findVictim(long newDpid);
 
     public int getNumPages();
 

-- 
To view, visit https://asterix-gerrit.ics.uci.edu/780
To unsubscribe, visit https://asterix-gerrit.ics.uci.edu/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ife86104c5d1dde597e1a990b7207fda4d4bef039
Gerrit-PatchSet: 1
Gerrit-Project: hyracks
Gerrit-Branch: master
Gerrit-Owner: Michael Blow <[email protected]>

Reply via email to