Index: pom.xml
===================================================================
--- pom.xml	(revision 120)
+++ pom.xml	(working copy)
@@ -35,28 +35,25 @@
   <properties>
     <avro.version>1.7.1</avro.version>
     <crawler-coordinator.version>0.1-SNAPSHOT</crawler-coordinator.version>
-    <datacube.version>1.2.4-GIT-20120809</datacube.version>
+    <datacube.version>1.2.4-GIT-20130413</datacube.version>
     <findbugs-jsr305.version>2.0.1</findbugs-jsr305.version>
-    <gbif-api.version>0.1-SNAPSHOT</gbif-api.version>
-    <gbif-common.version>0.8</gbif-common.version>
-    <gbif-common-service.version>0.3-SNAPSHOT</gbif-common-service.version>
-    <gbif-common-ws.version>0.5-SNAPSHOT</gbif-common-ws.version>
+    <gbif-api.version>0.2</gbif-api.version>
+    <gbif-common.version>0.10</gbif-common.version>
+    <gbif-common-service.version>0.4</gbif-common-service.version>
+    <gbif-common-ws.version>0.6</gbif-common-ws.version>
     <grizzly-servlet-webserver.version>1.9.50</grizzly-servlet-webserver.version>
     <guava.version>13.0.1</guava.version>
     <guice.version>3.0</guice.version>
-    <hbase.version>0.90.4-cdh3u2</hbase.version>
-    <hadoop.version>0.20.2-cdh3u2</hadoop.version>
-    <hbaseVersion>0.90.4-cdh3u2</hbaseVersion>
-    <hadoopVersion>0.20.2-cdh3u2</hadoopVersion>
+    <hbase.version>0.94.2-cdh4.2.0</hbase.version>
+    <hadoop.version>2.0.0-cdh4.2.0</hadoop.version>
+    <hadoopMR.version>2.0.0-mr1-cdh4.2.0</hadoopMR.version>
     <jsr311-api.version>1.0</jsr311-api.version>
     <junit.version>4.10</junit.version>
-    <!-- Fixed to the HBase version -->
-    <slf4j.version>1.5.8</slf4j.version>
+    <slf4j.version>1.7.5</slf4j.version>
     <commons-lang.version>2.6</commons-lang.version>
-    <!--  Important: 0.9.21 and after use SLF4J API 1.6+ which is incompatible with the HBase version -->
-    <logback.version>0.9.17</logback.version>
-    <occurrence-common.version>0.1-SNAPSHOT</occurrence-common.version>
-    <occurrence-persistence.version>0.2-SNAPSHOT</occurrence-persistence.version>
+    <logback.version>1.0.11</logback.version>
+    <occurrence-common.version>0.3-SNAPSHOT</occurrence-common.version>
+    <occurrence-persistence.version>0.3-SNAPSHOT</occurrence-persistence.version>
     <!-- Normally one ties Jackson versions to Jersey versions, but we need 1.9.5+ of Jackson
          because of http://jira.codehaus.org/browse/JACKSON-757 -->
     <jackson.version>1.9.7</jackson.version>
@@ -143,7 +140,7 @@
         <groupId>com.urbanairship</groupId>
         <artifactId>datacube</artifactId>
         <version>${datacube.version}</version>
-        <classifier>hbase${hbase.version}-hadoop${hadoop.version}</classifier>
+        <classifier>hbase${hbase.version}-hadoop${hadoopMR.version}</classifier>
       </dependency>
       <dependency>
         <groupId>org.gbif</groupId>
@@ -169,6 +166,20 @@
         <groupId>org.apache.hbase</groupId>
         <artifactId>hbase</artifactId>
         <version>${hbase.version}</version>
+        <exclusions>
+          <exclusion>
+            <artifactId>commons-logging</artifactId>
+            <groupId>commons-logging</groupId>
+          </exclusion>
+          <exclusion>
+            <artifactId>slf4j-log4j12</artifactId>
+            <groupId>org.slf4j</groupId>
+          </exclusion>
+          <exclusion>
+            <artifactId>log4j</artifactId>
+            <groupId>log4j</groupId>
+          </exclusion>
+        </exclusions>
       </dependency>
       <dependency>
         <groupId>org.slf4j</groupId>
@@ -197,9 +208,19 @@
       <dependency>
         <groupId>org.apache.hadoop</groupId>
         <artifactId>hadoop-core</artifactId>
+        <version>${hadoopMR.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.hadoop</groupId>
+        <artifactId>hadoop-common</artifactId>
         <version>${hadoop.version}</version>
       </dependency>
       <dependency>
+        <groupId>org.apache.hadoop</groupId>
+        <artifactId>hadoop-hdfs</artifactId>
+        <version>${hadoop.version}</version>
+      </dependency>
+      <dependency>
         <groupId>com.google.code.findbugs</groupId>
         <artifactId>jsr305</artifactId>
         <version>${findbugs-jsr305.version}</version>
Index: metrics-cli/src/main/java/org/gbif/metrics/cli/DensityCubeUpdaterService.java
===================================================================
--- metrics-cli/src/main/java/org/gbif/metrics/cli/DensityCubeUpdaterService.java	(revision 123)
+++ metrics-cli/src/main/java/org/gbif/metrics/cli/DensityCubeUpdaterService.java	(working copy)
@@ -1,6 +1,7 @@
 package org.gbif.metrics.cli;
 
 import org.gbif.api.model.occurrence.Occurrence;
+import org.gbif.api.vocabulary.BasisOfRecord;
 import org.gbif.common.messaging.api.MessageCallback;
 import org.gbif.common.messaging.api.OccurrencePersistedMessage;
 import org.gbif.metrics.cube.HBaseCubes;
@@ -9,7 +10,10 @@
 import org.gbif.metrics.cube.tile.density.DensityCubeUtil.Op;
 import org.gbif.metrics.cube.tile.density.DensityTile;
 
+import java.io.File;
 import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.Random;
 
 import com.google.common.base.Preconditions;
 import com.google.common.base.Throwables;
@@ -20,7 +24,42 @@
  * The service to update density cubes.
  */
 class DensityCubeUpdaterService extends CubeUpdaterService<DensityCubeConfiguration> {
-
+  
+  public static void main(String[] args) {
+    try {
+      File hbaseConfig = new File("/Users/tim/dev/hadoop/hbase-0.94.2-cdh4.2.0/conf/hbase-site.xml");
+      Configuration conf = new Configuration();
+      conf.addResource(hbaseConfig.toURI().toURL());
+      
+      HBaseCubes<DensityTile> cube =
+        HBaseCubes.newCombiningBatchAsync(DensityCube.INSTANCE, DensityTile.DESERIALIZER,
+          "tim_cdh4_crawler_density_cube".getBytes(), "dc".getBytes(), conf,
+          10000, 1, 1000, Integer.MAX_VALUE);
+      
+      Random r = new Random();
+      for (int i=0; i<Integer.MAX_VALUE; i++) {
+        
+        Occurrence occurrence = new Occurrence();
+        occurrence.setLatitude((double)r.nextInt(85));
+        occurrence.setLongitude((double)r.nextInt(85));
+        occurrence.setKingdomKey(1);
+        occurrence.setBasisOfRecord(BasisOfRecord.OBSERVATION);
+        occurrence.setGeospatialIssue(0);
+        cube.write(DensityCubeUtil.cubeMutations(occurrence, Op.ADDITION, 20, 4));
+        
+        if (i%100 == 0) {
+          cube.flush();
+          System.out.println("i " + i);
+        }
+      }
+      
+    } catch (Exception e) {
+      // TODO Auto-generated catch block
+      e.printStackTrace();
+    }
+    
+  }
+  
   DensityCubeUpdaterService(DensityCubeConfiguration configuration) {
     super(configuration);
   }
@@ -46,8 +85,7 @@
             // Maximum retry on any contention observed, with a relaxed tolerance on IO Exception (1000 retries)
             singletonCube =
               HBaseCubes.newCombiningBatchAsync(DensityCube.INSTANCE, DensityTile.DESERIALIZER,
-                configuration.cubeTable.getBytes(), configuration.cubeLookupTable.getBytes(),
-                configuration.cubeCounterTable.getBytes(), configuration.columnFamily.getBytes(), hadoopConfiguration,
+                configuration.cubeTable.getBytes(), configuration.columnFamily.getBytes(), hadoopConfiguration,
                 configuration.writeBatchSize, 1, 1000, Integer.MAX_VALUE);
 
           } catch (IOException e) {
Index: metrics-cli/src/main/resources/logback.xml
===================================================================
--- metrics-cli/src/main/resources/logback.xml	(revision 123)
+++ metrics-cli/src/main/resources/logback.xml	(working copy)
@@ -30,7 +30,7 @@
     </encoder>
   </appender>
 
-  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+  <!--appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
     <file>logs/metrics-updater.log</file>
     <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
       <fileNamePattern>logs/metrics-updater.%d{yyyy-MM-dd}.log.gz</fileNamePattern>
@@ -39,11 +39,11 @@
     <encoder>
       <pattern>${defaultPattern}</pattern>
     </encoder>
-  </appender>
+  </appender-->
 
   <root level="INFO">
-    <!-- <appender-ref ref="CONSOLE"/>   -->
-    <appender-ref ref="FILE"/>
+    <appender-ref ref="CONSOLE"/>  
+    <!--appender-ref ref="FILE"/-->
   </root>
 
 </configuration>
Index: metrics-cli/pom.xml
===================================================================
--- metrics-cli/pom.xml	(revision 123)
+++ metrics-cli/pom.xml	(working copy)
@@ -100,7 +100,7 @@
     <dependency>
       <groupId>com.urbanairship</groupId>
       <artifactId>datacube</artifactId>
-      <classifier>hbase${hbase.version}-hadoop${hadoop.version}</classifier>
+      <classifier>hbase${hbase.version}-hadoop${hadoopMR.version}</classifier>
       <exclusions>
         <exclusion>
           <artifactId>slf4j-log4j12</artifactId>
@@ -137,6 +137,10 @@
       </exclusions>
     </dependency>
     <dependency>
+      <groupId>org.apache.hadoop</groupId>
+      <artifactId>hadoop-common</artifactId>
+    </dependency>
+    <dependency>
       <groupId>org.gbif.common</groupId>
       <artifactId>gbif-cli</artifactId>
       <version>0.1</version>
Index: metrics-ws/pom.xml
===================================================================
--- metrics-ws/pom.xml	(revision 120)
+++ metrics-ws/pom.xml	(working copy)
@@ -94,7 +94,7 @@
     <dependency>
       <groupId>com.urbanairship</groupId>
       <artifactId>datacube</artifactId>
-      <classifier>hbase${hbase.version}-hadoop${hadoop.version}</classifier>
+      <classifier>hbase${hbase.version}-hadoop${hadoopMR.version}</classifier>
     </dependency>
     <dependency>
       <groupId>com.google.guava</groupId>
Index: cube/src/test/java/org/gbif/metrics/cube/occurrence/OccurrenceCubeTest.java
===================================================================
--- cube/src/test/java/org/gbif/metrics/cube/occurrence/OccurrenceCubeTest.java	(revision 120)
+++ cube/src/test/java/org/gbif/metrics/cube/occurrence/OccurrenceCubeTest.java	(working copy)
@@ -38,7 +38,7 @@
   @Before
   public void setup() {
     ConcurrentMap<BoxedByteArray, byte[]> backingMap = Maps.newConcurrentMap();
-    IdService idService = new CachingIdService(4, new MapIdService());
+    IdService idService = new CachingIdService(4, new MapIdService(), "id");
     DbHarness<LongOp> dbHarness = new MapDbHarness<LongOp>(backingMap, LongOp.DESERIALIZER, CommitType.READ_COMBINE_CAS, idService);
     cubeIo = new DataCubeIo<LongOp>(OccurrenceCube.INSTANCE, dbHarness, 1, Long.MAX_VALUE, SyncLevel.FULL_SYNC);
   }
Index: cube/src/main/java/org/gbif/metrics/cube/bucketer/CountryBucketer.java
===================================================================
--- cube/src/main/java/org/gbif/metrics/cube/bucketer/CountryBucketer.java	(revision 120)
+++ cube/src/main/java/org/gbif/metrics/cube/bucketer/CountryBucketer.java	(working copy)
@@ -2,41 +2,19 @@
 
 import org.gbif.api.vocabulary.Country;
 
-import java.util.List;
-
-import com.google.common.collect.ImmutableList;
-import com.urbanairship.datacube.BucketType;
-import com.urbanairship.datacube.Bucketer;
 import com.urbanairship.datacube.CSerializable;
+import com.urbanairship.datacube.bucketers.AbstractIdentityBucketer;
 import com.urbanairship.datacube.serializables.BytesSerializable;
 
 /**
  * Bucketer that serializes as 2 letter ISO codes.
  */
-public class CountryBucketer implements Bucketer<Country> {
+public class CountryBucketer extends AbstractIdentityBucketer<Country> { 
   // The number of bytes this buckets into (2 letter ISO codes)
   public static final int BYTES=2;
   
   @Override
-  public List<BucketType> getBucketTypes() {
-    return ImmutableList.of(BucketType.IDENTITY);
+  public CSerializable makeSerializable(Country coord) {
+    return new BytesSerializable(coord.getIso2LetterCode().getBytes());
   }
-  
-  @Override
-  public CSerializable bucketForWrite(Country coordinate, BucketType bucketType) {
-      return bucketInternal(coordinate, bucketType);
-  }
-
-  @Override
-  public CSerializable bucketForRead(Object coordinate, BucketType bucketType) {
-      return bucketInternal((Country)coordinate, bucketType);
-  }  
-
-  public CSerializable bucketInternal(Country c, BucketType bucketType) {
-    if (bucketType != BucketType.IDENTITY) {
-      throw new IllegalArgumentException("You can only use " + CountryBucketer.class.getSimpleName()
-        + " with the default identity bucketer");
-    }
-    return new BytesSerializable(c.getIso2LetterCode().getBytes());
-  }
 }
Index: cube/src/main/java/org/gbif/metrics/cube/bucketer/BasisOfRecordBucketer.java
===================================================================
--- cube/src/main/java/org/gbif/metrics/cube/bucketer/BasisOfRecordBucketer.java	(revision 120)
+++ cube/src/main/java/org/gbif/metrics/cube/bucketer/BasisOfRecordBucketer.java	(working copy)
@@ -3,44 +3,21 @@
 import org.gbif.api.vocabulary.BasisOfRecord;
 import org.gbif.occurrencestore.util.BasisOfRecordConverter;
 
-import java.util.List;
-
-import com.google.common.collect.ImmutableList;
-import com.urbanairship.datacube.BucketType;
-import com.urbanairship.datacube.Bucketer;
 import com.urbanairship.datacube.CSerializable;
+import com.urbanairship.datacube.bucketers.AbstractIdentityBucketer;
 import com.urbanairship.datacube.serializables.IntSerializable;
 
 /**
  * Bucketer that uses the basis of record converter to serialize as Ints
  */
-public class BasisOfRecordBucketer implements Bucketer<BasisOfRecord> {
+public class BasisOfRecordBucketer extends AbstractIdentityBucketer<BasisOfRecord> { 
   // The number of bytes this buckets into
   public static final int BYTES=4;
   
   private static final BasisOfRecordConverter BOR_CONVERTER = new BasisOfRecordConverter();
   
   @Override
-  public List<BucketType> getBucketTypes() {
-    return ImmutableList.of(BucketType.IDENTITY);
+  public CSerializable makeSerializable(BasisOfRecord coord) {
+    return new IntSerializable(BOR_CONVERTER.fromEnum(coord));
   }
-  
-  @Override
-  public CSerializable bucketForWrite(BasisOfRecord coordinate, BucketType bucketType) {
-      return bucketInternal(coordinate, bucketType);
-  }
-
-  @Override
-  public CSerializable bucketForRead(Object coordinate, BucketType bucketType) {
-      return bucketInternal((BasisOfRecord)coordinate, bucketType);
-  }  
-
-  public CSerializable bucketInternal(BasisOfRecord c, BucketType bucketType) {
-    if (bucketType != BucketType.IDENTITY) {
-      throw new IllegalArgumentException("You can only use " + BasisOfRecordBucketer.class.getSimpleName()
-        + " with the default identity bucketer");
-    }
-    return new IntSerializable(BOR_CONVERTER.fromEnum(c));
-  }
-
 }
Index: cube/src/main/java/org/gbif/metrics/cube/bucketer/UUIDBucketer.java
===================================================================
--- cube/src/main/java/org/gbif/metrics/cube/bucketer/UUIDBucketer.java	(revision 120)
+++ cube/src/main/java/org/gbif/metrics/cube/bucketer/UUIDBucketer.java	(working copy)
@@ -1,8 +1,12 @@
 package org.gbif.metrics.cube.bucketer;
 
+import org.gbif.api.vocabulary.Country;
+
 import java.util.List;
 import java.util.UUID;
 
+import com.urbanairship.datacube.bucketers.AbstractIdentityBucketer;
+
 import com.google.common.collect.ImmutableList;
 import com.urbanairship.datacube.BucketType;
 import com.urbanairship.datacube.Bucketer;
@@ -12,30 +16,12 @@
 /**
  * Bucketer that serializes UUIDs as 36 bytes of text.
  */
-public class UUIDBucketer implements Bucketer<UUID> {
+public class UUIDBucketer extends AbstractIdentityBucketer<UUID> { 
   // UUID are 36 long
   public static final int BYTES=36;
-  
-  @Override
-  public List<BucketType> getBucketTypes() {
-    return ImmutableList.of(BucketType.IDENTITY);
-  }
-  
-  @Override
-  public CSerializable bucketForWrite(UUID coordinate, BucketType bucketType) {
-      return bucketInternal(coordinate, bucketType);
-  }
 
   @Override
-  public CSerializable bucketForRead(Object coordinate, BucketType bucketType) {
-      return bucketInternal((UUID)coordinate, bucketType);
-  }  
-
-  public CSerializable bucketInternal(UUID c, BucketType bucketType) {
-    if (bucketType != BucketType.IDENTITY) {
-      throw new IllegalArgumentException("You can only use " + UUIDBucketer.class.getSimpleName()
-        + " with the default identity bucketer");
-    }
-    return new BytesSerializable(c.toString().getBytes());
+  public CSerializable makeSerializable(UUID coord) {
+    return new BytesSerializable(coord.toString().getBytes());
   }
 }
Index: cube/src/main/java/org/gbif/metrics/cube/tile/bucketer/MapKeyBucketer.java
===================================================================
--- cube/src/main/java/org/gbif/metrics/cube/tile/bucketer/MapKeyBucketer.java	(revision 121)
+++ cube/src/main/java/org/gbif/metrics/cube/tile/bucketer/MapKeyBucketer.java	(working copy)
@@ -1,46 +1,24 @@
 package org.gbif.metrics.cube.tile.bucketer;
 
-import java.util.List;
-
 import com.google.common.base.Strings;
-
-import com.google.common.base.CharMatcher;
-
-
-import com.google.common.collect.ImmutableList;
-import com.urbanairship.datacube.BucketType;
-import com.urbanairship.datacube.Bucketer;
 import com.urbanairship.datacube.CSerializable;
+import com.urbanairship.datacube.bucketers.AbstractIdentityBucketer;
 import com.urbanairship.datacube.serializables.StringSerializable;
 
 /**
  * Encodes and decodes the various map keys into 36 character bytes padding with spaces.
  * 36 characters are required for UUIDs which are considered the longest keys supported by maps.
  */
-public class MapKeyBucketer implements Bucketer<String> {
+public class MapKeyBucketer extends AbstractIdentityBucketer<String> {
   private static final MapKeyBucketer instance = new MapKeyBucketer();
   public static final int BYTES=36;
   
   @Override
-  public CSerializable bucketForWrite(String coordinateField, BucketType bucketType) {
-    return bucket(coordinateField, bucketType);
-  }
-
-  @Override
-  public CSerializable bucketForRead(Object coordinateField, BucketType bucketType) {
-    return bucket(CharMatcher.WHITESPACE.trimFrom((String)coordinateField), bucketType);
-  }
-
-  private CSerializable bucket(String coordinateField, BucketType bucketType) {
+  public CSerializable makeSerializable(String coordinateField) {
     return new StringSerializable(Strings.padStart(coordinateField, 36, ' '));
-  }
+  }  
   
-  @Override
-  public List<BucketType> getBucketTypes() {
-    return ImmutableList.of(BucketType.IDENTITY);
-  }
-
   public static final MapKeyBucketer getInstance() {
     return instance;
   }
-}
+}
\ No newline at end of file
Index: cube/pom.xml
===================================================================
--- cube/pom.xml	(revision 120)
+++ cube/pom.xml	(working copy)
@@ -102,7 +102,7 @@
     <dependency>
       <groupId>com.urbanairship</groupId>
       <artifactId>datacube</artifactId>
-      <classifier>hbase${hbase.version}-hadoop${hadoop.version}</classifier>
+      <classifier>hbase${hbase.version}-hadoop${hadoopMR.version}</classifier>
     </dependency>
     <dependency>
       <groupId>com.google.inject</groupId>
@@ -118,6 +118,10 @@
     </dependency>
     <dependency>
       <groupId>org.apache.hadoop</groupId>
+      <artifactId>hadoop-common</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.hadoop</groupId>
       <artifactId>hadoop-core</artifactId>
     </dependency>
     <dependency>
