accumulo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ctubb...@apache.org
Subject [06/18] git commit: ACCUMULO-1677 Allow loading native maps from multiple locations
Date Wed, 20 Nov 2013 23:33:25 GMT
ACCUMULO-1677 Allow loading native maps from multiple locations

  Allow native maps to load from java.library.path, which is set by
  LD_LIBRARY_PATH and from system library locations.


Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo
Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/bc65b369
Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/bc65b369
Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/bc65b369

Branch: refs/heads/master
Commit: bc65b369c5af8552e136d1c89e3dcbd91937e344
Parents: e647b1b
Author: Christopher Tubbs <ctubbsii@apache.org>
Authored: Tue Nov 19 17:24:28 2013 -0500
Committer: Christopher Tubbs <ctubbsii@apache.org>
Committed: Tue Nov 19 18:40:27 2013 -0500

----------------------------------------------------------------------
 server/native/src/main/resources/Makefile       |   2 +-
 .../apache/accumulo/tserver/InMemoryMap.java    |   2 +-
 .../org/apache/accumulo/tserver/NativeMap.java  | 411 +++++++-----
 .../tserver/TabletServerResourceManager.java    |   2 +-
 .../org/apache/accumulo/start/Platform.java     |  27 -
 test/pom.xml                                    |   5 +
 .../accumulo/test/functional/NativeMapTest.java | 654 -------------------
 .../test/MultiTableBatchWriterTest.java         |  18 +-
 .../accumulo/test/functional/NativeMapIT.java   | 586 ++++++++++++++++-
 9 files changed, 842 insertions(+), 865 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/accumulo/blob/bc65b369/server/native/src/main/resources/Makefile
----------------------------------------------------------------------
diff --git a/server/native/src/main/resources/Makefile b/server/native/src/main/resources/Makefile
index 6309e6d..9f0ecde 100644
--- a/server/native/src/main/resources/Makefile
+++ b/server/native/src/main/resources/Makefile
@@ -26,7 +26,7 @@ endif
 
 ifeq ($(shell uname),Darwin)
 	JAVA_HOME=$(shell /usr/libexec/java_home)
-	NATIVE_LIB:= libNativeMap-Mac_OS_X-x86_64-64.dylib
+	NATIVE_LIB:= libaccumulo.dylib
 	# Update flags for OSX-10.9 and Xcode 5.0.1
 	# I think that we should be able to remove the `-undefined dynamic_lookup` option,
 	# but I don't know exactly how to go about this.

http://git-wip-us.apache.org/repos/asf/accumulo/blob/bc65b369/server/tserver/src/main/java/org/apache/accumulo/tserver/InMemoryMap.java
----------------------------------------------------------------------
diff --git a/server/tserver/src/main/java/org/apache/accumulo/tserver/InMemoryMap.java b/server/tserver/src/main/java/org/apache/accumulo/tserver/InMemoryMap.java
index 66f49c4..9678638 100644
--- a/server/tserver/src/main/java/org/apache/accumulo/tserver/InMemoryMap.java
+++ b/server/tserver/src/main/java/org/apache/accumulo/tserver/InMemoryMap.java
@@ -220,7 +220,7 @@ public class InMemoryMap {
   }
   
   private static SimpleMap newMap(boolean useNativeMap) {
-    if (useNativeMap && NativeMap.loadedNativeLibraries()) {
+    if (useNativeMap && NativeMap.isLoaded()) {
       try {
         return new NativeMapWrapper();
       } catch (Throwable t) {

http://git-wip-us.apache.org/repos/asf/accumulo/blob/bc65b369/server/tserver/src/main/java/org/apache/accumulo/tserver/NativeMap.java
----------------------------------------------------------------------
diff --git a/server/tserver/src/main/java/org/apache/accumulo/tserver/NativeMap.java b/server/tserver/src/main/java/org/apache/accumulo/tserver/NativeMap.java
index 59142f7..80c6f62 100644
--- a/server/tserver/src/main/java/org/apache/accumulo/tserver/NativeMap.java
+++ b/server/tserver/src/main/java/org/apache/accumulo/tserver/NativeMap.java
@@ -18,6 +18,8 @@ package org.apache.accumulo.tserver;
 
 import java.io.File;
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.ConcurrentModificationException;
 import java.util.HashSet;
@@ -41,7 +43,6 @@ import org.apache.accumulo.core.iterators.IterationInterruptedException;
 import org.apache.accumulo.core.iterators.IteratorEnvironment;
 import org.apache.accumulo.core.iterators.SortedKeyValueIterator;
 import org.apache.accumulo.core.iterators.system.InterruptibleIterator;
-import org.apache.accumulo.start.Platform;
 import org.apache.log4j.Logger;
 
 /**
@@ -54,42 +55,142 @@ import org.apache.log4j.Logger;
  */
 
 public class NativeMap implements Iterable<Map.Entry<Key,Value>> {
-  
+
   private static final Logger log = Logger.getLogger(NativeMap.class);
-  
+  private static AtomicBoolean loadedNativeLibraries = new AtomicBoolean(false);
+
+  // Load native library
+  static {
+    // Check standard directories
+    List<File> directories = new ArrayList<File>(Arrays.asList(new File[] {new File("/usr/lib64"), new File("/usr/lib")}));
+    // Check in old ACCUMULO_HOME location, too
+    String envAccumuloHome = System.getenv("ACCUMULO_HOME");
+    if (envAccumuloHome != null)
+      directories.add(new File(envAccumuloHome + "/lib/native/map"));
+    // Attempt to load from these directories, using standard names
+    loadNativeLib(directories);
+
+    // Check LD_LIBRARY_PATH (DYLD_LIBRARY_PATH on Mac)
+    if (!isLoaded()) {
+      String ldLibraryPath = System.getProperty("java.library.path");
+      String errMsg = "Tried and failed to load native map library from " + ldLibraryPath;
+      try {
+        System.loadLibrary("accumulo");
+        log.info("Loaded native map shared library from " + ldLibraryPath);
+      } catch (Exception e) {
+        log.error(errMsg, e);
+      } catch (UnsatisfiedLinkError e) {
+        log.error(errMsg, e);
+      }
+    }
+  }
+
+  /**
+   * If native libraries are not loaded, the specified search path will be used to attempt to load them. Directories will be searched by using the
+   * system-specific library naming conventions. A path directly to a file can also be provided. Loading will continue until the search path is exhausted, or
+   * until the native libraries are found and successfully loaded, whichever occurs first.
+   * 
+   * @param searchPath
+   *          a list of files and directories to search
+   */
+  public static void loadNativeLib(List<File> searchPath) {
+    if (!isLoaded()) {
+      List<String> names = getValidLibraryNames();
+      List<File> tryList = new ArrayList<File>(searchPath.size() * names.size());
+
+      for (File p : searchPath)
+        if (p.exists() && p.isDirectory())
+          for (String name : names)
+            tryList.add(new File(p, name));
+        else
+          tryList.add(p);
+
+      for (File f : tryList)
+        if (loadNativeLib(f))
+          break;
+    }
+  }
+
+  /**
+   * Check if native libraries are loaded.
+   * 
+   * @return true if they are loaded; false otherwise
+   */
+  public static boolean isLoaded() {
+    return loadedNativeLibraries.get();
+  }
+
+  private static List<String> getValidLibraryNames() {
+    ArrayList<String> names = new ArrayList<String>(3);
+
+    String libname = System.mapLibraryName("accumulo");
+    names.add(libname);
+
+    int dot = libname.lastIndexOf(".");
+    String prefix = dot < 0 ? libname : libname.substring(0, dot);
+
+    // additional supported Mac extensions
+    if ("Mac OS X".equals(System.getProperty("os.name")))
+      for (String ext : new String[] {".dylib", ".jnilib"})
+        if (!libname.endsWith(ext))
+          names.add(prefix + ext);
+
+    return names;
+  }
+
+  private static boolean loadNativeLib(File libFile) {
+    log.debug("Trying to load native map library " + libFile);
+    if (libFile.exists() && libFile.isFile()) {
+      String errMsg = "Tried and failed to load native map library " + libFile;
+      try {
+        System.load(libFile.getAbsolutePath());
+        loadedNativeLibraries.set(true);
+        log.info("Loaded native map shared library " + libFile);
+        return true;
+      } catch (Exception e) {
+        log.error(errMsg, e);
+      } catch (UnsatisfiedLinkError e) {
+        log.error(errMsg, e);
+      }
+    } else {
+      log.debug("Native map library " + libFile + " not found or is not a file.");
+    }
+    return false;
+  }
+
   private long nmPointer;
-  
+
   private final ReadWriteLock rwLock;
   private final Lock rlock;
   private final Lock wlock;
-  
+
   int modCount = 0;
-  
+
   private static native long createNM();
-  
+
   // private static native void putNM(long nmPointer, byte[] kd, int cfo, int cqo, int cvo, int tl, long ts, boolean del, byte[] value);
-  
+
   private static native void singleUpdate(long nmPointer, byte[] row, byte cf[], byte cq[], byte cv[], long ts, boolean del, byte[] value, int mutationCount);
-  
+
   private static native long startUpdate(long nmPointer, byte[] row);
-  
+
   private static native void update(long nmPointer, long updateID, byte cf[], byte cq[], byte cv[], long ts, boolean del, byte[] value, int mutationCount);
-  
+
   private static native int sizeNM(long nmPointer);
-  
+
   private static native long memoryUsedNM(long nmPointer);
-  
+
   private static native long deleteNM(long nmPointer);
-  
+
   private static boolean init = false;
   private static long totalAllocations;
   private static HashSet<Long> allocatedNativeMaps;
-  
+
   private static synchronized long createNativeMap() {
-    
+
     if (!init) {
       allocatedNativeMaps = new HashSet<Long>();
-      
+
       Runnable r = new Runnable() {
         @Override
         public void run() {
@@ -101,29 +202,29 @@ public class NativeMap implements Iterable<Map.Entry<Key,Value>> {
               log.error("There are " + allocatedNativeMaps.size() + " allocated native maps");
             }
           }
-          
+
           log.debug(totalAllocations + " native maps were allocated");
         }
       };
-      
+
       Runtime.getRuntime().addShutdownHook(new Thread(r));
-      
+
       init = true;
     }
-    
+
     long nmPtr = createNM();
-    
+
     if (allocatedNativeMaps.contains(nmPtr)) {
       // something is really screwy, this should not happen
       throw new RuntimeException(String.format("Duplicate native map pointer 0x%016x ", nmPtr));
     }
-    
+
     totalAllocations++;
     allocatedNativeMaps.add(nmPtr);
-    
+
     return nmPtr;
   }
-  
+
   private static synchronized void deleteNativeMap(long nmPtr) {
     if (allocatedNativeMaps.contains(nmPtr)) {
       deleteNM(nmPtr);
@@ -132,74 +233,46 @@ public class NativeMap implements Iterable<Map.Entry<Key,Value>> {
       throw new RuntimeException(String.format("Attempt to delete native map that is not allocated 0x%016x ", nmPtr));
     }
   }
-  
-  private static boolean loadedNativeLibraries = false;
-  
-  public static String getNativeLibPath() {
-    return "lib/native/map/" + System.mapLibraryName("NativeMap-" + Platform.getPlatform());
-  }
-  
-  public static void loadNativeLib(String nativeLib) {
-    try {
-      System.load(nativeLib);
-      log.info("Loaded native map shared library " + nativeLib);
-      loadedNativeLibraries = true;
-    } catch (Throwable t) {
-      log.error("Failed to load native map library " + nativeLib, t);
-    }
-  }
-  
-  static {
-    String aHome = System.getenv("ACCUMULO_HOME");
-    if (aHome != null) {
-      String nativeLib = aHome + "/" + getNativeLibPath();
-      loadNativeLib(new File(nativeLib).getAbsolutePath());
-    }
-  }
-  
-  public static boolean loadedNativeLibraries() {
-    return loadedNativeLibraries;
-  }
-  
+
   private static native long createNMI(long nmp, int fieldLens[]);
-  
+
   private static native long createNMI(long nmp, byte[] row, byte cf[], byte cq[], byte cv[], long ts, boolean del, int fieldLens[]);
-  
+
   private static native boolean nmiNext(long nmiPointer, int fieldLens[]);
-  
+
   private static native void nmiGetData(long nmiPointer, byte[] row, byte cf[], byte cq[], byte cv[], byte[] valData);
-  
+
   private static native long nmiGetTS(long nmiPointer);
-  
+
   private static native void deleteNMI(long nmiPointer);
-  
+
   private class ConcurrentIterator implements Iterator<Map.Entry<Key,Value>> {
-    
+
     // in order to get good performance when there are multiple threads reading, need to read a lot while the
     // the read lock is held..... lots of threads trying to get the read lock very often causes serious slow
     // downs.... also reading a lot of entries at once lessens the impact of concurrent writes... if only
     // one entry were read at a time and there were concurrent writes, then iteration could be n*log(n)
-    
+
     // increasing this number has a positive effect on concurrent read performance, but negatively effects
     // concurrent writers
     private static final int MAX_READ_AHEAD_ENTRIES = 16;
     private static final int READ_AHEAD_BYTES = 4096;
-    
+
     private NMIterator source;
-    
+
     private Entry<Key,Value> nextEntries[];
     private int index;
     private int end;
-    
+
     ConcurrentIterator() {
       this(new MemKey());
     }
-    
+
     @SuppressWarnings("unchecked")
     ConcurrentIterator(Key key) {
       // start off with a small read ahead
       nextEntries = new Entry[1];
-      
+
       rlock.lock();
       try {
         source = new NMIterator(key);
@@ -208,45 +281,45 @@ public class NativeMap implements Iterable<Map.Entry<Key,Value>> {
         rlock.unlock();
       }
     }
-    
+
     // it is assumed the read lock is held when this method is called
     @SuppressWarnings("unchecked")
     private void fill() {
       end = 0;
       index = 0;
-      
+
       if (source.hasNext())
         source.doNextPreCheck();
-      
+
       int amountRead = 0;
-      
+
       // as we keep filling, increase the read ahead buffer
       if (nextEntries.length < MAX_READ_AHEAD_ENTRIES)
         nextEntries = new Entry[Math.min(nextEntries.length * 2, MAX_READ_AHEAD_ENTRIES)];
-      
+
       while (source.hasNext() && end < nextEntries.length) {
         Entry<Key,Value> ne = source.next();
         nextEntries[end++] = ne;
         amountRead += ne.getKey().getSize() + ne.getValue().getSize();
-        
+
         if (amountRead > READ_AHEAD_BYTES)
           break;
       }
     }
-    
+
     @Override
     public boolean hasNext() {
       return end != 0;
     }
-    
+
     @Override
     public Entry<Key,Value> next() {
       if (end == 0) {
         throw new NoSuchElementException();
       }
-      
+
       Entry<Key,Value> ret = nextEntries[index++];
-      
+
       if (index == end) {
         rlock.lock();
         try {
@@ -264,24 +337,24 @@ public class NativeMap implements Iterable<Map.Entry<Key,Value>> {
         } finally {
           rlock.unlock();
         }
-        
+
       }
-      
+
       return ret;
     }
-    
+
     @Override
     public void remove() {
       throw new UnsupportedOperationException();
     }
-    
+
     public void delete() {
       source.delete();
     }
   }
-  
+
   private class NMIterator implements Iterator<Map.Entry<Key,Value>> {
-    
+
     /**
      * The strategy for dealing with native memory allocated for iterators is to simply delete that memory when this Java Object is garbage collected.
      * 
@@ -289,28 +362,28 @@ public class NativeMap implements Iterable<Map.Entry<Key,Value>> {
      * slowly garbage collected they only hold a small amount of native memory.
      * 
      */
-    
+
     private long nmiPointer;
     private boolean hasNext;
     private int expectedModCount;
     private int[] fieldsLens = new int[7];
     private byte lastRow[];
-    
+
     // it is assumed the read lock is held when this method is called
     NMIterator(Key key) {
-      
+
       if (nmPointer == 0) {
         throw new IllegalStateException();
       }
-      
+
       expectedModCount = modCount;
-      
+
       nmiPointer = createNMI(nmPointer, key.getRowData().toArray(), key.getColumnFamilyData().toArray(), key.getColumnQualifierData().toArray(), key
           .getColumnVisibilityData().toArray(), key.getTimestamp(), key.isDeleted(), fieldsLens);
-      
+
       hasNext = nmiPointer != 0;
     }
-    
+
     // delete is synchronized on a per iterator basis want to ensure only one
     // thread deletes an iterator w/o acquiring the global write lock...
     // there is no contention among concurrent readers for deleting their iterators
@@ -318,30 +391,30 @@ public class NativeMap implements Iterable<Map.Entry<Key,Value>> {
       if (nmiPointer == 0) {
         return;
       }
-      
+
       // log.debug("Deleting native map iterator pointer");
-      
+
       deleteNMI(nmiPointer);
       nmiPointer = 0;
     }
-    
+
     @Override
     public boolean hasNext() {
       return hasNext;
     }
-    
+
     // it is assumed the read lock is held when this method is called
     // this method only needs to be called once per read lock acquisition
     private void doNextPreCheck() {
       if (nmPointer == 0) {
         throw new IllegalStateException();
       }
-      
+
       if (modCount != expectedModCount) {
         throw new ConcurrentModificationException();
       }
     }
-    
+
     @Override
     // It is assumed that this method is called w/ the read lock held and
     // that doNextPreCheck() is called prior to calling this method
@@ -351,39 +424,39 @@ public class NativeMap implements Iterable<Map.Entry<Key,Value>> {
       if (!hasNext) {
         throw new NoSuchElementException();
       }
-      
+
       if (nmiPointer == 0) {
         throw new IllegalStateException("Native Map Iterator Deleted");
       }
-      
+
       byte[] row = null;
       if (fieldsLens[0] >= 0) {
         row = new byte[fieldsLens[0]];
         lastRow = row;
       }
-      
+
       byte cf[] = new byte[fieldsLens[1]];
       byte cq[] = new byte[fieldsLens[2]];
       byte cv[] = new byte[fieldsLens[3]];
       boolean deleted = fieldsLens[4] == 0 ? false : true;
       byte val[] = new byte[fieldsLens[5]];
-      
+
       nmiGetData(nmiPointer, row, cf, cq, cv, val);
       long ts = nmiGetTS(nmiPointer);
-      
+
       Key k = new MemKey(lastRow, cf, cq, cv, ts, deleted, false, fieldsLens[6]);
       Value v = new Value(val, false);
-      
+
       hasNext = nmiNext(nmiPointer, fieldsLens);
-      
+
       return new NMEntry(k, v);
     }
-    
+
     @Override
     public void remove() {
       throw new UnsupportedOperationException();
     }
-    
+
     @Override
     protected void finalize() throws Throwable {
       super.finalize();
@@ -392,39 +465,40 @@ public class NativeMap implements Iterable<Map.Entry<Key,Value>> {
         deleteNMI(nmiPointer);
       }
     }
-    
+
   }
-  
+
   private static class NMEntry implements Map.Entry<Key,Value> {
-    
+
     private Key key;
     private Value val;
-    
+
     NMEntry(Key k, Value v) {
       this.key = k;
       this.val = v;
     }
-    
+
     @Override
     public Key getKey() {
       return key;
     }
-    
+
     @Override
     public Value getValue() {
       return val;
     }
-    
+
     @Override
     public Value setValue(Value value) {
       throw new UnsupportedOperationException();
     }
-    
+
+    @Override
     public String toString() {
       return key + "=" + val;
     }
   }
-  
+
   public NativeMap() {
     nmPointer = createNativeMap();
     rwLock = new ReentrantReadWriteLock();
@@ -432,7 +506,7 @@ public class NativeMap implements Iterable<Map.Entry<Key,Value>> {
     wlock = rwLock.writeLock();
     log.debug(String.format("Allocated native map 0x%016x", nmPointer));
   }
-  
+
   @Override
   protected void finalize() throws Throwable {
     super.finalize();
@@ -441,9 +515,9 @@ public class NativeMap implements Iterable<Map.Entry<Key,Value>> {
       deleteNativeMap(nmPointer);
     }
   }
-  
+
   private void _mutate(Mutation mutation, int mutationCount) {
-    
+
     List<ColumnUpdate> updates = mutation.getUpdates();
     if (updates.size() == 1) {
       ColumnUpdate update = updates.get(0);
@@ -455,38 +529,38 @@ public class NativeMap implements Iterable<Map.Entry<Key,Value>> {
         update(nmPointer, uid, update.getColumnFamily(), update.getColumnQualifier(), update.getColumnVisibility(), update.getTimestamp(), update.isDeleted(),
             update.getValue(), mutationCount);
       }
-      
+
     }
   }
-  
+
   public void mutate(Mutation mutation, int mutationCount) {
     wlock.lock();
     try {
       if (nmPointer == 0) {
         throw new IllegalStateException("Native Map Deleted");
       }
-      
+
       modCount++;
-      
+
       _mutate(mutation, mutationCount);
     } finally {
       wlock.unlock();
     }
   }
-  
+
   public void mutate(List<Mutation> mutations, int mutationCount) {
     Iterator<Mutation> iter = mutations.iterator();
-    
+
     while (iter.hasNext()) {
-      
+
       wlock.lock();
       try {
         if (nmPointer == 0) {
           throw new IllegalStateException("Native Map Deleted");
         }
-        
+
         modCount++;
-        
+
         int count = 0;
         while (iter.hasNext() && count < 10) {
           Mutation mutation = iter.next();
@@ -499,23 +573,23 @@ public class NativeMap implements Iterable<Map.Entry<Key,Value>> {
       }
     }
   }
-  
+
   public void put(Key key, Value value) {
     wlock.lock();
     try {
       if (nmPointer == 0) {
         throw new IllegalStateException("Native Map Deleted");
       }
-      
+
       modCount++;
-      
+
       singleUpdate(nmPointer, key.getRowData().toArray(), key.getColumnFamilyData().toArray(), key.getColumnQualifierData().toArray(), key
           .getColumnVisibilityData().toArray(), key.getTimestamp(), key.isDeleted(), value.get(), 0);
     } finally {
       wlock.unlock();
     }
   }
-  
+
   public Value get(Key key) {
     rlock.lock();
     try {
@@ -527,75 +601,76 @@ public class NativeMap implements Iterable<Map.Entry<Key,Value>> {
           ret = entry.getValue();
         }
       }
-      
+
       nmi.delete();
-      
+
       return ret;
     } finally {
       rlock.unlock();
     }
   }
-  
+
   public int size() {
     rlock.lock();
     try {
       if (nmPointer == 0) {
         throw new IllegalStateException("Native Map Deleted");
       }
-      
+
       return sizeNM(nmPointer);
     } finally {
       rlock.unlock();
     }
   }
-  
+
   public long getMemoryUsed() {
     rlock.lock();
     try {
       if (nmPointer == 0) {
         throw new IllegalStateException("Native Map Deleted");
       }
-      
+
       return memoryUsedNM(nmPointer);
     } finally {
       rlock.unlock();
     }
   }
-  
+
+  @Override
   public Iterator<Map.Entry<Key,Value>> iterator() {
     rlock.lock();
     try {
       if (nmPointer == 0) {
         throw new IllegalStateException("Native Map Deleted");
       }
-      
+
       return new ConcurrentIterator();
     } finally {
       rlock.unlock();
     }
   }
-  
+
   public Iterator<Map.Entry<Key,Value>> iterator(Key startKey) {
     rlock.lock();
     try {
-      
+
       if (nmPointer == 0) {
         throw new IllegalStateException("Native Map Deleted");
       }
-      
+
       return new ConcurrentIterator(startKey);
     } finally {
       rlock.unlock();
     }
   }
-  
+
   public void delete() {
     wlock.lock();
     try {
       if (nmPointer == 0) {
         throw new IllegalStateException("Native Map Deleted");
       }
-      
+
       log.debug(String.format("Deallocating native map 0x%016x", nmPointer));
       deleteNativeMap(nmPointer);
       nmPointer = 0;
@@ -603,17 +678,17 @@ public class NativeMap implements Iterable<Map.Entry<Key,Value>> {
       wlock.unlock();
     }
   }
-  
+
   private static class NMSKVIter implements InterruptibleIterator {
-    
+
     private ConcurrentIterator iter;
     private Entry<Key,Value> entry;
-    
+
     private NativeMap map;
     private Range range;
     private AtomicBoolean interruptFlag;
     private int interruptCheckCount = 0;
-    
+
     private NMSKVIter(NativeMap map, AtomicBoolean interruptFlag) {
       this.map = map;
       this.range = new Range();
@@ -622,40 +697,40 @@ public class NativeMap implements Iterable<Map.Entry<Key,Value>> {
         entry = iter.next();
       else
         entry = null;
-      
+
       this.interruptFlag = interruptFlag;
     }
-    
+
     public NMSKVIter(NativeMap map) {
       this(map, null);
     }
-    
+
     @Override
     public Key getTopKey() {
       return entry.getKey();
     }
-    
+
     @Override
     public Value getTopValue() {
       return entry.getValue();
     }
-    
+
     @Override
     public boolean hasTop() {
       return entry != null;
     }
-    
+
     @Override
     public void next() throws IOException {
-      
+
       if (entry == null)
         throw new IllegalStateException();
-      
+
       // checking the interrupt flag for every call to next had bad a bad performance impact
       // so check it every 100th time
       if (interruptFlag != null && interruptCheckCount++ % 100 == 0 && interruptFlag.get())
         throw new IterationInterruptedException();
-      
+
       if (iter.hasNext()) {
         entry = iter.next();
         if (range.afterEndKey(entry.getKey())) {
@@ -663,24 +738,24 @@ public class NativeMap implements Iterable<Map.Entry<Key,Value>> {
         }
       } else
         entry = null;
-      
+
     }
-    
+
     @Override
     public void seek(Range range, Collection<ByteSequence> columnFamilies, boolean inclusive) throws IOException {
-      
+
       if (interruptFlag != null && interruptFlag.get())
         throw new IterationInterruptedException();
-      
+
       iter.delete();
-      
+
       this.range = range;
-      
+
       Key key = range.getStartKey();
       if (key == null) {
         key = new MemKey();
       }
-      
+
       iter = map.new ConcurrentIterator(key);
       if (iter.hasNext()) {
         entry = iter.next();
@@ -689,28 +764,28 @@ public class NativeMap implements Iterable<Map.Entry<Key,Value>> {
         }
       } else
         entry = null;
-      
+
       while (hasTop() && range.beforeStartKey(getTopKey())) {
         next();
       }
     }
-    
+
     @Override
     public void init(SortedKeyValueIterator<Key,Value> source, Map<String,String> options, IteratorEnvironment env) throws IOException {
       throw new UnsupportedOperationException();
     }
-    
+
     @Override
     public SortedKeyValueIterator<Key,Value> deepCopy(IteratorEnvironment env) {
       return new NMSKVIter(map, interruptFlag);
     }
-    
+
     @Override
     public void setInterruptFlag(AtomicBoolean flag) {
       this.interruptFlag = flag;
     }
   }
-  
+
   public SortedKeyValueIterator<Key,Value> skvIterator() {
     return new NMSKVIter(this);
   }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/bc65b369/server/tserver/src/main/java/org/apache/accumulo/tserver/TabletServerResourceManager.java
----------------------------------------------------------------------
diff --git a/server/tserver/src/main/java/org/apache/accumulo/tserver/TabletServerResourceManager.java b/server/tserver/src/main/java/org/apache/accumulo/tserver/TabletServerResourceManager.java
index 81ead34..e958437 100644
--- a/server/tserver/src/main/java/org/apache/accumulo/tserver/TabletServerResourceManager.java
+++ b/server/tserver/src/main/java/org/apache/accumulo/tserver/TabletServerResourceManager.java
@@ -152,7 +152,7 @@ public class TabletServerResourceManager {
     final AccumuloConfiguration acuConf = conf.getConfiguration();
 
     long maxMemory = acuConf.getMemoryInBytes(Property.TSERV_MAXMEM);
-    boolean usingNativeMap = acuConf.getBoolean(Property.TSERV_NATIVEMAP_ENABLED) && NativeMap.loadedNativeLibraries();
+    boolean usingNativeMap = acuConf.getBoolean(Property.TSERV_NATIVEMAP_ENABLED) && NativeMap.isLoaded();
 
     long blockSize = acuConf.getMemoryInBytes(Property.TSERV_DEFAULT_BLOCKSIZE);
     long dCacheSize = acuConf.getMemoryInBytes(Property.TSERV_DATACACHE_SIZE);

http://git-wip-us.apache.org/repos/asf/accumulo/blob/bc65b369/start/src/main/java/org/apache/accumulo/start/Platform.java
----------------------------------------------------------------------
diff --git a/start/src/main/java/org/apache/accumulo/start/Platform.java b/start/src/main/java/org/apache/accumulo/start/Platform.java
deleted file mode 100644
index a6d2d3d..0000000
--- a/start/src/main/java/org/apache/accumulo/start/Platform.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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 org.apache.accumulo.start;
-
-public class Platform {
-  public static void main(String[] args) {
-    System.out.println(getPlatform());
-  }
-  
-  public static String getPlatform() {
-    return (System.getProperty("os.name") + "-" + System.getProperty("os.arch") + "-" + System.getProperty("sun.arch.data.model")).replace(' ', '_');
-  }
-}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/bc65b369/test/pom.xml
----------------------------------------------------------------------
diff --git a/test/pom.xml b/test/pom.xml
index 6fe8148..831c280 100644
--- a/test/pom.xml
+++ b/test/pom.xml
@@ -67,6 +67,11 @@
     </dependency>
     <dependency>
       <groupId>org.apache.accumulo</groupId>
+      <artifactId>accumulo-native</artifactId>
+      <type>tar.gz</type>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.accumulo</groupId>
       <artifactId>accumulo-server-base</artifactId>
     </dependency>
     <dependency>

http://git-wip-us.apache.org/repos/asf/accumulo/blob/bc65b369/test/src/main/java/org/apache/accumulo/test/functional/NativeMapTest.java
----------------------------------------------------------------------
diff --git a/test/src/main/java/org/apache/accumulo/test/functional/NativeMapTest.java b/test/src/main/java/org/apache/accumulo/test/functional/NativeMapTest.java
deleted file mode 100644
index 3f904e7..0000000
--- a/test/src/main/java/org/apache/accumulo/test/functional/NativeMapTest.java
+++ /dev/null
@@ -1,654 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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 org.apache.accumulo.test.functional;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.Map.Entry;
-import java.util.NoSuchElementException;
-import java.util.Random;
-import java.util.TreeMap;
-
-import org.apache.accumulo.core.data.Key;
-import org.apache.accumulo.core.data.Value;
-import org.apache.accumulo.core.iterators.SortedKeyValueIterator;
-import org.apache.accumulo.core.util.Pair;
-import org.apache.accumulo.tserver.NativeMap;
-import org.apache.hadoop.io.Text;
-
-public class NativeMapTest {
-  
-  // BEGIN JUnit methods
-  // this used to be a unit test, but it would not
-  // run on the build server... so made it a functional
-  // test... in order to avoid a junit dependency
-  // the junit methods used were implemented here
-  
-  private void assertTrue(boolean b) {
-    if (!b) {
-      throw new RuntimeException();
-    }
-    
-  }
-  
-  private void assertEquals(Object o1, Object o2) {
-    if (!o1.equals(o2)) {
-      throw new RuntimeException(o1 + " != " + o2);
-    }
-  }
-  
-  private void assertFalse(boolean b) {
-    if (b)
-      throw new RuntimeException();
-  }
-  
-  private void assertNotNull(Object o) {
-    if (o == null)
-      throw new RuntimeException();
-  }
-  
-  private void assertNull(Object o) {
-    if (o != null)
-      throw new RuntimeException();
-  }
-  
-  public static void main(String[] args) throws Exception {
-    NativeMapTest nmt = new NativeMapTest();
-    nmt.setUp();
-    
-    nmt.test1();
-    nmt.test2();
-    nmt.test4();
-    nmt.test5();
-    nmt.test7();
-    nmt.test8();
-    nmt.test9();
-    nmt.test10();
-    nmt.test11();
-    nmt.testBinary();
-    nmt.testEmpty();
-    nmt.testConcurrentIter();
-    System.out.println("Ran to completion");
-  }
-  
-  // END JUnit methods
-  
-  private Key nk(int r) {
-    return new Key(new Text(String.format("r%09d", r)));
-  }
-  
-  private Key nk(int r, int cf, int cq, int cv, int ts, boolean deleted) {
-    Key k = new Key(new Text(String.format("r%09d", r)), new Text(String.format("cf%09d", cf)), new Text(String.format("cq%09d", cq)), new Text(String.format(
-        "cv%09d", cv)), ts);
-    
-    k.setDeleted(deleted);
-    
-    return k;
-  }
-  
-  private Value nv(int v) {
-    return new Value(String.format("r%09d", v).getBytes());
-  }
-  
-  public void setUp() {
-    if (!NativeMap.loadedNativeLibraries()) {
-      File f = new File(System.getProperty("user.dir"));
-      
-      while (f != null) {
-        File nativeLib = new File(f, NativeMap.getNativeLibPath());
-        if (nativeLib.exists()) {
-          break;
-        }
-        f = f.getParentFile();
-      }
-      
-      if (f != null) {
-        File nativeLib = new File(f, NativeMap.getNativeLibPath());
-        NativeMap.loadNativeLib(nativeLib.toString());
-      }
-    }
-    
-  }
-  
-  private void verifyIterator(int start, int end, int valueOffset, Iterator<Entry<Key,Value>> iter) {
-    for (int i = start; i <= end; i++) {
-      assertTrue(iter.hasNext());
-      Entry<Key,Value> entry = iter.next();
-      assertEquals(nk(i), entry.getKey());
-      assertEquals(nv(i + valueOffset), entry.getValue());
-    }
-    
-    assertFalse(iter.hasNext());
-  }
-  
-  private void insertAndVerify(NativeMap nm, int start, int end, int valueOffset) {
-    for (int i = start; i <= end; i++) {
-      nm.put(nk(i), nv(i + valueOffset));
-    }
-    
-    for (int i = start; i <= end; i++) {
-      Value v = nm.get(nk(i));
-      assertNotNull(v);
-      assertEquals(nv(i + valueOffset), v);
-      
-      Iterator<Entry<Key,Value>> iter2 = nm.iterator(nk(i));
-      assertTrue(iter2.hasNext());
-      Entry<Key,Value> entry = iter2.next();
-      assertEquals(nk(i), entry.getKey());
-      assertEquals(nv(i + valueOffset), entry.getValue());
-    }
-    
-    assertNull(nm.get(nk(start - 1)));
-    
-    assertNull(nm.get(nk(end + 1)));
-    
-    Iterator<Entry<Key,Value>> iter = nm.iterator();
-    verifyIterator(start, end, valueOffset, iter);
-    
-    for (int i = start; i <= end; i++) {
-      iter = nm.iterator(nk(i));
-      verifyIterator(i, end, valueOffset, iter);
-      
-      // lookup nonexistant key that falls after existing key
-      iter = nm.iterator(nk(i, 1, 1, 1, 1, false));
-      verifyIterator(i + 1, end, valueOffset, iter);
-    }
-    
-    assertEquals(end - start + 1, nm.size());
-  }
-  
-  private void insertAndVerifyExhaustive(NativeMap nm, int num, int run) {
-    for (int i = 0; i < num; i++) {
-      for (int j = 0; j < num; j++) {
-        for (int k = 0; k < num; k++) {
-          for (int l = 0; l < num; l++) {
-            for (int ts = 0; ts < num; ts++) {
-              Key key = nk(i, j, k, l, ts, true);
-              Value value = new Value((i + "_" + j + "_" + k + "_" + l + "_" + ts + "_" + true + "_" + run).getBytes());
-              
-              nm.put(key, value);
-              
-              key = nk(i, j, k, l, ts, false);
-              value = new Value((i + "_" + j + "_" + k + "_" + l + "_" + ts + "_" + false + "_" + run).getBytes());
-              
-              nm.put(key, value);
-            }
-          }
-        }
-      }
-    }
-    
-    Iterator<Entry<Key,Value>> iter = nm.iterator();
-    
-    for (int i = 0; i < num; i++) {
-      for (int j = 0; j < num; j++) {
-        for (int k = 0; k < num; k++) {
-          for (int l = 0; l < num; l++) {
-            for (int ts = num - 1; ts >= 0; ts--) {
-              Key key = nk(i, j, k, l, ts, true);
-              Value value = new Value((i + "_" + j + "_" + k + "_" + l + "_" + ts + "_" + true + "_" + run).getBytes());
-              
-              assertTrue(iter.hasNext());
-              Entry<Key,Value> entry = iter.next();
-              assertEquals(key, entry.getKey());
-              assertEquals(value, entry.getValue());
-              
-              key = nk(i, j, k, l, ts, false);
-              value = new Value((i + "_" + j + "_" + k + "_" + l + "_" + ts + "_" + false + "_" + run).getBytes());
-              
-              assertTrue(iter.hasNext());
-              entry = iter.next();
-              assertEquals(key, entry.getKey());
-              assertEquals(value, entry.getValue());
-            }
-          }
-        }
-      }
-    }
-    
-    assertFalse(iter.hasNext());
-    
-    for (int i = 0; i < num; i++) {
-      for (int j = 0; j < num; j++) {
-        for (int k = 0; k < num; k++) {
-          for (int l = 0; l < num; l++) {
-            for (int ts = 0; ts < num; ts++) {
-              Key key = nk(i, j, k, l, ts, true);
-              Value value = new Value((i + "_" + j + "_" + k + "_" + l + "_" + ts + "_" + true + "_" + run).getBytes());
-              
-              assertEquals(value, nm.get(key));
-              
-              Iterator<Entry<Key,Value>> iter2 = nm.iterator(key);
-              assertTrue(iter2.hasNext());
-              Entry<Key,Value> entry = iter2.next();
-              assertEquals(key, entry.getKey());
-              assertEquals(value, entry.getValue());
-              
-              key = nk(i, j, k, l, ts, false);
-              value = new Value((i + "_" + j + "_" + k + "_" + l + "_" + ts + "_" + false + "_" + run).getBytes());
-              
-              assertEquals(value, nm.get(key));
-              
-              Iterator<Entry<Key,Value>> iter3 = nm.iterator(key);
-              assertTrue(iter3.hasNext());
-              Entry<Key,Value> entry2 = iter3.next();
-              assertEquals(key, entry2.getKey());
-              assertEquals(value, entry2.getValue());
-            }
-          }
-        }
-      }
-    }
-    
-    assertEquals(num * num * num * num * num * 2, nm.size());
-  }
-  
-  public void test1() {
-    NativeMap nm = new NativeMap();
-    Iterator<Entry<Key,Value>> iter = nm.iterator();
-    assertFalse(iter.hasNext());
-    nm.delete();
-  }
-  
-  public void test2() {
-    NativeMap nm = new NativeMap();
-    
-    insertAndVerify(nm, 1, 10, 0);
-    insertAndVerify(nm, 1, 10, 1);
-    insertAndVerify(nm, 1, 10, 2);
-    
-    nm.delete();
-  }
-  
-  public void test4() {
-    NativeMap nm = new NativeMap();
-    
-    insertAndVerifyExhaustive(nm, 3, 0);
-    insertAndVerifyExhaustive(nm, 3, 1);
-    
-    nm.delete();
-  }
-  
-  public void test5() {
-    NativeMap nm = new NativeMap();
-    
-    insertAndVerify(nm, 1, 10, 0);
-    
-    Iterator<Entry<Key,Value>> iter = nm.iterator();
-    iter.next();
-    
-    nm.delete();
-    
-    try {
-      nm.put(nk(1), nv(1));
-      assertTrue(false);
-    } catch (IllegalStateException e) {
-      
-    }
-    
-    try {
-      nm.get(nk(1));
-      assertTrue(false);
-    } catch (IllegalStateException e) {
-      
-    }
-    
-    try {
-      nm.iterator();
-      assertTrue(false);
-    } catch (IllegalStateException e) {
-      
-    }
-    
-    try {
-      nm.iterator(nk(1));
-      assertTrue(false);
-    } catch (IllegalStateException e) {
-      
-    }
-    
-    try {
-      nm.size();
-      assertTrue(false);
-    } catch (IllegalStateException e) {
-      
-    }
-    
-    try {
-      iter.next();
-      assertTrue(false);
-    } catch (IllegalStateException e) {
-      
-    }
-    
-  }
-  
-  public void test7() {
-    NativeMap nm = new NativeMap();
-    
-    insertAndVerify(nm, 1, 10, 0);
-    
-    nm.delete();
-    
-    try {
-      nm.delete();
-      assertTrue(false);
-    } catch (IllegalStateException e) {
-      
-    }
-  }
-  
-  public void test8() {
-    // test verifies that native map sorts keys sharing some common prefix properly
-    
-    NativeMap nm = new NativeMap();
-    
-    TreeMap<Key,Value> tm = new TreeMap<Key,Value>();
-    
-    tm.put(new Key(new Text("fo")), new Value("0".getBytes()));
-    tm.put(new Key(new Text("foo")), new Value("1".getBytes()));
-    tm.put(new Key(new Text("foo1")), new Value("2".getBytes()));
-    tm.put(new Key(new Text("foo2")), new Value("3".getBytes()));
-    
-    for (Entry<Key,Value> entry : tm.entrySet()) {
-      nm.put(entry.getKey(), entry.getValue());
-    }
-    
-    Iterator<Entry<Key,Value>> iter = nm.iterator();
-    
-    for (Entry<Key,Value> entry : tm.entrySet()) {
-      assertTrue(iter.hasNext());
-      Entry<Key,Value> entry2 = iter.next();
-      
-      assertEquals(entry.getKey(), entry2.getKey());
-      assertEquals(entry.getValue(), entry2.getValue());
-    }
-    
-    assertFalse(iter.hasNext());
-    
-    nm.delete();
-  }
-  
-  public void test9() {
-    NativeMap nm = new NativeMap();
-    
-    Iterator<Entry<Key,Value>> iter = nm.iterator();
-    
-    try {
-      iter.next();
-      assertTrue(false);
-    } catch (NoSuchElementException e) {
-      
-    }
-    
-    insertAndVerify(nm, 1, 1, 0);
-    
-    iter = nm.iterator();
-    iter.next();
-    
-    try {
-      iter.next();
-      assertTrue(false);
-    } catch (NoSuchElementException e) {
-      
-    }
-    
-    nm.delete();
-  }
-  
-  public void test10() {
-    int start = 1;
-    int end = 10000;
-    
-    NativeMap nm = new NativeMap();
-    for (int i = start; i <= end; i++) {
-      nm.put(nk(i), nv(i));
-    }
-    
-    long mem1 = nm.getMemoryUsed();
-    
-    for (int i = start; i <= end; i++) {
-      nm.put(nk(i), nv(i));
-    }
-    
-    long mem2 = nm.getMemoryUsed();
-    
-    if (mem1 != mem2) {
-      throw new RuntimeException("Memory changed after inserting duplicate data " + mem1 + " " + mem2);
-    }
-    
-    for (int i = start; i <= end; i++) {
-      nm.put(nk(i), nv(i));
-    }
-    
-    long mem3 = nm.getMemoryUsed();
-    
-    if (mem1 != mem3) {
-      throw new RuntimeException("Memory changed after inserting duplicate data " + mem1 + " " + mem3);
-    }
-    
-    byte bigrow[] = new byte[1000000];
-    byte bigvalue[] = new byte[bigrow.length];
-    
-    for (int i = 0; i < bigrow.length; i++) {
-      bigrow[i] = (byte) (0xff & (i % 256));
-      bigvalue[i] = bigrow[i];
-    }
-    
-    nm.put(new Key(new Text(bigrow)), new Value(bigvalue));
-    
-    long mem4 = nm.getMemoryUsed();
-    
-    Value val = nm.get(new Key(new Text(bigrow)));
-    if (val == null || !val.equals(new Value(bigvalue))) {
-      throw new RuntimeException("Did not get expected big value");
-    }
-    
-    nm.put(new Key(new Text(bigrow)), new Value(bigvalue));
-    
-    long mem5 = nm.getMemoryUsed();
-    
-    if (mem4 != mem5) {
-      throw new RuntimeException("Memory changed after inserting duplicate data " + mem4 + " " + mem5);
-    }
-    
-    val = nm.get(new Key(new Text(bigrow)));
-    if (val == null || !val.equals(new Value(bigvalue))) {
-      throw new RuntimeException("Did not get expected big value");
-    }
-    
-    nm.delete();
-  }
-  
-  // random length random field
-  private static byte[] rlrf(Random r, int maxLen) {
-    int len = r.nextInt(maxLen);
-    
-    byte f[] = new byte[len];
-    r.nextBytes(f);
-    
-    return f;
-  }
-  
-  public void test11() {
-    NativeMap nm = new NativeMap();
-    
-    // insert things with varying field sizes and value sizes
-    
-    // generate random data
-    Random r = new Random(75);
-    
-    ArrayList<Pair<Key,Value>> testData = new ArrayList<Pair<Key,Value>>();
-    
-    for (int i = 0; i < 100000; i++) {
-      
-      Key k = new Key(rlrf(r, 97), rlrf(r, 13), rlrf(r, 31), rlrf(r, 11), (r.nextLong() & 0x7fffffffffffffffl), false, false);
-      Value v = new Value(rlrf(r, 511));
-      
-      testData.add(new Pair<Key,Value>(k, v));
-    }
-    
-    // insert unsorted data
-    for (Pair<Key,Value> pair : testData) {
-      nm.put(pair.getFirst(), pair.getSecond());
-    }
-    
-    for (int i = 0; i < 2; i++) {
-      
-      // sort data
-      Collections.sort(testData, new Comparator<Pair<Key,Value>>() {
-        @Override
-        public int compare(Pair<Key,Value> o1, Pair<Key,Value> o2) {
-          return o1.getFirst().compareTo(o2.getFirst());
-        }
-      });
-      
-      // verify
-      Iterator<Entry<Key,Value>> iter1 = nm.iterator();
-      Iterator<Pair<Key,Value>> iter2 = testData.iterator();
-      
-      while (iter1.hasNext() && iter2.hasNext()) {
-        Entry<Key,Value> e = iter1.next();
-        Pair<Key,Value> p = iter2.next();
-        
-        if (!e.getKey().equals(p.getFirst()))
-          throw new RuntimeException("Keys not equal");
-        
-        if (!e.getValue().equals(p.getSecond()))
-          throw new RuntimeException("Values not equal");
-      }
-      
-      if (iter1.hasNext())
-        throw new RuntimeException("Not all of native map consumed");
-      
-      if (iter2.hasNext())
-        throw new RuntimeException("Not all of test data consumed");
-      
-      System.out.println("test 11 nm mem " + nm.getMemoryUsed());
-      
-      // insert data again w/ different value
-      Collections.shuffle(testData, r);
-      // insert unsorted data
-      for (Pair<Key,Value> pair : testData) {
-        pair.getSecond().set(rlrf(r, 511));
-        nm.put(pair.getFirst(), pair.getSecond());
-      }
-    }
-    
-    nm.delete();
-  }
-  
-  public void testBinary() {
-    NativeMap nm = new NativeMap();
-    
-    byte emptyBytes[] = new byte[0];
-    
-    for (int i = 0; i < 256; i++) {
-      for (int j = 0; j < 256; j++) {
-        byte row[] = new byte[] {'r', (byte) (0xff & i), (byte) (0xff & j)};
-        byte data[] = new byte[] {'v', (byte) (0xff & i), (byte) (0xff & j)};
-        
-        Key k = new Key(row, emptyBytes, emptyBytes, emptyBytes, 1);
-        Value v = new Value(data);
-        
-        nm.put(k, v);
-      }
-    }
-    
-    Iterator<Entry<Key,Value>> iter = nm.iterator();
-    for (int i = 0; i < 256; i++) {
-      for (int j = 0; j < 256; j++) {
-        byte row[] = new byte[] {'r', (byte) (0xff & i), (byte) (0xff & j)};
-        byte data[] = new byte[] {'v', (byte) (0xff & i), (byte) (0xff & j)};
-        
-        Key k = new Key(row, emptyBytes, emptyBytes, emptyBytes, 1);
-        Value v = new Value(data);
-        
-        assertTrue(iter.hasNext());
-        Entry<Key,Value> entry = iter.next();
-        
-        assertEquals(k, entry.getKey());
-        assertEquals(v, entry.getValue());
-        
-      }
-    }
-    
-    assertFalse(iter.hasNext());
-    
-    for (int i = 0; i < 256; i++) {
-      for (int j = 0; j < 256; j++) {
-        byte row[] = new byte[] {'r', (byte) (0xff & i), (byte) (0xff & j)};
-        byte data[] = new byte[] {'v', (byte) (0xff & i), (byte) (0xff & j)};
-        
-        Key k = new Key(row, emptyBytes, emptyBytes, emptyBytes, 1);
-        Value v = new Value(data);
-        
-        Value v2 = nm.get(k);
-        
-        assertEquals(v, v2);
-      }
-    }
-    
-    nm.delete();
-  }
-  
-  public void testEmpty() {
-    NativeMap nm = new NativeMap();
-    
-    assertTrue(nm.size() == 0);
-    assertTrue(nm.getMemoryUsed() == 0);
-    
-    nm.delete();
-  }
-  
-  public void testConcurrentIter() throws IOException {
-    NativeMap nm = new NativeMap();
-    
-    nm.put(nk(0), nv(0));
-    nm.put(nk(1), nv(1));
-    nm.put(nk(3), nv(3));
-    
-    SortedKeyValueIterator<Key,Value> iter = nm.skvIterator();
-    
-    // modify map after iter created
-    nm.put(nk(2), nv(2));
-    
-    assertTrue(iter.hasTop());
-    assertEquals(iter.getTopKey(), nk(0));
-    iter.next();
-    
-    assertTrue(iter.hasTop());
-    assertEquals(iter.getTopKey(), nk(1));
-    iter.next();
-    
-    assertTrue(iter.hasTop());
-    assertEquals(iter.getTopKey(), nk(2));
-    iter.next();
-    
-    assertTrue(iter.hasTop());
-    assertEquals(iter.getTopKey(), nk(3));
-    iter.next();
-    
-    assertFalse(iter.hasTop());
-    
-    nm.delete();
-  }
-}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/bc65b369/test/src/test/java/org/apache/accumulo/test/MultiTableBatchWriterTest.java
----------------------------------------------------------------------
diff --git a/test/src/test/java/org/apache/accumulo/test/MultiTableBatchWriterTest.java b/test/src/test/java/org/apache/accumulo/test/MultiTableBatchWriterTest.java
index 4fe3d3f..ace5d24 100644
--- a/test/src/test/java/org/apache/accumulo/test/MultiTableBatchWriterTest.java
+++ b/test/src/test/java/org/apache/accumulo/test/MultiTableBatchWriterTest.java
@@ -68,8 +68,8 @@ public class MultiTableBatchWriterTest {
   public static void tearDownAfterClass() throws Exception {
     cluster.stop();
     folder.delete();
- }
-  
+  }
+
   @Test
   public void testTableRenameDataValidation() throws Exception {
     ZooKeeperInstance instance = new ZooKeeperInstance(new ClientConfiguration().withInstance(cluster.getInstanceName()).withZkHosts(cluster.getZooKeepers()));
@@ -97,7 +97,7 @@ public class MultiTableBatchWriterTest {
       tops.create(table1);
 
       BatchWriter bw2 = mtbw.getBatchWriter(table1);
-      
+
       Mutation m2 = new Mutation("bar");
       m2.put("col1", "", "val1");
 
@@ -130,7 +130,7 @@ public class MultiTableBatchWriterTest {
       }
 
       Assert.assertEquals("Differing results for " + table2, table2Expectations, actual);
-      
+
     } finally {
       if (null != mtbw) {
         mtbw.close();
@@ -239,14 +239,14 @@ public class MultiTableBatchWriterTest {
       }
 
       tops.rename(table2, newTable2);
-      
+
       try {
         bw2 = mtbw.getBatchWriter(table2);
         Assert.fail("Should not be able to find this table");
       } catch (TableNotFoundException e) {
-        //pass
+        // pass
       }
-      
+
       bw1 = mtbw.getBatchWriter(newTable1);
       bw2 = mtbw.getBatchWriter(newTable2);
 
@@ -288,7 +288,7 @@ public class MultiTableBatchWriterTest {
     Connector connector = instance.getConnector("root", password);
 
     BatchWriterConfig config = new BatchWriterConfig();
-    
+
     Credentials creds = new Credentials("root", password);
     MultiTableBatchWriter mtbw = new MultiTableBatchWriterImpl(instance, creds, config, 0, TimeUnit.SECONDS);
 
@@ -450,7 +450,7 @@ public class MultiTableBatchWriterTest {
     Connector connector = instance.getConnector("root", password);
 
     BatchWriterConfig config = new BatchWriterConfig();
-    
+
     Credentials creds = new Credentials("root", password);
     MultiTableBatchWriter mtbw = new MultiTableBatchWriterImpl(instance, creds, config, 60, TimeUnit.SECONDS);
     boolean mutationsRejected = false;

http://git-wip-us.apache.org/repos/asf/accumulo/blob/bc65b369/test/src/test/java/org/apache/accumulo/test/functional/NativeMapIT.java
----------------------------------------------------------------------
diff --git a/test/src/test/java/org/apache/accumulo/test/functional/NativeMapIT.java b/test/src/test/java/org/apache/accumulo/test/functional/NativeMapIT.java
index 32be35d..408d32c 100644
--- a/test/src/test/java/org/apache/accumulo/test/functional/NativeMapIT.java
+++ b/test/src/test/java/org/apache/accumulo/test/functional/NativeMapIT.java
@@ -17,14 +17,592 @@
 package org.apache.accumulo.test.functional;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.Map.Entry;
+import java.util.NoSuchElementException;
+import java.util.Random;
+import java.util.TreeMap;
+
+import org.apache.accumulo.core.Constants;
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Value;
+import org.apache.accumulo.core.iterators.SortedKeyValueIterator;
+import org.apache.accumulo.core.util.Pair;
+import org.apache.accumulo.tserver.NativeMap;
+import org.apache.hadoop.io.Text;
+import org.junit.BeforeClass;
 import org.junit.Test;
 
-public class NativeMapIT extends ConfigurableMacIT {
+public class NativeMapIT {
+
+  private Key nk(int r) {
+    return new Key(new Text(String.format("r%09d", r)));
+  }
+
+  private Key nk(int r, int cf, int cq, int cv, int ts, boolean deleted) {
+    Key k = new Key(new Text(String.format("r%09d", r)), new Text(String.format("cf%09d", cf)), new Text(String.format("cq%09d", cq)), new Text(String.format(
+        "cv%09d", cv)), ts);
+
+    k.setDeleted(deleted);
+
+    return k;
+  }
+
+  private Value nv(int v) {
+    return new Value(String.format("r%09d", v).getBytes());
+  }
+
+  @BeforeClass
+  public static void setUp() {
+    File projectDir = new File(System.getProperty("user.dir")).getParentFile();
+    File nativeMapDir = new File(projectDir, "server/native/target/accumulo-native-" + Constants.VERSION + "/accumulo-native-" + Constants.VERSION);
+    NativeMap.loadNativeLib(Collections.singletonList(nativeMapDir));
+  }
+
+  private void verifyIterator(int start, int end, int valueOffset, Iterator<Entry<Key,Value>> iter) {
+    for (int i = start; i <= end; i++) {
+      assertTrue(iter.hasNext());
+      Entry<Key,Value> entry = iter.next();
+      assertEquals(nk(i), entry.getKey());
+      assertEquals(nv(i + valueOffset), entry.getValue());
+    }
+
+    assertFalse(iter.hasNext());
+  }
+
+  private void insertAndVerify(NativeMap nm, int start, int end, int valueOffset) {
+    for (int i = start; i <= end; i++) {
+      nm.put(nk(i), nv(i + valueOffset));
+    }
+
+    for (int i = start; i <= end; i++) {
+      Value v = nm.get(nk(i));
+      assertNotNull(v);
+      assertEquals(nv(i + valueOffset), v);
+
+      Iterator<Entry<Key,Value>> iter2 = nm.iterator(nk(i));
+      assertTrue(iter2.hasNext());
+      Entry<Key,Value> entry = iter2.next();
+      assertEquals(nk(i), entry.getKey());
+      assertEquals(nv(i + valueOffset), entry.getValue());
+    }
+
+    assertNull(nm.get(nk(start - 1)));
+
+    assertNull(nm.get(nk(end + 1)));
+
+    Iterator<Entry<Key,Value>> iter = nm.iterator();
+    verifyIterator(start, end, valueOffset, iter);
+
+    for (int i = start; i <= end; i++) {
+      iter = nm.iterator(nk(i));
+      verifyIterator(i, end, valueOffset, iter);
+
+      // lookup nonexistant key that falls after existing key
+      iter = nm.iterator(nk(i, 1, 1, 1, 1, false));
+      verifyIterator(i + 1, end, valueOffset, iter);
+    }
+
+    assertEquals(end - start + 1, nm.size());
+  }
+
+  private void insertAndVerifyExhaustive(NativeMap nm, int num, int run) {
+    for (int i = 0; i < num; i++) {
+      for (int j = 0; j < num; j++) {
+        for (int k = 0; k < num; k++) {
+          for (int l = 0; l < num; l++) {
+            for (int ts = 0; ts < num; ts++) {
+              Key key = nk(i, j, k, l, ts, true);
+              Value value = new Value((i + "_" + j + "_" + k + "_" + l + "_" + ts + "_" + true + "_" + run).getBytes());
+
+              nm.put(key, value);
+
+              key = nk(i, j, k, l, ts, false);
+              value = new Value((i + "_" + j + "_" + k + "_" + l + "_" + ts + "_" + false + "_" + run).getBytes());
+
+              nm.put(key, value);
+            }
+          }
+        }
+      }
+    }
+
+    Iterator<Entry<Key,Value>> iter = nm.iterator();
+
+    for (int i = 0; i < num; i++) {
+      for (int j = 0; j < num; j++) {
+        for (int k = 0; k < num; k++) {
+          for (int l = 0; l < num; l++) {
+            for (int ts = num - 1; ts >= 0; ts--) {
+              Key key = nk(i, j, k, l, ts, true);
+              Value value = new Value((i + "_" + j + "_" + k + "_" + l + "_" + ts + "_" + true + "_" + run).getBytes());
+
+              assertTrue(iter.hasNext());
+              Entry<Key,Value> entry = iter.next();
+              assertEquals(key, entry.getKey());
+              assertEquals(value, entry.getValue());
+
+              key = nk(i, j, k, l, ts, false);
+              value = new Value((i + "_" + j + "_" + k + "_" + l + "_" + ts + "_" + false + "_" + run).getBytes());
+
+              assertTrue(iter.hasNext());
+              entry = iter.next();
+              assertEquals(key, entry.getKey());
+              assertEquals(value, entry.getValue());
+            }
+          }
+        }
+      }
+    }
+
+    assertFalse(iter.hasNext());
+
+    for (int i = 0; i < num; i++) {
+      for (int j = 0; j < num; j++) {
+        for (int k = 0; k < num; k++) {
+          for (int l = 0; l < num; l++) {
+            for (int ts = 0; ts < num; ts++) {
+              Key key = nk(i, j, k, l, ts, true);
+              Value value = new Value((i + "_" + j + "_" + k + "_" + l + "_" + ts + "_" + true + "_" + run).getBytes());
+
+              assertEquals(value, nm.get(key));
+
+              Iterator<Entry<Key,Value>> iter2 = nm.iterator(key);
+              assertTrue(iter2.hasNext());
+              Entry<Key,Value> entry = iter2.next();
+              assertEquals(key, entry.getKey());
+              assertEquals(value, entry.getValue());
+
+              key = nk(i, j, k, l, ts, false);
+              value = new Value((i + "_" + j + "_" + k + "_" + l + "_" + ts + "_" + false + "_" + run).getBytes());
+
+              assertEquals(value, nm.get(key));
+
+              Iterator<Entry<Key,Value>> iter3 = nm.iterator(key);
+              assertTrue(iter3.hasNext());
+              Entry<Key,Value> entry2 = iter3.next();
+              assertEquals(key, entry2.getKey());
+              assertEquals(value, entry2.getValue());
+            }
+          }
+        }
+      }
+    }
+
+    assertEquals(num * num * num * num * num * 2, nm.size());
+  }
+
+  @Test
+  public void test1() {
+    NativeMap nm = new NativeMap();
+    Iterator<Entry<Key,Value>> iter = nm.iterator();
+    assertFalse(iter.hasNext());
+    nm.delete();
+  }
+
+  @Test
+  public void test2() {
+    NativeMap nm = new NativeMap();
+
+    insertAndVerify(nm, 1, 10, 0);
+    insertAndVerify(nm, 1, 10, 1);
+    insertAndVerify(nm, 1, 10, 2);
+
+    nm.delete();
+  }
+
+  @Test
+  public void test4() {
+    NativeMap nm = new NativeMap();
+
+    insertAndVerifyExhaustive(nm, 3, 0);
+    insertAndVerifyExhaustive(nm, 3, 1);
+
+    nm.delete();
+  }
+
+  @Test
+  public void test5() {
+    NativeMap nm = new NativeMap();
+
+    insertAndVerify(nm, 1, 10, 0);
+
+    Iterator<Entry<Key,Value>> iter = nm.iterator();
+    iter.next();
+
+    nm.delete();
+
+    try {
+      nm.put(nk(1), nv(1));
+      assertTrue(false);
+    } catch (IllegalStateException e) {
+
+    }
+
+    try {
+      nm.get(nk(1));
+      assertTrue(false);
+    } catch (IllegalStateException e) {
+
+    }
+
+    try {
+      nm.iterator();
+      assertTrue(false);
+    } catch (IllegalStateException e) {
+
+    }
+
+    try {
+      nm.iterator(nk(1));
+      assertTrue(false);
+    } catch (IllegalStateException e) {
+
+    }
+
+    try {
+      nm.size();
+      assertTrue(false);
+    } catch (IllegalStateException e) {
+
+    }
+
+    try {
+      iter.next();
+      assertTrue(false);
+    } catch (IllegalStateException e) {
+
+    }
+
+  }
+
+  @Test
+  public void test7() {
+    NativeMap nm = new NativeMap();
+
+    insertAndVerify(nm, 1, 10, 0);
+
+    nm.delete();
+
+    try {
+      nm.delete();
+      assertTrue(false);
+    } catch (IllegalStateException e) {
+
+    }
+  }
+
+  @Test
+  public void test8() {
+    // test verifies that native map sorts keys sharing some common prefix properly
+
+    NativeMap nm = new NativeMap();
+
+    TreeMap<Key,Value> tm = new TreeMap<Key,Value>();
+
+    tm.put(new Key(new Text("fo")), new Value("0".getBytes()));
+    tm.put(new Key(new Text("foo")), new Value("1".getBytes()));
+    tm.put(new Key(new Text("foo1")), new Value("2".getBytes()));
+    tm.put(new Key(new Text("foo2")), new Value("3".getBytes()));
+
+    for (Entry<Key,Value> entry : tm.entrySet()) {
+      nm.put(entry.getKey(), entry.getValue());
+    }
+
+    Iterator<Entry<Key,Value>> iter = nm.iterator();
+
+    for (Entry<Key,Value> entry : tm.entrySet()) {
+      assertTrue(iter.hasNext());
+      Entry<Key,Value> entry2 = iter.next();
+
+      assertEquals(entry.getKey(), entry2.getKey());
+      assertEquals(entry.getValue(), entry2.getValue());
+    }
+
+    assertFalse(iter.hasNext());
+
+    nm.delete();
+  }
+
+  @Test
+  public void test9() {
+    NativeMap nm = new NativeMap();
+
+    Iterator<Entry<Key,Value>> iter = nm.iterator();
+
+    try {
+      iter.next();
+      assertTrue(false);
+    } catch (NoSuchElementException e) {
+
+    }
+
+    insertAndVerify(nm, 1, 1, 0);
+
+    iter = nm.iterator();
+    iter.next();
+
+    try {
+      iter.next();
+      assertTrue(false);
+    } catch (NoSuchElementException e) {
+
+    }
+
+    nm.delete();
+  }
+
+  @Test
+  public void test10() {
+    int start = 1;
+    int end = 10000;
+
+    NativeMap nm = new NativeMap();
+    for (int i = start; i <= end; i++) {
+      nm.put(nk(i), nv(i));
+    }
+
+    long mem1 = nm.getMemoryUsed();
+
+    for (int i = start; i <= end; i++) {
+      nm.put(nk(i), nv(i));
+    }
+
+    long mem2 = nm.getMemoryUsed();
+
+    if (mem1 != mem2) {
+      throw new RuntimeException("Memory changed after inserting duplicate data " + mem1 + " " + mem2);
+    }
+
+    for (int i = start; i <= end; i++) {
+      nm.put(nk(i), nv(i));
+    }
+
+    long mem3 = nm.getMemoryUsed();
+
+    if (mem1 != mem3) {
+      throw new RuntimeException("Memory changed after inserting duplicate data " + mem1 + " " + mem3);
+    }
+
+    byte bigrow[] = new byte[1000000];
+    byte bigvalue[] = new byte[bigrow.length];
+
+    for (int i = 0; i < bigrow.length; i++) {
+      bigrow[i] = (byte) (0xff & (i % 256));
+      bigvalue[i] = bigrow[i];
+    }
+
+    nm.put(new Key(new Text(bigrow)), new Value(bigvalue));
+
+    long mem4 = nm.getMemoryUsed();
+
+    Value val = nm.get(new Key(new Text(bigrow)));
+    if (val == null || !val.equals(new Value(bigvalue))) {
+      throw new RuntimeException("Did not get expected big value");
+    }
+
+    nm.put(new Key(new Text(bigrow)), new Value(bigvalue));
+
+    long mem5 = nm.getMemoryUsed();
+
+    if (mem4 != mem5) {
+      throw new RuntimeException("Memory changed after inserting duplicate data " + mem4 + " " + mem5);
+    }
+
+    val = nm.get(new Key(new Text(bigrow)));
+    if (val == null || !val.equals(new Value(bigvalue))) {
+      throw new RuntimeException("Did not get expected big value");
+    }
+
+    nm.delete();
+  }
+
+  // random length random field
+  private static byte[] rlrf(Random r, int maxLen) {
+    int len = r.nextInt(maxLen);
+
+    byte f[] = new byte[len];
+    r.nextBytes(f);
+
+    return f;
+  }
+
+  @Test
+  public void test11() {
+    NativeMap nm = new NativeMap();
+
+    // insert things with varying field sizes and value sizes
+
+    // generate random data
+    Random r = new Random(75);
+
+    ArrayList<Pair<Key,Value>> testData = new ArrayList<Pair<Key,Value>>();
+
+    for (int i = 0; i < 100000; i++) {
+
+      Key k = new Key(rlrf(r, 97), rlrf(r, 13), rlrf(r, 31), rlrf(r, 11), (r.nextLong() & 0x7fffffffffffffffl), false, false);
+      Value v = new Value(rlrf(r, 511));
+
+      testData.add(new Pair<Key,Value>(k, v));
+    }
+
+    // insert unsorted data
+    for (Pair<Key,Value> pair : testData) {
+      nm.put(pair.getFirst(), pair.getSecond());
+    }
+
+    for (int i = 0; i < 2; i++) {
+
+      // sort data
+      Collections.sort(testData, new Comparator<Pair<Key,Value>>() {
+        @Override
+        public int compare(Pair<Key,Value> o1, Pair<Key,Value> o2) {
+          return o1.getFirst().compareTo(o2.getFirst());
+        }
+      });
+
+      // verify
+      Iterator<Entry<Key,Value>> iter1 = nm.iterator();
+      Iterator<Pair<Key,Value>> iter2 = testData.iterator();
+
+      while (iter1.hasNext() && iter2.hasNext()) {
+        Entry<Key,Value> e = iter1.next();
+        Pair<Key,Value> p = iter2.next();
+
+        if (!e.getKey().equals(p.getFirst()))
+          throw new RuntimeException("Keys not equal");
+
+        if (!e.getValue().equals(p.getSecond()))
+          throw new RuntimeException("Values not equal");
+      }
+
+      if (iter1.hasNext())
+        throw new RuntimeException("Not all of native map consumed");
+
+      if (iter2.hasNext())
+        throw new RuntimeException("Not all of test data consumed");
+
+      System.out.println("test 11 nm mem " + nm.getMemoryUsed());
+
+      // insert data again w/ different value
+      Collections.shuffle(testData, r);
+      // insert unsorted data
+      for (Pair<Key,Value> pair : testData) {
+        pair.getSecond().set(rlrf(r, 511));
+        nm.put(pair.getFirst(), pair.getSecond());
+      }
+    }
+
+    nm.delete();
+  }
+
+  @Test
+  public void testBinary() {
+    NativeMap nm = new NativeMap();
+
+    byte emptyBytes[] = new byte[0];
+
+    for (int i = 0; i < 256; i++) {
+      for (int j = 0; j < 256; j++) {
+        byte row[] = new byte[] {'r', (byte) (0xff & i), (byte) (0xff & j)};
+        byte data[] = new byte[] {'v', (byte) (0xff & i), (byte) (0xff & j)};
+
+        Key k = new Key(row, emptyBytes, emptyBytes, emptyBytes, 1);
+        Value v = new Value(data);
+
+        nm.put(k, v);
+      }
+    }
+
+    Iterator<Entry<Key,Value>> iter = nm.iterator();
+    for (int i = 0; i < 256; i++) {
+      for (int j = 0; j < 256; j++) {
+        byte row[] = new byte[] {'r', (byte) (0xff & i), (byte) (0xff & j)};
+        byte data[] = new byte[] {'v', (byte) (0xff & i), (byte) (0xff & j)};
+
+        Key k = new Key(row, emptyBytes, emptyBytes, emptyBytes, 1);
+        Value v = new Value(data);
+
+        assertTrue(iter.hasNext());
+        Entry<Key,Value> entry = iter.next();
+
+        assertEquals(k, entry.getKey());
+        assertEquals(v, entry.getValue());
+
+      }
+    }
+
+    assertFalse(iter.hasNext());
+
+    for (int i = 0; i < 256; i++) {
+      for (int j = 0; j < 256; j++) {
+        byte row[] = new byte[] {'r', (byte) (0xff & i), (byte) (0xff & j)};
+        byte data[] = new byte[] {'v', (byte) (0xff & i), (byte) (0xff & j)};
+
+        Key k = new Key(row, emptyBytes, emptyBytes, emptyBytes, 1);
+        Value v = new Value(data);
+
+        Value v2 = nm.get(k);
+
+        assertEquals(v, v2);
+      }
+    }
+
+    nm.delete();
+  }
+
+  @Test
+  public void testEmpty() {
+    NativeMap nm = new NativeMap();
+
+    assertTrue(nm.size() == 0);
+    assertTrue(nm.getMemoryUsed() == 0);
+
+    nm.delete();
+  }
+
+  @Test
+  public void testConcurrentIter() throws IOException {
+    NativeMap nm = new NativeMap();
+
+    nm.put(nk(0), nv(0));
+    nm.put(nk(1), nv(1));
+    nm.put(nk(3), nv(3));
+
+    SortedKeyValueIterator<Key,Value> iter = nm.skvIterator();
+
+    // modify map after iter created
+    nm.put(nk(2), nv(2));
+
+    assertTrue(iter.hasTop());
+    assertEquals(iter.getTopKey(), nk(0));
+    iter.next();
+
+    assertTrue(iter.hasTop());
+    assertEquals(iter.getTopKey(), nk(1));
+    iter.next();
+
+    assertTrue(iter.hasTop());
+    assertEquals(iter.getTopKey(), nk(2));
+    iter.next();
+
+    assertTrue(iter.hasTop());
+    assertEquals(iter.getTopKey(), nk(3));
+    iter.next();
+
+    assertFalse(iter.hasTop());
 
-  @Test(timeout = 15 * 1000)
-  public void test() throws Exception {
-    assertEquals(0, exec(NativeMapTest.class).waitFor());
+    nm.delete();
   }
 
 }


Mime
View raw message