/**
 * Copyright 2015 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.keyvalue.partition;

import com.google.common.base.Function;
import com.palantir.atlasdb.keyvalue.partition.api.DynamicPartitionMap;
import com.palantir.atlasdb.keyvalue.partition.exception.ClientVersionTooOldException;

/**
 * This is to make sure that no one extending this class
 * can access the partitionMap directly.
 *
 * Still care needs to be taken not to leak any direct
 * or indirect DynamicPartitionMap references to outside of
 * the runWithPartitionMap method.
 *
 * @author htarasiuk
 *
 */
public class PartitionMapProvider {

	private DynamicPartitionMap partitionMap;

    protected <T> T runWithPartitionMap(Function<DynamicPartitionMap, T> task) {
    	try {
    		return task.apply(partitionMap);
    	} catch (ClientVersionTooOldException e) {
    		partitionMap = e.getUpdatedMap();
    		/**
    		 * Update the map but let the transaction manager retry the task.
    		 * It seems to be reasonable since some of the KVS operations
    		 * are not idempotent so retrying them from here could get
    		 * other errors that would confuse the transaction manager.
    		 */
    		throw e;
    	}
    }

    protected void updatePartitionMap(DynamicPartitionMap partitionMap) {
    	this.partitionMap = partitionMap;
    }

    protected PartitionMapProvider(DynamicPartitionMap partitionMap) {
    	this.partitionMap = partitionMap;
    }
}

@@ -830,16 +830,105 @@
 ception;
+%0Aimport com.palantir.atlasdb.keyvalue.partition.exception.EndpointVersionTooOldException;
 %0A%0A/**%0A *
@@ -1244,17 +1244,20 @@
 ider %7B%0A%0A
-%09
+    
 private 
@@ -1376,17 +1376,20 @@
 ) %7B%0A    
-%09
+    
 try %7B%0A  
@@ -1390,18 +1390,24 @@
 y %7B%0A    
-%09%09
+        
 return t
@@ -1435,17 +1435,20 @@
 p);%0A    
-%09
+    
 %7D catch 
@@ -1486,18 +1486,24 @@
 ) %7B%0A    
-%09%09
+        
 partitio
@@ -1536,20 +1536,32 @@
     
-%09%09/**%0A    %09%09
+        /**%0A            
  * U
@@ -1626,18 +1626,24 @@
 sk.%0A    
-%09%09
+        
  * It se
@@ -1700,18 +1700,24 @@
 ons%0A    
-%09%09
+        
  * are n
@@ -1771,18 +1771,24 @@
 get%0A    
-%09%09
+        
  * other
@@ -1847,20 +1847,32 @@
     
-%09%09 */%0A    %09%09
+         */%0A            
 thro
@@ -1884,96 +1884,334 @@
     
-%09%7D%0A
     %7D
-%0A%0A    protected void updatePartitionMap(DynamicPartitionMap parti
+ catch (EndpointVersionTooOldException e) %7B%0A            e.pushNewMap(partitionMap);%0A            /**%0A             * Push my map version to the endpoint but let the transaction%0A             * manager retry this task for same reasons as above.%0A             */%0A            throw e;%0A        %7D catch (RuntimeExcep
 tion
-Map
+ e
 ) %7B%0A    
 %09thi
@@ -2198,38 +2198,97 @@
 eption e) %7B%0A    
-%09this.
+        /**%0A             * TODO:%0A             * Consult the seed 
 partitionMap = p
@@ -2280,35 +2280,142 @@
 artition
-Map = partitionMap;
+ map servers to ensure that my map is%0A             * up-to-date.%0A             *%0A             */%0A            throw e;%0A        %7D
 %0A    %7D%0A%0A
@@ -2493,9 +2493,12 @@
     
-%09
+    
 this

Update PartitionMapProvider.