TEPHRA-230 Fix reading of saved regions during an invalid pruning run

This closes #43

Signed-off-by: poorna <poorna@apache.org>
diff --git a/tephra-hbase-compat-0.96/src/main/java/org/apache/tephra/hbase/txprune/DataJanitorState.java b/tephra-hbase-compat-0.96/src/main/java/org/apache/tephra/hbase/txprune/DataJanitorState.java
index 4345fe6..dcf5eb2 100644
--- a/tephra-hbase-compat-0.96/src/main/java/org/apache/tephra/hbase/txprune/DataJanitorState.java
+++ b/tephra-hbase-compat-0.96/src/main/java/org/apache/tephra/hbase/txprune/DataJanitorState.java
@@ -291,7 +291,7 @@
         } else {
           LOG.warn(String.format("Got incorrect count for regions saved at time %s, expected = %s but actual = %s",
                                  timeRegions.getTime(), count, timeRegions.getRegions().size()));
-          time = time - 1;
+          time = timeRegions.getTime() - 1;
         }
       }
       return null;
diff --git a/tephra-hbase-compat-0.96/src/test/java/org/apache/tephra/hbase/txprune/DataJanitorStateTest.java b/tephra-hbase-compat-0.96/src/test/java/org/apache/tephra/hbase/txprune/DataJanitorStateTest.java
index 14bf96c..525b80c 100644
--- a/tephra-hbase-compat-0.96/src/test/java/org/apache/tephra/hbase/txprune/DataJanitorStateTest.java
+++ b/tephra-hbase-compat-0.96/src/test/java/org/apache/tephra/hbase/txprune/DataJanitorStateTest.java
@@ -142,7 +142,7 @@
     Assert.assertEquals(expectedMap, dataJanitorState.getPruneUpperBoundForRegions(allRegions));
   }
 
-  @Test
+  @Test(timeout = 30000L) // The timeout is used to verify the fix for TEPHRA-230, the test will timeout without the fix
   public void testSaveRegionTime() throws Exception {
     int maxTime = 100;
 
@@ -169,16 +169,21 @@
                         dataJanitorState.getRegionsOnOrBeforeTime(maxTime + 1000));
     Assert.assertNull(dataJanitorState.getRegionsOnOrBeforeTime(-10));
 
-    // Now change the count stored for regions saved at time 0 and 30
+    // Now change the count stored for regions saved at time 0, 30 and 90
     try (HTableInterface stateTable = connection.getTable(pruneStateTable)) {
       dataJanitorState.saveRegionCountForTime(stateTable, Bytes.toBytes(Long.MAX_VALUE), 3);
       dataJanitorState.saveRegionCountForTime(stateTable, Bytes.toBytes(Long.MAX_VALUE - 30L), 3);
+      dataJanitorState.saveRegionCountForTime(stateTable, Bytes.toBytes(Long.MAX_VALUE - 90L), 0);
     }
+
     // Now querying for time 0 should return null, and querying for time 30 should return regions from time 20
     Assert.assertNull(dataJanitorState.getRegionsOnOrBeforeTime(0));
     Assert.assertEquals(new TimeRegions(20, regionsTime.get(20L)), dataJanitorState.getRegionsOnOrBeforeTime(30));
     Assert.assertEquals(new TimeRegions(20, regionsTime.get(20L)), dataJanitorState.getRegionsOnOrBeforeTime(35));
     Assert.assertEquals(new TimeRegions(20, regionsTime.get(20L)), dataJanitorState.getRegionsOnOrBeforeTime(25));
+    // Querying for anything higher than 90 should give 80 (reproduces TEPHRA-230)
+    Assert.assertEquals(new TimeRegions(80, regionsTime.get(80L)),
+                        dataJanitorState.getRegionsOnOrBeforeTime(Long.MAX_VALUE));
 
     // Delete regions saved on or before time 30
     dataJanitorState.deleteAllRegionsOnOrBeforeTime(30);
diff --git a/tephra-hbase-compat-0.98/src/main/java/org/apache/tephra/hbase/txprune/DataJanitorState.java b/tephra-hbase-compat-0.98/src/main/java/org/apache/tephra/hbase/txprune/DataJanitorState.java
index 4345fe6..dcf5eb2 100644
--- a/tephra-hbase-compat-0.98/src/main/java/org/apache/tephra/hbase/txprune/DataJanitorState.java
+++ b/tephra-hbase-compat-0.98/src/main/java/org/apache/tephra/hbase/txprune/DataJanitorState.java
@@ -291,7 +291,7 @@
         } else {
           LOG.warn(String.format("Got incorrect count for regions saved at time %s, expected = %s but actual = %s",
                                  timeRegions.getTime(), count, timeRegions.getRegions().size()));
-          time = time - 1;
+          time = timeRegions.getTime() - 1;
         }
       }
       return null;
diff --git a/tephra-hbase-compat-0.98/src/test/java/org/apache/tephra/hbase/txprune/DataJanitorStateTest.java b/tephra-hbase-compat-0.98/src/test/java/org/apache/tephra/hbase/txprune/DataJanitorStateTest.java
index 14bf96c..525b80c 100644
--- a/tephra-hbase-compat-0.98/src/test/java/org/apache/tephra/hbase/txprune/DataJanitorStateTest.java
+++ b/tephra-hbase-compat-0.98/src/test/java/org/apache/tephra/hbase/txprune/DataJanitorStateTest.java
@@ -142,7 +142,7 @@
     Assert.assertEquals(expectedMap, dataJanitorState.getPruneUpperBoundForRegions(allRegions));
   }
 
-  @Test
+  @Test(timeout = 30000L) // The timeout is used to verify the fix for TEPHRA-230, the test will timeout without the fix
   public void testSaveRegionTime() throws Exception {
     int maxTime = 100;
 
@@ -169,16 +169,21 @@
                         dataJanitorState.getRegionsOnOrBeforeTime(maxTime + 1000));
     Assert.assertNull(dataJanitorState.getRegionsOnOrBeforeTime(-10));
 
-    // Now change the count stored for regions saved at time 0 and 30
+    // Now change the count stored for regions saved at time 0, 30 and 90
     try (HTableInterface stateTable = connection.getTable(pruneStateTable)) {
       dataJanitorState.saveRegionCountForTime(stateTable, Bytes.toBytes(Long.MAX_VALUE), 3);
       dataJanitorState.saveRegionCountForTime(stateTable, Bytes.toBytes(Long.MAX_VALUE - 30L), 3);
+      dataJanitorState.saveRegionCountForTime(stateTable, Bytes.toBytes(Long.MAX_VALUE - 90L), 0);
     }
+
     // Now querying for time 0 should return null, and querying for time 30 should return regions from time 20
     Assert.assertNull(dataJanitorState.getRegionsOnOrBeforeTime(0));
     Assert.assertEquals(new TimeRegions(20, regionsTime.get(20L)), dataJanitorState.getRegionsOnOrBeforeTime(30));
     Assert.assertEquals(new TimeRegions(20, regionsTime.get(20L)), dataJanitorState.getRegionsOnOrBeforeTime(35));
     Assert.assertEquals(new TimeRegions(20, regionsTime.get(20L)), dataJanitorState.getRegionsOnOrBeforeTime(25));
+    // Querying for anything higher than 90 should give 80 (reproduces TEPHRA-230)
+    Assert.assertEquals(new TimeRegions(80, regionsTime.get(80L)),
+                        dataJanitorState.getRegionsOnOrBeforeTime(Long.MAX_VALUE));
 
     // Delete regions saved on or before time 30
     dataJanitorState.deleteAllRegionsOnOrBeforeTime(30);
diff --git a/tephra-hbase-compat-1.0-cdh/src/main/java/org/apache/tephra/hbase/txprune/DataJanitorState.java b/tephra-hbase-compat-1.0-cdh/src/main/java/org/apache/tephra/hbase/txprune/DataJanitorState.java
index fc0ec76..db59d7d 100644
--- a/tephra-hbase-compat-1.0-cdh/src/main/java/org/apache/tephra/hbase/txprune/DataJanitorState.java
+++ b/tephra-hbase-compat-1.0-cdh/src/main/java/org/apache/tephra/hbase/txprune/DataJanitorState.java
@@ -291,7 +291,7 @@
         } else {
           LOG.warn(String.format("Got incorrect count for regions saved at time %s, expected = %s but actual = %s",
                                  timeRegions.getTime(), count, timeRegions.getRegions().size()));
-          time = time - 1;
+          time = timeRegions.getTime() - 1;
         }
       }
       return null;
diff --git a/tephra-hbase-compat-1.0-cdh/src/test/java/org/apache/tephra/hbase/txprune/DataJanitorStateTest.java b/tephra-hbase-compat-1.0-cdh/src/test/java/org/apache/tephra/hbase/txprune/DataJanitorStateTest.java
index b96d87d..2e9dc17 100644
--- a/tephra-hbase-compat-1.0-cdh/src/test/java/org/apache/tephra/hbase/txprune/DataJanitorStateTest.java
+++ b/tephra-hbase-compat-1.0-cdh/src/test/java/org/apache/tephra/hbase/txprune/DataJanitorStateTest.java
@@ -137,7 +137,7 @@
     Assert.assertEquals(expectedMap, dataJanitorState.getPruneUpperBoundForRegions(allRegions));
   }
 
-  @Test
+  @Test(timeout = 30000L) // The timeout is used to verify the fix for TEPHRA-230, the test will timeout without the fix
   public void testSaveRegionTime() throws Exception {
     int maxTime = 100;
 
@@ -164,16 +164,21 @@
                         dataJanitorState.getRegionsOnOrBeforeTime(maxTime + 1000));
     Assert.assertNull(dataJanitorState.getRegionsOnOrBeforeTime(-10));
 
-    // Now change the count stored for regions saved at time 0 and 30
+    // Now change the count stored for regions saved at time 0, 30 and 90
     try (Table stateTable = testUtil.getConnection().getTable(pruneStateTable)) {
       dataJanitorState.saveRegionCountForTime(stateTable, Bytes.toBytes(Long.MAX_VALUE), 3);
       dataJanitorState.saveRegionCountForTime(stateTable, Bytes.toBytes(Long.MAX_VALUE - 30L), 3);
+      dataJanitorState.saveRegionCountForTime(stateTable, Bytes.toBytes(Long.MAX_VALUE - 90L), 0);
     }
+
     // Now querying for time 0 should return null, and querying for time 30 should return regions from time 20
     Assert.assertNull(dataJanitorState.getRegionsOnOrBeforeTime(0));
     Assert.assertEquals(new TimeRegions(20, regionsTime.get(20L)), dataJanitorState.getRegionsOnOrBeforeTime(30));
     Assert.assertEquals(new TimeRegions(20, regionsTime.get(20L)), dataJanitorState.getRegionsOnOrBeforeTime(35));
     Assert.assertEquals(new TimeRegions(20, regionsTime.get(20L)), dataJanitorState.getRegionsOnOrBeforeTime(25));
+    // Querying for anything higher than 90 should give 80 (reproduces TEPHRA-230)
+    Assert.assertEquals(new TimeRegions(80, regionsTime.get(80L)),
+                        dataJanitorState.getRegionsOnOrBeforeTime(Long.MAX_VALUE));
 
     // Delete regions saved on or before time 30
     dataJanitorState.deleteAllRegionsOnOrBeforeTime(30);
diff --git a/tephra-hbase-compat-1.0/src/main/java/org/apache/tephra/hbase/txprune/DataJanitorState.java b/tephra-hbase-compat-1.0/src/main/java/org/apache/tephra/hbase/txprune/DataJanitorState.java
index fc0ec76..db59d7d 100644
--- a/tephra-hbase-compat-1.0/src/main/java/org/apache/tephra/hbase/txprune/DataJanitorState.java
+++ b/tephra-hbase-compat-1.0/src/main/java/org/apache/tephra/hbase/txprune/DataJanitorState.java
@@ -291,7 +291,7 @@
         } else {
           LOG.warn(String.format("Got incorrect count for regions saved at time %s, expected = %s but actual = %s",
                                  timeRegions.getTime(), count, timeRegions.getRegions().size()));
-          time = time - 1;
+          time = timeRegions.getTime() - 1;
         }
       }
       return null;
diff --git a/tephra-hbase-compat-1.0/src/test/java/org/apache/tephra/hbase/txprune/DataJanitorStateTest.java b/tephra-hbase-compat-1.0/src/test/java/org/apache/tephra/hbase/txprune/DataJanitorStateTest.java
index b96d87d..2e9dc17 100644
--- a/tephra-hbase-compat-1.0/src/test/java/org/apache/tephra/hbase/txprune/DataJanitorStateTest.java
+++ b/tephra-hbase-compat-1.0/src/test/java/org/apache/tephra/hbase/txprune/DataJanitorStateTest.java
@@ -137,7 +137,7 @@
     Assert.assertEquals(expectedMap, dataJanitorState.getPruneUpperBoundForRegions(allRegions));
   }
 
-  @Test
+  @Test(timeout = 30000L) // The timeout is used to verify the fix for TEPHRA-230, the test will timeout without the fix
   public void testSaveRegionTime() throws Exception {
     int maxTime = 100;
 
@@ -164,16 +164,21 @@
                         dataJanitorState.getRegionsOnOrBeforeTime(maxTime + 1000));
     Assert.assertNull(dataJanitorState.getRegionsOnOrBeforeTime(-10));
 
-    // Now change the count stored for regions saved at time 0 and 30
+    // Now change the count stored for regions saved at time 0, 30 and 90
     try (Table stateTable = testUtil.getConnection().getTable(pruneStateTable)) {
       dataJanitorState.saveRegionCountForTime(stateTable, Bytes.toBytes(Long.MAX_VALUE), 3);
       dataJanitorState.saveRegionCountForTime(stateTable, Bytes.toBytes(Long.MAX_VALUE - 30L), 3);
+      dataJanitorState.saveRegionCountForTime(stateTable, Bytes.toBytes(Long.MAX_VALUE - 90L), 0);
     }
+
     // Now querying for time 0 should return null, and querying for time 30 should return regions from time 20
     Assert.assertNull(dataJanitorState.getRegionsOnOrBeforeTime(0));
     Assert.assertEquals(new TimeRegions(20, regionsTime.get(20L)), dataJanitorState.getRegionsOnOrBeforeTime(30));
     Assert.assertEquals(new TimeRegions(20, regionsTime.get(20L)), dataJanitorState.getRegionsOnOrBeforeTime(35));
     Assert.assertEquals(new TimeRegions(20, regionsTime.get(20L)), dataJanitorState.getRegionsOnOrBeforeTime(25));
+    // Querying for anything higher than 90 should give 80 (reproduces TEPHRA-230)
+    Assert.assertEquals(new TimeRegions(80, regionsTime.get(80L)),
+                        dataJanitorState.getRegionsOnOrBeforeTime(Long.MAX_VALUE));
 
     // Delete regions saved on or before time 30
     dataJanitorState.deleteAllRegionsOnOrBeforeTime(30);
diff --git a/tephra-hbase-compat-1.1-base/src/main/java/org/apache/tephra/hbase/txprune/DataJanitorState.java b/tephra-hbase-compat-1.1-base/src/main/java/org/apache/tephra/hbase/txprune/DataJanitorState.java
index fc0ec76..db59d7d 100644
--- a/tephra-hbase-compat-1.1-base/src/main/java/org/apache/tephra/hbase/txprune/DataJanitorState.java
+++ b/tephra-hbase-compat-1.1-base/src/main/java/org/apache/tephra/hbase/txprune/DataJanitorState.java
@@ -291,7 +291,7 @@
         } else {
           LOG.warn(String.format("Got incorrect count for regions saved at time %s, expected = %s but actual = %s",
                                  timeRegions.getTime(), count, timeRegions.getRegions().size()));
-          time = time - 1;
+          time = timeRegions.getTime() - 1;
         }
       }
       return null;
diff --git a/tephra-hbase-compat-1.1-base/src/test/java/org/apache/tephra/hbase/txprune/DataJanitorStateTest.java b/tephra-hbase-compat-1.1-base/src/test/java/org/apache/tephra/hbase/txprune/DataJanitorStateTest.java
index b96d87d..2e9dc17 100644
--- a/tephra-hbase-compat-1.1-base/src/test/java/org/apache/tephra/hbase/txprune/DataJanitorStateTest.java
+++ b/tephra-hbase-compat-1.1-base/src/test/java/org/apache/tephra/hbase/txprune/DataJanitorStateTest.java
@@ -137,7 +137,7 @@
     Assert.assertEquals(expectedMap, dataJanitorState.getPruneUpperBoundForRegions(allRegions));
   }
 
-  @Test
+  @Test(timeout = 30000L) // The timeout is used to verify the fix for TEPHRA-230, the test will timeout without the fix
   public void testSaveRegionTime() throws Exception {
     int maxTime = 100;
 
@@ -164,16 +164,21 @@
                         dataJanitorState.getRegionsOnOrBeforeTime(maxTime + 1000));
     Assert.assertNull(dataJanitorState.getRegionsOnOrBeforeTime(-10));
 
-    // Now change the count stored for regions saved at time 0 and 30
+    // Now change the count stored for regions saved at time 0, 30 and 90
     try (Table stateTable = testUtil.getConnection().getTable(pruneStateTable)) {
       dataJanitorState.saveRegionCountForTime(stateTable, Bytes.toBytes(Long.MAX_VALUE), 3);
       dataJanitorState.saveRegionCountForTime(stateTable, Bytes.toBytes(Long.MAX_VALUE - 30L), 3);
+      dataJanitorState.saveRegionCountForTime(stateTable, Bytes.toBytes(Long.MAX_VALUE - 90L), 0);
     }
+
     // Now querying for time 0 should return null, and querying for time 30 should return regions from time 20
     Assert.assertNull(dataJanitorState.getRegionsOnOrBeforeTime(0));
     Assert.assertEquals(new TimeRegions(20, regionsTime.get(20L)), dataJanitorState.getRegionsOnOrBeforeTime(30));
     Assert.assertEquals(new TimeRegions(20, regionsTime.get(20L)), dataJanitorState.getRegionsOnOrBeforeTime(35));
     Assert.assertEquals(new TimeRegions(20, regionsTime.get(20L)), dataJanitorState.getRegionsOnOrBeforeTime(25));
+    // Querying for anything higher than 90 should give 80 (reproduces TEPHRA-230)
+    Assert.assertEquals(new TimeRegions(80, regionsTime.get(80L)),
+                        dataJanitorState.getRegionsOnOrBeforeTime(Long.MAX_VALUE));
 
     // Delete regions saved on or before time 30
     dataJanitorState.deleteAllRegionsOnOrBeforeTime(30);