Add method to check state of buffer cache

Change-Id: I80fb891b5310252143854a336b591bf3f8cd4ba8
Reviewed-on: https://asterix-gerrit.ics.uci.edu/497
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Murtadha Hubail <hubailmor@gmail.com>
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 3a23c8d..f66726b 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
@@ -20,12 +20,7 @@
 
 import java.io.IOException;
 import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
@@ -487,6 +482,49 @@
         return buffer.toString();
     }
 
+    @Override
+    public boolean isClean(){
+        List<Long> reachableDpids = new LinkedList<>();
+        synchronized (cachedPages) {
+            for (ICachedPageInternal internalPage : cachedPages) {
+            CachedPage c = (CachedPage) internalPage;
+                if (c.confiscated() ||
+                        c.latch.getReadLockCount() != 0 || c.latch.getWriteHoldCount() != 0) {
+                    return false;
+                }
+                if(c.valid){
+                    reachableDpids.add(c.dpid);
+                }
+            }
+        }
+        for(Long l: reachableDpids){
+            if(!canFindValidCachedPage(l)){
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private boolean canFindValidCachedPage(long dpid){
+        int hash = hash(dpid);
+        CachedPage cPage = null;
+        CacheBucket bucket = pageMap[hash];
+        bucket.bucketLock.lock();
+        try {
+            cPage = bucket.cachedPage;
+            while (cPage != null) {
+                assert bucket.cachedPage != bucket.cachedPage.next;
+                if (cPage.dpid == dpid) {
+                    return true;
+                }
+                cPage = cPage.next;
+            }
+        } finally {
+            bucket.bucketLock.unlock();
+        }
+        return false;
+    }
+
     private void read(CachedPage cPage) throws HyracksDataException {
         BufferedFileHandle fInfo = getFileInfo(cPage);
         cPage.buffer.clear();
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 7c9f01f..01f06d8 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
@@ -19,6 +19,8 @@
 package org.apache.hyracks.storage.common.buffercache;
 
 public interface IBufferCacheInternal extends IBufferCache {
+    boolean isClean();
+
     public ICachedPageInternal getPage(int cpid);
 
     public void addPage(ICachedPageInternal page);