/**
 * Copyright 2016 Palantir Technologies
 *
 * Licensed under the BSD-3 License (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://opensource.org/licenses/BSD-3-Clause
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.palantir.atlasdb.jepsen;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MonotonicChecker implements Visitor {
    boolean valid = true;
    List<Event> errors = new ArrayList<>();
    Map<Integer, Last> lastPerProcess = new HashMap<>();

    private static class Last {
        Long lastSeen = null;
        Event lastEvent = null;
    }

    @Override
    public void visit(InfoRead event) {
    }

    @Override
    public void visit(InvokeRead event) {
    }

    @Override
    public void visit(OkRead event) {
        Integer process = event.process();
        lastPerProcess.putIfAbsent(process, new Last());
        Last last = lastPerProcess.get(process);
        Long value = event.value();
        if (last.lastSeen != null && value <= last.lastSeen) {
            valid = false;
            errors.add(last.lastEvent);
            errors.add(event);
        }
        last.lastSeen = value;
        last.lastEvent = event;
    }

    public boolean valid() {
        return valid;
    }

    public List<Event> errors() {
        return errors;
    }
}

@@ -720,16 +720,65 @@
 l.Map;%0A%0A
+import com.google.common.collect.ImmutableList;%0A%0A
 public c
@@ -828,33 +828,21 @@
     
-boolean valid = true;%0A   
+private final
  Lis
@@ -886,161 +886,118 @@
     
-Map%3CInteger, Last%3E lastPerProcess = new HashMap%3C%3E();%0A%0A    private static class Last %7B%0A        Long lastSeen = null;%0A        Event lastEvent = null;%0A    %7D
+private final Map%3CInteger, OkRead%3E latestEventPerProcess = new HashMap%3C%3E();%0A%0A    private boolean valid = true;
 %0A%0A  
@@ -1178,23 +1178,19 @@
         
-I
+i
 nt
-eger
  process
@@ -1209,24 +1209,25 @@
 cess();%0A
+%0A
         
 lastPerP
@@ -1222,205 +1222,191 @@
     
-lastPerProcess.putIfAbsent(process, new Last());%0A        Last last = lastPerProcess.get(process);%0A        Long value = event.value();%0A        if (last.lastSeen != null && value %3C= last.lastSeen) %7B%0A
+if (latestEventPerProcess.containsKey(process)) %7B%0A            OkRead previousEvent = latestEventPerProcess.get(process);%0A            if (event.value() %3C= previousEvent.value()) %7B%0A    
     
@@ -1432,32 +1432,36 @@
 se;%0A            
+    
 errors.add(last.
@@ -1459,25 +1459,24 @@
 add(
-last.last
+previous
 Event);%0A
     
@@ -1467,24 +1467,28 @@
 iousEvent);%0A
+    
             
@@ -1514,16 +1514,20 @@
         
+    
 %7D%0A      
@@ -1532,30 +1532,9 @@
     
-last.lastSeen = value;
+%7D
 %0A   
@@ -1544,28 +1544,47 @@
   la
-st.la
+te
 stEvent
- =
+PerProcess.put(process,
  event
+)
 ;%0A  
@@ -1695,22 +1695,44 @@
  return 
+ImmutableList.copyOf(
 errors
+)
 ;%0A    %7D%0A

Clean up MonotonicChecker