accumulo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ctubb...@apache.org
Subject [40/53] [abbrv] ACCUMULO-658 consistent package names to avoid overlapped sealed jars
Date Fri, 06 Sep 2013 01:49:08 GMT
http://git-wip-us.apache.org/repos/asf/accumulo/blob/fc9363a0/server/base/src/main/java/org/apache/accumulo/server/master/state/MergeInfo.java
----------------------------------------------------------------------
diff --git a/server/base/src/main/java/org/apache/accumulo/server/master/state/MergeInfo.java b/server/base/src/main/java/org/apache/accumulo/server/master/state/MergeInfo.java
new file mode 100644
index 0000000..708b1b7
--- /dev/null
+++ b/server/base/src/main/java/org/apache/accumulo/server/master/state/MergeInfo.java
@@ -0,0 +1,107 @@
+/*
+ * 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.server.master.state;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.accumulo.core.data.KeyExtent;
+import org.apache.hadoop.io.Writable;
+
+/**
+ * Information about the current merge/rangeDelete.
+ * 
+ * Writable to serialize for zookeeper and the Tablet
+ */
+public class MergeInfo implements Writable {
+  
+  public enum Operation {
+    MERGE, DELETE,
+  }
+  
+  MergeState state = MergeState.NONE;
+  KeyExtent extent;
+  Operation operation = Operation.MERGE;
+  
+  public MergeInfo() {}
+  
+  @Override
+  public void readFields(DataInput in) throws IOException {
+    extent = new KeyExtent();
+    extent.readFields(in);
+    state = MergeState.values()[in.readInt()];
+    operation = Operation.values()[in.readInt()];
+  }
+  
+  @Override
+  public void write(DataOutput out) throws IOException {
+    extent.write(out);
+    out.writeInt(state.ordinal());
+    out.writeInt(operation.ordinal());
+  }
+  
+  public MergeInfo(KeyExtent range, Operation op) {
+    this.extent = range;
+    this.operation = op;
+  }
+  
+  public MergeState getState() {
+    return state;
+  }
+  
+  public KeyExtent getExtent() {
+    return extent;
+  }
+  
+  public Operation getOperation() {
+    return operation;
+  }
+  
+  public void setState(MergeState state) {
+    this.state = state;
+  }
+  
+  public boolean isDelete() {
+    return this.operation.equals(Operation.DELETE);
+  }
+  
+  public boolean needsToBeChopped(KeyExtent otherExtent) {
+    // During a delete, the block after the merge will be stretched to cover the deleted area.
+    // Therefore, it needs to be chopped
+    if (!otherExtent.getTableId().equals(extent.getTableId()))
+      return false;
+    if (isDelete())
+      return otherExtent.getPrevEndRow() != null && otherExtent.getPrevEndRow().equals(extent.getEndRow());
+    else
+      return this.extent.overlaps(otherExtent);
+  }
+  
+  public boolean overlaps(KeyExtent otherExtent) {
+    boolean result = this.extent.overlaps(otherExtent);
+    if (!result && needsToBeChopped(otherExtent))
+      return true;
+    return result;
+  }
+  
+  @Override
+  public String toString() {
+    if (!state.equals(MergeState.NONE))
+      return "Merge " + operation.toString() + " of " + extent + " State: " + state;
+    return "No Merge in progress";
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/fc9363a0/server/base/src/main/java/org/apache/accumulo/server/master/state/MergeState.java
----------------------------------------------------------------------
diff --git a/server/base/src/main/java/org/apache/accumulo/server/master/state/MergeState.java b/server/base/src/main/java/org/apache/accumulo/server/master/state/MergeState.java
new file mode 100644
index 0000000..29b6ae3
--- /dev/null
+++ b/server/base/src/main/java/org/apache/accumulo/server/master/state/MergeState.java
@@ -0,0 +1,49 @@
+/*
+ * 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.server.master.state;
+
+public enum MergeState {
+  /**
+   * Not merging
+   */
+  NONE,
+  /**
+   * created, stored in zookeeper, other merges are prevented on the table
+   */
+  STARTED,
+  /**
+   * put all matching tablets online, split tablets if we are deleting
+   */
+  SPLITTING,
+  /**
+   * after the tablet server chops the file, it marks the metadata table with a chopped marker
+   */
+  WAITING_FOR_CHOPPED,
+  /**
+   * when the number of chopped tablets in the range matches the number of online tablets in the range, take the tablets offline
+   */
+  WAITING_FOR_OFFLINE,
+  /**
+   * when the number of chopped, offline tablets equals the number of merge tablets, begin the metadata updates
+   */
+  MERGING,
+  /**
+   * merge is complete, the resulting tablet can be brought online, remove the marker in zookeeper
+   */
+  COMPLETE;
+  
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/fc9363a0/server/base/src/main/java/org/apache/accumulo/server/master/state/MetaDataStateStore.java
----------------------------------------------------------------------
diff --git a/server/base/src/main/java/org/apache/accumulo/server/master/state/MetaDataStateStore.java b/server/base/src/main/java/org/apache/accumulo/server/master/state/MetaDataStateStore.java
new file mode 100644
index 0000000..082f2ca
--- /dev/null
+++ b/server/base/src/main/java/org/apache/accumulo/server/master/state/MetaDataStateStore.java
@@ -0,0 +1,160 @@
+/*
+ * 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.server.master.state;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.accumulo.core.client.BatchWriter;
+import org.apache.accumulo.core.client.BatchWriterConfig;
+import org.apache.accumulo.core.client.Instance;
+import org.apache.accumulo.core.client.MutationsRejectedException;
+import org.apache.accumulo.core.client.TableNotFoundException;
+import org.apache.accumulo.core.data.Mutation;
+import org.apache.accumulo.core.metadata.MetadataTable;
+import org.apache.accumulo.core.metadata.schema.MetadataSchema;
+import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection;
+import org.apache.accumulo.core.security.Credentials;
+import org.apache.accumulo.server.client.HdfsZooInstance;
+import org.apache.accumulo.server.master.state.CurrentState;
+import org.apache.accumulo.server.master.state.MetaDataTableScanner;
+import org.apache.accumulo.server.master.state.TabletLocationState;
+import org.apache.accumulo.server.security.SystemCredentials;
+import org.apache.hadoop.io.Text;
+
+public class MetaDataStateStore extends TabletStateStore {
+  // private static final Logger log = Logger.getLogger(MetaDataStateStore.class);
+  
+  private static final int THREADS = 4;
+  private static final int LATENCY = 1000;
+  private static final int MAX_MEMORY = 200 * 1024 * 1024;
+  
+  final protected Instance instance;
+  final protected CurrentState state;
+  final protected Credentials credentials;
+  final private String targetTableName;
+  
+  protected MetaDataStateStore(Instance instance, Credentials credentials, CurrentState state, String targetTableName) {
+    this.instance = instance;
+    this.state = state;
+    this.credentials = credentials;
+    this.targetTableName = targetTableName;
+  }
+  
+  public MetaDataStateStore(Instance instance, Credentials credentials, CurrentState state) {
+    this(instance, credentials, state, MetadataTable.NAME);
+  }
+  
+  protected MetaDataStateStore(String tableName) {
+    this(HdfsZooInstance.getInstance(), SystemCredentials.get(), null, tableName);
+  }
+  
+  public MetaDataStateStore() {
+    this(MetadataTable.NAME);
+  }
+  
+  @Override
+  public Iterator<TabletLocationState> iterator() {
+    return new MetaDataTableScanner(instance, credentials, MetadataSchema.TabletsSection.getRange(), state);
+  }
+  
+  @Override
+  public void setLocations(Collection<Assignment> assignments) throws DistributedStoreException {
+    BatchWriter writer = createBatchWriter();
+    try {
+      for (Assignment assignment : assignments) {
+        Mutation m = new Mutation(assignment.tablet.getMetadataEntry());
+        Text cq = assignment.server.asColumnQualifier();
+        m.put(TabletsSection.CurrentLocationColumnFamily.NAME, cq, assignment.server.asMutationValue());
+        m.putDelete(TabletsSection.FutureLocationColumnFamily.NAME, cq);
+        writer.addMutation(m);
+      }
+    } catch (Exception ex) {
+      throw new DistributedStoreException(ex);
+    } finally {
+      try {
+        writer.close();
+      } catch (MutationsRejectedException e) {
+        throw new DistributedStoreException(e);
+      }
+    }
+  }
+  
+  BatchWriter createBatchWriter() {
+    try {
+      return instance.getConnector(credentials.getPrincipal(), credentials.getToken()).createBatchWriter(targetTableName,
+          new BatchWriterConfig().setMaxMemory(MAX_MEMORY).setMaxLatency(LATENCY, TimeUnit.MILLISECONDS).setMaxWriteThreads(THREADS));
+    } catch (TableNotFoundException e) {
+      // ya, I don't think so
+      throw new RuntimeException(e);
+    } catch (Exception e) {
+      throw new RuntimeException(e);
+    }
+  }
+  
+  @Override
+  public void setFutureLocations(Collection<Assignment> assignments) throws DistributedStoreException {
+    BatchWriter writer = createBatchWriter();
+    try {
+      for (Assignment assignment : assignments) {
+        Mutation m = new Mutation(assignment.tablet.getMetadataEntry());
+        m.put(TabletsSection.FutureLocationColumnFamily.NAME, assignment.server.asColumnQualifier(), assignment.server.asMutationValue());
+        writer.addMutation(m);
+      }
+    } catch (Exception ex) {
+      throw new DistributedStoreException(ex);
+    } finally {
+      try {
+        writer.close();
+      } catch (MutationsRejectedException e) {
+        throw new DistributedStoreException(e);
+      }
+    }
+  }
+  
+  @Override
+  public void unassign(Collection<TabletLocationState> tablets) throws DistributedStoreException {
+    
+    BatchWriter writer = createBatchWriter();
+    try {
+      for (TabletLocationState tls : tablets) {
+        Mutation m = new Mutation(tls.extent.getMetadataEntry());
+        if (tls.current != null) {
+          m.putDelete(TabletsSection.CurrentLocationColumnFamily.NAME, tls.current.asColumnQualifier());
+        }
+        if (tls.future != null) {
+          m.putDelete(TabletsSection.FutureLocationColumnFamily.NAME, tls.future.asColumnQualifier());
+        }
+        writer.addMutation(m);
+      }
+    } catch (Exception ex) {
+      throw new DistributedStoreException(ex);
+    } finally {
+      try {
+        writer.close();
+      } catch (MutationsRejectedException e) {
+        throw new DistributedStoreException(e);
+      }
+    }
+  }
+  
+  @Override
+  public String name() {
+    return "Normal Tablets";
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/fc9363a0/server/base/src/main/java/org/apache/accumulo/server/master/state/MetaDataTableScanner.java
----------------------------------------------------------------------
diff --git a/server/base/src/main/java/org/apache/accumulo/server/master/state/MetaDataTableScanner.java b/server/base/src/main/java/org/apache/accumulo/server/master/state/MetaDataTableScanner.java
new file mode 100644
index 0000000..cec0bcf
--- /dev/null
+++ b/server/base/src/main/java/org/apache/accumulo/server/master/state/MetaDataTableScanner.java
@@ -0,0 +1,196 @@
+/*
+ * 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.server.master.state;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.SortedMap;
+
+import org.apache.accumulo.core.client.BatchScanner;
+import org.apache.accumulo.core.client.Connector;
+import org.apache.accumulo.core.client.Instance;
+import org.apache.accumulo.core.client.IteratorSetting;
+import org.apache.accumulo.core.client.ScannerBase;
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.KeyExtent;
+import org.apache.accumulo.core.data.Range;
+import org.apache.accumulo.core.data.Value;
+import org.apache.accumulo.core.iterators.user.WholeRowIterator;
+import org.apache.accumulo.core.metadata.MetadataTable;
+import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection;
+import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.ChoppedColumnFamily;
+import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.LogColumnFamily;
+import org.apache.accumulo.core.security.Authorizations;
+import org.apache.accumulo.core.security.Credentials;
+import org.apache.accumulo.server.master.state.TabletLocationState.BadLocationStateException;
+import org.apache.hadoop.io.Text;
+import org.apache.log4j.Logger;
+
+public class MetaDataTableScanner implements Iterator<TabletLocationState> {
+  private static final Logger log = Logger.getLogger(MetaDataTableScanner.class);
+  
+  BatchScanner mdScanner;
+  Iterator<Entry<Key,Value>> iter;
+  
+  public MetaDataTableScanner(Instance instance, Credentials credentials, Range range, CurrentState state) {
+    this(instance, credentials, range, state, MetadataTable.NAME);
+  }
+  
+  MetaDataTableScanner(Instance instance, Credentials credentials, Range range, CurrentState state, String tableName) {
+    // scan over metadata table, looking for tablets in the wrong state based on the live servers and online tables
+    try {
+      Connector connector = instance.getConnector(credentials.getPrincipal(), credentials.getToken());
+      mdScanner = connector.createBatchScanner(tableName, Authorizations.EMPTY, 8);
+      configureScanner(mdScanner, state);
+      mdScanner.setRanges(Collections.singletonList(range));
+      iter = mdScanner.iterator();
+    } catch (Exception ex) {
+      mdScanner.close();
+      throw new RuntimeException(ex);
+    }
+  }
+  
+  static public void configureScanner(ScannerBase scanner, CurrentState state) {
+    TabletsSection.TabletColumnFamily.PREV_ROW_COLUMN.fetch(scanner);
+    scanner.fetchColumnFamily(TabletsSection.CurrentLocationColumnFamily.NAME);
+    scanner.fetchColumnFamily(TabletsSection.FutureLocationColumnFamily.NAME);
+    scanner.fetchColumnFamily(LogColumnFamily.NAME);
+    scanner.fetchColumnFamily(ChoppedColumnFamily.NAME);
+    scanner.addScanIterator(new IteratorSetting(1000, "wholeRows", WholeRowIterator.class));
+    IteratorSetting tabletChange = new IteratorSetting(1001, "tabletChange", TabletStateChangeIterator.class);
+    if (state != null) {
+      TabletStateChangeIterator.setCurrentServers(tabletChange, state.onlineTabletServers());
+      TabletStateChangeIterator.setOnlineTables(tabletChange, state.onlineTables());
+      TabletStateChangeIterator.setMerges(tabletChange, state.merges());
+    }
+    scanner.addScanIterator(tabletChange);
+  }
+  
+  public MetaDataTableScanner(Instance instance, Credentials credentials, Range range) {
+    this(instance, credentials, range, MetadataTable.NAME);
+  }
+  
+  public MetaDataTableScanner(Instance instance, Credentials credentials, Range range, String tableName) {
+    this(instance, credentials, range, null, tableName);
+  }
+  
+  public void close() {
+    if (iter != null) {
+      mdScanner.close();
+      iter = null;
+    }
+  }
+  
+  @Override
+  public void finalize() {
+    close();
+  }
+  
+  @Override
+  public boolean hasNext() {
+    if (iter == null)
+      return false;
+    boolean result = iter.hasNext();
+    if (!result) {
+      close();
+    }
+    return result;
+  }
+  
+  @Override
+  public TabletLocationState next() {
+    try {
+      return fetch();
+    } catch (RuntimeException ex) {
+      // something is wrong with the records in the !METADATA table, just skip over it
+      log.error(ex, ex);
+      mdScanner.close();
+      return null;
+    }
+  }
+  
+  public static TabletLocationState createTabletLocationState(Key k, Value v) throws IOException, BadLocationStateException {
+    final SortedMap<Key,Value> decodedRow = WholeRowIterator.decodeRow(k, v);
+    KeyExtent extent = null;
+    TServerInstance future = null;
+    TServerInstance current = null;
+    TServerInstance last = null;
+    List<Collection<String>> walogs = new ArrayList<Collection<String>>();
+    boolean chopped = false;
+    
+    for (Entry<Key,Value> entry : decodedRow.entrySet()) {
+      Key key = entry.getKey();
+      Text row = key.getRow();
+      Text cf = key.getColumnFamily();
+      Text cq = key.getColumnQualifier();
+      
+      if (cf.compareTo(TabletsSection.FutureLocationColumnFamily.NAME) == 0) {
+        TServerInstance location = new TServerInstance(entry.getValue(), cq);
+        if (future != null) {
+          throw new BadLocationStateException("found two assignments for the same extent " + key.getRow() + ": " + future + " and " + location);
+        }
+        future = location;
+      } else if (cf.compareTo(TabletsSection.CurrentLocationColumnFamily.NAME) == 0) {
+        TServerInstance location = new TServerInstance(entry.getValue(), cq);
+        if (current != null) {
+          throw new BadLocationStateException("found two locations for the same extent " + key.getRow() + ": " + current + " and " + location);
+        }
+        current = location;
+      } else if (cf.compareTo(LogColumnFamily.NAME) == 0) {
+        String[] split = entry.getValue().toString().split("\\|")[0].split(";");
+        walogs.add(Arrays.asList(split));
+      } else if (cf.compareTo(TabletsSection.LastLocationColumnFamily.NAME) == 0) {
+        TServerInstance location = new TServerInstance(entry.getValue(), cq);
+        if (last != null) {
+          throw new BadLocationStateException("found two last locations for the same extent " + key.getRow() + ": " + last + " and " + location);
+        }
+        last = new TServerInstance(entry.getValue(), cq);
+      } else if (cf.compareTo(ChoppedColumnFamily.NAME) == 0) {
+        chopped = true;
+      } else if (TabletsSection.TabletColumnFamily.PREV_ROW_COLUMN.equals(cf, cq)) {
+        extent = new KeyExtent(row, entry.getValue());
+      }
+    }
+    if (extent == null) {
+      log.warn("No prev-row for key extent: " + decodedRow);
+      return null;
+    }
+    return new TabletLocationState(extent, future, current, last, walogs, chopped);
+  }
+  
+  private TabletLocationState fetch() {
+    try {
+      Entry<Key,Value> e = iter.next();
+      return createTabletLocationState(e.getKey(), e.getValue());
+    } catch (IOException ex) {
+      throw new RuntimeException(ex);
+    } catch (BadLocationStateException ex) {
+      throw new RuntimeException(ex);
+    }
+  }
+  
+  @Override
+  public void remove() {
+    throw new RuntimeException("Unimplemented");
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/fc9363a0/server/base/src/main/java/org/apache/accumulo/server/master/state/RootTabletStateStore.java
----------------------------------------------------------------------
diff --git a/server/base/src/main/java/org/apache/accumulo/server/master/state/RootTabletStateStore.java b/server/base/src/main/java/org/apache/accumulo/server/master/state/RootTabletStateStore.java
new file mode 100644
index 0000000..7cb171a
--- /dev/null
+++ b/server/base/src/main/java/org/apache/accumulo/server/master/state/RootTabletStateStore.java
@@ -0,0 +1,48 @@
+/*
+ * 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.server.master.state;
+
+import java.util.Iterator;
+
+import org.apache.accumulo.core.client.Instance;
+import org.apache.accumulo.core.metadata.RootTable;
+import org.apache.accumulo.core.metadata.schema.MetadataSchema;
+import org.apache.accumulo.core.security.Credentials;
+import org.apache.accumulo.server.master.state.CurrentState;
+import org.apache.accumulo.server.master.state.MetaDataTableScanner;
+import org.apache.accumulo.server.master.state.TabletLocationState;
+
+public class RootTabletStateStore extends MetaDataStateStore {
+  
+  public RootTabletStateStore(Instance instance, Credentials credentials, CurrentState state) {
+    super(instance, credentials, state, RootTable.NAME);
+  }
+  
+  public RootTabletStateStore() {
+    super(RootTable.NAME);
+  }
+  
+  @Override
+  public Iterator<TabletLocationState> iterator() {
+    return new MetaDataTableScanner(instance, credentials, MetadataSchema.TabletsSection.getRange(), state, RootTable.NAME);
+  }
+  
+  @Override
+  public String name() {
+    return "Non-Root Metadata Tablets";
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/fc9363a0/server/base/src/main/java/org/apache/accumulo/server/master/state/TServerInstance.java
----------------------------------------------------------------------
diff --git a/server/base/src/main/java/org/apache/accumulo/server/master/state/TServerInstance.java b/server/base/src/main/java/org/apache/accumulo/server/master/state/TServerInstance.java
new file mode 100644
index 0000000..753a3cf
--- /dev/null
+++ b/server/base/src/main/java/org/apache/accumulo/server/master/state/TServerInstance.java
@@ -0,0 +1,127 @@
+/*
+ * 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.server.master.state;
+
+import java.io.Serializable;
+import java.net.InetSocketAddress;
+
+import org.apache.accumulo.core.data.Mutation;
+import org.apache.accumulo.core.data.Value;
+import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection;
+import org.apache.accumulo.core.util.AddressUtil;
+import org.apache.hadoop.io.Text;
+
+/**
+ * A tablet is assigned to a tablet server at the given address as long as it is alive and well. When the tablet server is restarted, the instance information
+ * it advertises will change. Therefore tablet assignments can be considered out-of-date if the tablet server instance information has been changed.
+ * 
+ */
+public class TServerInstance implements Comparable<TServerInstance>, Serializable {
+  
+  private static final long serialVersionUID = 1L;
+  
+  private InetSocketAddress location;
+  private String session;
+  private String cachedStringRepresentation;
+  
+  public TServerInstance(InetSocketAddress address, String session) {
+    this.location = address;
+    this.session = session;
+    this.cachedStringRepresentation = hostPort() + "[" + session + "]";
+  }
+  
+  public TServerInstance(InetSocketAddress address, long session) {
+    this(address, Long.toHexString(session));
+  }
+  
+  public TServerInstance(String address, long session) {
+    this(AddressUtil.parseAddress(address), Long.toHexString(session));
+  }
+  
+  public TServerInstance(Value address, Text session) {
+    this(AddressUtil.parseAddress(new String(address.get())), session.toString());
+  }
+  
+  public void putLocation(Mutation m) {
+    m.put(TabletsSection.CurrentLocationColumnFamily.NAME, asColumnQualifier(), asMutationValue());
+  }
+  
+  public void putFutureLocation(Mutation m) {
+    m.put(TabletsSection.FutureLocationColumnFamily.NAME, asColumnQualifier(), asMutationValue());
+  }
+  
+  public void putLastLocation(Mutation m) {
+    m.put(TabletsSection.LastLocationColumnFamily.NAME, asColumnQualifier(), asMutationValue());
+  }
+  
+  public void clearLastLocation(Mutation m) {
+    m.putDelete(TabletsSection.LastLocationColumnFamily.NAME, asColumnQualifier());
+  }
+  
+  @Override
+  public int compareTo(TServerInstance other) {
+    if (this == other)
+      return 0;
+    return this.toString().compareTo(other.toString());
+  }
+  
+  @Override
+  public int hashCode() {
+    return toString().hashCode();
+  }
+  
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof TServerInstance) {
+      return compareTo((TServerInstance) obj) == 0;
+    }
+    return false;
+  }
+  
+  @Override
+  public String toString() {
+    return cachedStringRepresentation;
+  }
+  
+  public int port() {
+    return getLocation().getPort();
+  }
+  
+  public String host() {
+    return getLocation().getAddress().getHostAddress();
+  }
+  
+  public String hostPort() {
+    return org.apache.accumulo.core.util.AddressUtil.toString(getLocation());
+  }
+  
+  public Text asColumnQualifier() {
+    return new Text(this.getSession());
+  }
+  
+  public Value asMutationValue() {
+    return new Value(org.apache.accumulo.core.util.AddressUtil.toString(getLocation()).getBytes());
+  }
+  
+  public InetSocketAddress getLocation() {
+    return location;
+  }
+  
+  public String getSession() {
+    return session;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/fc9363a0/server/base/src/main/java/org/apache/accumulo/server/master/state/TabletLocationState.java
----------------------------------------------------------------------
diff --git a/server/base/src/main/java/org/apache/accumulo/server/master/state/TabletLocationState.java b/server/base/src/main/java/org/apache/accumulo/server/master/state/TabletLocationState.java
new file mode 100644
index 0000000..bcfaead
--- /dev/null
+++ b/server/base/src/main/java/org/apache/accumulo/server/master/state/TabletLocationState.java
@@ -0,0 +1,97 @@
+/*
+ * 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.server.master.state;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+
+import org.apache.accumulo.core.data.KeyExtent;
+
+/**
+ * When a tablet is assigned, we mark its future location. When the tablet is opened, we set its current location. A tablet should never have both a future and
+ * current location.
+ * 
+ * A tablet server is always associated with a unique session id. If the current tablet server has a different session, we know the location information is
+ * out-of-date.
+ */
+public class TabletLocationState {
+  
+  static public class BadLocationStateException extends Exception {
+    private static final long serialVersionUID = 1L;
+
+    BadLocationStateException(String msg) { super(msg); }
+  }
+  
+  public TabletLocationState(KeyExtent extent, TServerInstance future, TServerInstance current, TServerInstance last, Collection<Collection<String>> walogs,
+      boolean chopped) throws BadLocationStateException {
+    this.extent = extent;
+    this.future = future;
+    this.current = current;
+    this.last = last;
+    if (walogs == null)
+      walogs = Collections.emptyList();
+    this.walogs = walogs;
+    this.chopped = chopped;
+    if (current != null && future != null) {
+      throw new BadLocationStateException(extent + " is both assigned and hosted, which should never happen: " + this);
+    }
+  }
+  
+  final public KeyExtent extent;
+  final public TServerInstance future;
+  final public TServerInstance current;
+  final public TServerInstance last;
+  final public Collection<Collection<String>> walogs;
+  final public boolean chopped;
+  
+  public String toString() {
+    return extent + "@(" + future + "," + current + "," + last + ")" + (chopped ? " chopped" : "");
+  }
+  
+  public TServerInstance getServer() {
+    TServerInstance result = null;
+    if (current != null) {
+      result = current;
+    } else if (future != null) {
+      result = future;
+    } else {
+      result = last;
+    }
+    return result;
+  }
+  
+  public TabletState getState(Set<TServerInstance> liveServers) {
+    TServerInstance server = getServer();
+    if (server == null)
+      return TabletState.UNASSIGNED;
+    if (server.equals(current) || server.equals(future)) {
+      if (liveServers.contains(server))
+        if (server.equals(future)) {
+          return TabletState.ASSIGNED;
+        } else {
+          return TabletState.HOSTED;
+        }
+      else {
+        return TabletState.ASSIGNED_TO_DEAD_SERVER;
+      }
+    }
+    // server == last
+    return TabletState.UNASSIGNED;
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/fc9363a0/server/base/src/main/java/org/apache/accumulo/server/master/state/TabletServerState.java
----------------------------------------------------------------------
diff --git a/server/base/src/main/java/org/apache/accumulo/server/master/state/TabletServerState.java b/server/base/src/main/java/org/apache/accumulo/server/master/state/TabletServerState.java
new file mode 100644
index 0000000..23f16e3
--- /dev/null
+++ b/server/base/src/main/java/org/apache/accumulo/server/master/state/TabletServerState.java
@@ -0,0 +1,76 @@
+/*
+ * 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.server.master.state;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+
+public enum TabletServerState {
+  // not a valid state, reserved for internal use only
+  RESERVED((byte) (-1)),
+  
+  // the following are normally functioning states
+  NEW((byte) 0),
+  ONLINE((byte) 1),
+  UNRESPONSIVE((byte) 2),
+  DOWN((byte) 3),
+  
+  // the following are bad states and cause tservers to be ignored by the master
+  BAD_SYSTEM_PASSWORD((byte) 101),
+  BAD_VERSION((byte) 102),
+  BAD_INSTANCE((byte) 103),
+  BAD_CONFIG((byte) 104),
+  BAD_VERSION_AND_INSTANCE((byte) 105),
+  BAD_VERSION_AND_CONFIG((byte) 106),
+  BAD_VERSION_AND_INSTANCE_AND_CONFIG((byte) 107),
+  BAD_INSTANCE_AND_CONFIG((byte) 108);
+  
+  private byte id;
+  
+  private static HashMap<Byte,TabletServerState> mapping;
+  private static HashSet<TabletServerState> badStates;
+  
+  static {
+    mapping = new HashMap<Byte,TabletServerState>(TabletServerState.values().length);
+    badStates = new HashSet<TabletServerState>();
+    for (TabletServerState state : TabletServerState.values()) {
+      mapping.put(state.id, state);
+      if (state.id > 99)
+        badStates.add(state);
+    }
+  }
+  
+  private TabletServerState(byte id) {
+    this.id = id;
+  }
+  
+  public byte getId() {
+    return this.id;
+  }
+  
+  public static TabletServerState getStateById(byte id) {
+    if (mapping.containsKey(id))
+      return mapping.get(id);
+    throw new IndexOutOfBoundsException("No such state");
+  }
+  
+  public static Set<TabletServerState> getBadStates() {
+    return Collections.unmodifiableSet(badStates);
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/fc9363a0/server/base/src/main/java/org/apache/accumulo/server/master/state/TabletState.java
----------------------------------------------------------------------
diff --git a/server/base/src/main/java/org/apache/accumulo/server/master/state/TabletState.java b/server/base/src/main/java/org/apache/accumulo/server/master/state/TabletState.java
new file mode 100644
index 0000000..d69ca19
--- /dev/null
+++ b/server/base/src/main/java/org/apache/accumulo/server/master/state/TabletState.java
@@ -0,0 +1,21 @@
+/*
+ * 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.server.master.state;
+
+public enum TabletState {
+  UNASSIGNED, ASSIGNED, HOSTED, ASSIGNED_TO_DEAD_SERVER
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/fc9363a0/server/base/src/main/java/org/apache/accumulo/server/master/state/TabletStateChangeIterator.java
----------------------------------------------------------------------
diff --git a/server/base/src/main/java/org/apache/accumulo/server/master/state/TabletStateChangeIterator.java b/server/base/src/main/java/org/apache/accumulo/server/master/state/TabletStateChangeIterator.java
new file mode 100644
index 0000000..ddcdeea
--- /dev/null
+++ b/server/base/src/main/java/org/apache/accumulo/server/master/state/TabletStateChangeIterator.java
@@ -0,0 +1,188 @@
+/*
+ * 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.server.master.state;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.accumulo.core.client.IteratorSetting;
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.KeyExtent;
+import org.apache.accumulo.core.data.Value;
+import org.apache.accumulo.core.iterators.IteratorEnvironment;
+import org.apache.accumulo.core.iterators.SkippingIterator;
+import org.apache.accumulo.core.iterators.SortedKeyValueIterator;
+import org.apache.accumulo.core.util.AddressUtil;
+import org.apache.accumulo.core.util.StringUtil;
+import org.apache.accumulo.server.master.state.TabletLocationState.BadLocationStateException;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.hadoop.io.DataInputBuffer;
+import org.apache.hadoop.io.DataOutputBuffer;
+import org.apache.hadoop.io.Text;
+
+public class TabletStateChangeIterator extends SkippingIterator {
+  
+  private static final String SERVERS_OPTION = "servers";
+  private static final String TABLES_OPTION = "tables";
+  private static final String MERGES_OPTION = "merges";
+  // private static final Logger log = Logger.getLogger(TabletStateChangeIterator.class);
+  
+  Set<TServerInstance> current;
+  Set<String> onlineTables;
+  Map<Text,MergeInfo> merges;
+  
+  @Override
+  public void init(SortedKeyValueIterator<Key,Value> source, Map<String,String> options, IteratorEnvironment env) throws IOException {
+    super.init(source, options, env);
+    current = parseServers(options.get(SERVERS_OPTION));
+    onlineTables = parseTables(options.get(TABLES_OPTION));
+    merges = parseMerges(options.get(MERGES_OPTION));
+  }
+  
+  private Set<String> parseTables(String tables) {
+    if (tables == null)
+      return null;
+    Set<String> result = new HashSet<String>();
+    for (String table : tables.split(","))
+      result.add(table);
+    return result;
+  }
+  
+  private Set<TServerInstance> parseServers(String servers) {
+    if (servers == null)
+      return null;
+    // parse "host:port[INSTANCE]"
+    Set<TServerInstance> result = new HashSet<TServerInstance>();
+    if (servers.length() > 0) {
+      for (String part : servers.split(",")) {
+        String parts[] = part.split("\\[", 2);
+        String hostport = parts[0];
+        String instance = parts[1];
+        if (instance != null && instance.endsWith("]"))
+          instance = instance.substring(0, instance.length() - 1);
+        result.add(new TServerInstance(AddressUtil.parseAddress(hostport), instance));
+      }
+    }
+    return result;
+  }
+  
+  private Map<Text,MergeInfo> parseMerges(String merges) {
+    if (merges == null)
+      return null;
+    try {
+      Map<Text,MergeInfo> result = new HashMap<Text,MergeInfo>();
+      DataInputBuffer buffer = new DataInputBuffer();
+      byte[] data = Base64.decodeBase64(merges.getBytes());
+      buffer.reset(data, data.length);
+      while (buffer.available() > 0) {
+        MergeInfo mergeInfo = new MergeInfo();
+        mergeInfo.readFields(buffer);
+        result.put(mergeInfo.extent.getTableId(), mergeInfo);
+      }
+      return result;
+    } catch (Exception ex) {
+      throw new RuntimeException(ex);
+    }
+  }
+  
+  @Override
+  protected void consume() throws IOException {
+    while (getSource().hasTop()) {
+      Key k = getSource().getTopKey();
+      Value v = getSource().getTopValue();
+      
+      if (onlineTables == null || current == null)
+        return;
+      
+      TabletLocationState tls;
+      try {
+        tls = MetaDataTableScanner.createTabletLocationState(k, v);
+        if (tls == null)
+          return;
+      } catch (BadLocationStateException e) {
+        // maybe the master can do something with a tablet with bad/inconsistent state
+        return;
+      }
+      // we always want data about merges
+      MergeInfo merge = merges.get(tls.extent.getTableId());
+      if (merge != null && merge.getExtent() != null && merge.getExtent().overlaps(tls.extent)) {
+        return;
+      }
+      // is the table supposed to be online or offline?
+      boolean shouldBeOnline = onlineTables.contains(tls.extent.getTableId().toString());
+      
+      switch (tls.getState(current)) {
+        case ASSIGNED:
+          // we always want data about assigned tablets
+          return;
+        case HOSTED:
+          if (!shouldBeOnline)
+            return;
+        case ASSIGNED_TO_DEAD_SERVER:
+          return;
+        case UNASSIGNED:
+          if (shouldBeOnline)
+            return;
+      }
+      // table is in the expected state so don't bother returning any information about it
+      getSource().next();
+    }
+  }
+  
+  @Override
+  public SortedKeyValueIterator<Key,Value> deepCopy(IteratorEnvironment env) {
+    throw new UnsupportedOperationException();
+  }
+  
+  public static void setCurrentServers(IteratorSetting cfg, Set<TServerInstance> goodServers) {
+    if (goodServers != null) {
+      List<String> servers = new ArrayList<String>();
+      for (TServerInstance server : goodServers)
+        servers.add(server.toString());
+      cfg.addOption(SERVERS_OPTION, StringUtil.join(servers, ","));
+    }
+  }
+  
+  public static void setOnlineTables(IteratorSetting cfg, Set<String> onlineTables) {
+    if (onlineTables != null)
+      cfg.addOption(TABLES_OPTION, StringUtil.join(onlineTables, ","));
+  }
+  
+  public static void setMerges(IteratorSetting cfg, Collection<MergeInfo> merges) {
+    DataOutputBuffer buffer = new DataOutputBuffer();
+    try {
+      for (MergeInfo info : merges) {
+        KeyExtent extent = info.getExtent();
+        if (extent != null && !info.getState().equals(MergeState.NONE)) {
+          info.write(buffer);
+        }
+      }
+    } catch (Exception ex) {
+      throw new RuntimeException(ex);
+    }
+    String encoded = new String(Base64.encodeBase64(Arrays.copyOf(buffer.getData(), buffer.getLength())));
+    cfg.addOption(MERGES_OPTION, encoded);
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/fc9363a0/server/base/src/main/java/org/apache/accumulo/server/master/state/TabletStateStore.java
----------------------------------------------------------------------
diff --git a/server/base/src/main/java/org/apache/accumulo/server/master/state/TabletStateStore.java b/server/base/src/main/java/org/apache/accumulo/server/master/state/TabletStateStore.java
new file mode 100644
index 0000000..5e19976
--- /dev/null
+++ b/server/base/src/main/java/org/apache/accumulo/server/master/state/TabletStateStore.java
@@ -0,0 +1,94 @@
+/*
+ * 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.server.master.state;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+
+import org.apache.accumulo.server.master.state.TabletLocationState;
+
+/**
+ * Interface for storing information about tablet assignments. There are three implementations:
+ * 
+ * ZooTabletStateStore: information about the root tablet is stored in ZooKeeper MetaDataStateStore: information about the other tablets are stored in the
+ * metadata table
+ * 
+ */
+public abstract class TabletStateStore implements Iterable<TabletLocationState> {
+  
+  /**
+   * Identifying name for this tablet state store.
+   */
+  abstract public String name();
+  
+  /**
+   * Scan the information about the tablets covered by this store
+   */
+  @Override
+  abstract public Iterator<TabletLocationState> iterator();
+  
+  /**
+   * Store the assigned locations in the data store.
+   * 
+   * @param assignments
+   * @throws DistributedStoreException
+   */
+  abstract public void setFutureLocations(Collection<Assignment> assignments) throws DistributedStoreException;
+  
+  /**
+   * Tablet servers will update the data store with the location when they bring the tablet online
+   * 
+   * @param assignments
+   * @throws DistributedStoreException
+   */
+  abstract public void setLocations(Collection<Assignment> assignments) throws DistributedStoreException;
+  
+  /**
+   * Mark the tablets as having no known or future location.
+   * 
+   * @param tablets
+   *          the tablets' current information
+   * @throws DistributedStoreException
+   */
+  abstract public void unassign(Collection<TabletLocationState> tablets) throws DistributedStoreException;
+  
+  public static void unassign(TabletLocationState tls) throws DistributedStoreException {
+    TabletStateStore store;
+    if (tls.extent.isRootTablet()) {
+      store = new ZooTabletStateStore();
+    } else if (tls.extent.isMeta()) {
+      store = new RootTabletStateStore();
+    } else {
+      store = new MetaDataStateStore();
+    }
+    store.unassign(Collections.singletonList(tls));
+  }
+  
+  public static void setLocation(Assignment assignment) throws DistributedStoreException {
+    TabletStateStore store;
+    if (assignment.tablet.isRootTablet()) {
+      store = new ZooTabletStateStore();
+    } else if (assignment.tablet.isMeta()) {
+      store = new RootTabletStateStore();
+    } else {
+      store = new MetaDataStateStore();
+    }
+    store.setLocations(Collections.singletonList(assignment));
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/fc9363a0/server/base/src/main/java/org/apache/accumulo/server/master/state/ZooStore.java
----------------------------------------------------------------------
diff --git a/server/base/src/main/java/org/apache/accumulo/server/master/state/ZooStore.java b/server/base/src/main/java/org/apache/accumulo/server/master/state/ZooStore.java
new file mode 100644
index 0000000..bce6681
--- /dev/null
+++ b/server/base/src/main/java/org/apache/accumulo/server/master/state/ZooStore.java
@@ -0,0 +1,96 @@
+/*
+ * 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.server.master.state;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.accumulo.core.zookeeper.ZooUtil;
+import org.apache.accumulo.fate.zookeeper.IZooReaderWriter;
+import org.apache.accumulo.fate.zookeeper.ZooUtil.NodeExistsPolicy;
+import org.apache.accumulo.fate.zookeeper.ZooUtil.NodeMissingPolicy;
+import org.apache.accumulo.server.client.HdfsZooInstance;
+import org.apache.accumulo.server.zookeeper.ZooCache;
+import org.apache.accumulo.server.zookeeper.ZooReaderWriter;
+import org.apache.log4j.Logger;
+
+public class ZooStore implements DistributedStore {
+  
+  private static final Logger log = Logger.getLogger(ZooStore.class);
+  
+  String basePath;
+  
+  ZooCache cache = new ZooCache();
+  
+  public ZooStore(String basePath) throws IOException {
+    if (basePath.endsWith("/"))
+      basePath = basePath.substring(0, basePath.length() - 1);
+    this.basePath = basePath;
+  }
+  
+  public ZooStore() throws IOException {
+    this(ZooUtil.getRoot(HdfsZooInstance.getInstance().getInstanceID()));
+  }
+  
+  @Override
+  public byte[] get(String path) throws DistributedStoreException {
+    try {
+      return cache.get(relative(path));
+    } catch (Exception ex) {
+      throw new DistributedStoreException(ex);
+    }
+  }
+  
+  private String relative(String path) {
+    return basePath + path;
+  }
+  
+  @Override
+  public List<String> getChildren(String path) throws DistributedStoreException {
+    try {
+      return cache.getChildren(relative(path));
+    } catch (Exception ex) {
+      throw new DistributedStoreException(ex);
+    }
+  }
+  
+  @Override
+  public void put(String path, byte[] bs) throws DistributedStoreException {
+    try {
+      path = relative(path);
+      ZooReaderWriter.getInstance().putPersistentData(path, bs, NodeExistsPolicy.OVERWRITE);
+      cache.clear();
+      log.debug("Wrote " + new String(bs) + " to " + path);
+    } catch (Exception ex) {
+      throw new DistributedStoreException(ex);
+    }
+  }
+  
+  @Override
+  public void remove(String path) throws DistributedStoreException {
+    try {
+      log.debug("Removing " + path);
+      path = relative(path);
+      IZooReaderWriter zoo = ZooReaderWriter.getInstance();
+      if (zoo.exists(path))
+        zoo.recursiveDelete(path, NodeMissingPolicy.SKIP);
+      cache.clear();
+    } catch (Exception ex) {
+      throw new DistributedStoreException(ex);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/fc9363a0/server/base/src/main/java/org/apache/accumulo/server/master/state/ZooTabletStateStore.java
----------------------------------------------------------------------
diff --git a/server/base/src/main/java/org/apache/accumulo/server/master/state/ZooTabletStateStore.java b/server/base/src/main/java/org/apache/accumulo/server/master/state/ZooTabletStateStore.java
new file mode 100644
index 0000000..e6882ae
--- /dev/null
+++ b/server/base/src/main/java/org/apache/accumulo/server/master/state/ZooTabletStateStore.java
@@ -0,0 +1,176 @@
+/*
+ * 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.server.master.state;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.accumulo.core.metadata.RootTable;
+import org.apache.accumulo.core.util.AddressUtil;
+import org.apache.accumulo.server.master.state.TServerInstance;
+import org.apache.accumulo.server.master.state.TabletLocationState;
+import org.apache.accumulo.server.util.MetadataTableUtil;
+import org.apache.commons.lang.NotImplementedException;
+import org.apache.log4j.Logger;
+
+public class ZooTabletStateStore extends TabletStateStore {
+  
+  private static final Logger log = Logger.getLogger(ZooTabletStateStore.class);
+  final private DistributedStore store;
+  
+  public ZooTabletStateStore(DistributedStore store) {
+    this.store = store;
+  }
+  
+  public ZooTabletStateStore() throws DistributedStoreException {
+    try {
+      store = new ZooStore();
+    } catch (IOException ex) {
+      throw new DistributedStoreException(ex);
+    }
+  }
+  
+  @Override
+  public Iterator<TabletLocationState> iterator() {
+    return new Iterator<TabletLocationState>() {
+      boolean finished = false;
+      
+      @Override
+      public boolean hasNext() {
+        return !finished;
+      }
+      
+      @Override
+      public TabletLocationState next() {
+        finished = true;
+        try {
+          byte[] future = store.get(RootTable.ZROOT_TABLET_FUTURE_LOCATION);
+          byte[] current = store.get(RootTable.ZROOT_TABLET_LOCATION);
+          byte[] last = store.get(RootTable.ZROOT_TABLET_LAST_LOCATION);
+          
+          TServerInstance currentSession = null;
+          TServerInstance futureSession = null;
+          TServerInstance lastSession = null;
+          
+          if (future != null)
+            futureSession = parse(future);
+          
+          if (last != null)
+            lastSession = parse(last);
+          
+          if (current != null) {
+            currentSession = parse(current);
+            futureSession = null;
+          }
+          List<Collection<String>> logs = new ArrayList<Collection<String>>();
+          for (String entry : store.getChildren(RootTable.ZROOT_TABLET_WALOGS)) {
+            byte[] logInfo = store.get(RootTable.ZROOT_TABLET_WALOGS + "/" + entry);
+            if (logInfo != null) {
+              MetadataTableUtil.LogEntry logEntry = new MetadataTableUtil.LogEntry();
+              logEntry.fromBytes(logInfo);
+              logs.add(logEntry.logSet);
+              log.debug("root tablet logSet " + logEntry.logSet);
+            }
+          }
+          TabletLocationState result = new TabletLocationState(RootTable.EXTENT, futureSession, currentSession, lastSession, logs, false);
+          log.debug("Returning root tablet state: " + result);
+          return result;
+        } catch (Exception ex) {
+          throw new RuntimeException(ex);
+        }
+      }
+      
+      @Override
+      public void remove() {
+        throw new NotImplementedException();
+      }
+    };
+  }
+  
+  protected TServerInstance parse(byte[] current) {
+    String str = new String(current);
+    String[] parts = str.split("[|]", 2);
+    InetSocketAddress address = AddressUtil.parseAddress(parts[0], 0);
+    if (parts.length > 1 && parts[1] != null && parts[1].length() > 0) {
+      return new TServerInstance(address, parts[1]);
+    } else {
+      // a 1.2 location specification: DO NOT WANT
+      return null;
+    }
+  }
+  
+  @Override
+  public void setFutureLocations(Collection<Assignment> assignments) throws DistributedStoreException {
+    if (assignments.size() != 1)
+      throw new IllegalArgumentException("There is only one root tablet");
+    Assignment assignment = assignments.iterator().next();
+    if (assignment.tablet.compareTo(RootTable.EXTENT) != 0)
+      throw new IllegalArgumentException("You can only store the root tablet location");
+    String value = AddressUtil.toString(assignment.server.getLocation()) + "|" + assignment.server.getSession();
+    Iterator<TabletLocationState> currentIter = iterator();
+    TabletLocationState current = currentIter.next();
+    if (current.current != null) {
+      throw new DistributedStoreException("Trying to set the root tablet location: it is already set to " + current.current);
+    }
+    store.put(RootTable.ZROOT_TABLET_FUTURE_LOCATION, value.getBytes());
+  }
+  
+  @Override
+  public void setLocations(Collection<Assignment> assignments) throws DistributedStoreException {
+    if (assignments.size() != 1)
+      throw new IllegalArgumentException("There is only one root tablet");
+    Assignment assignment = assignments.iterator().next();
+    if (assignment.tablet.compareTo(RootTable.EXTENT) != 0)
+      throw new IllegalArgumentException("You can only store the root tablet location");
+    String value = AddressUtil.toString(assignment.server.getLocation()) + "|" + assignment.server.getSession();
+    Iterator<TabletLocationState> currentIter = iterator();
+    TabletLocationState current = currentIter.next();
+    if (current.current != null) {
+      throw new DistributedStoreException("Trying to set the root tablet location: it is already set to " + current.current);
+    }
+    if (!current.future.equals(assignment.server)) {
+      throw new DistributedStoreException("Root tablet is already assigned to " + current.future);
+    }
+    store.put(RootTable.ZROOT_TABLET_LOCATION, value.getBytes());
+    store.put(RootTable.ZROOT_TABLET_LAST_LOCATION, value.getBytes());
+    // Make the following unnecessary by making the entire update atomic
+    store.remove(RootTable.ZROOT_TABLET_FUTURE_LOCATION);
+    log.debug("Put down root tablet location");
+  }
+  
+  @Override
+  public void unassign(Collection<TabletLocationState> tablets) throws DistributedStoreException {
+    if (tablets.size() != 1)
+      throw new IllegalArgumentException("There is only one root tablet");
+    TabletLocationState tls = tablets.iterator().next();
+    if (tls.extent.compareTo(RootTable.EXTENT) != 0)
+      throw new IllegalArgumentException("You can only store the root tablet location");
+    store.remove(RootTable.ZROOT_TABLET_LOCATION);
+    store.remove(RootTable.ZROOT_TABLET_FUTURE_LOCATION);
+    log.debug("unassign root tablet location");
+  }
+  
+  @Override
+  public String name() {
+    return "Root Tablet";
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/fc9363a0/server/base/src/main/java/org/apache/accumulo/server/master/tableOps/CompactionIterators.java
----------------------------------------------------------------------
diff --git a/server/base/src/main/java/org/apache/accumulo/server/master/tableOps/CompactionIterators.java b/server/base/src/main/java/org/apache/accumulo/server/master/tableOps/CompactionIterators.java
new file mode 100644
index 0000000..4f5bf42
--- /dev/null
+++ b/server/base/src/main/java/org/apache/accumulo/server/master/tableOps/CompactionIterators.java
@@ -0,0 +1,106 @@
+/*
+ * 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.server.master.tableOps;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.accumulo.core.client.IteratorSetting;
+import org.apache.hadoop.io.Text;
+import org.apache.hadoop.io.Writable;
+
+public class CompactionIterators implements Writable {
+  byte[] startRow;
+  byte[] endRow;
+  List<IteratorSetting> iterators;
+  
+  public CompactionIterators(byte[] startRow, byte[] endRow, List<IteratorSetting> iterators) {
+    this.startRow = startRow;
+    this.endRow = endRow;
+    this.iterators = iterators;
+  }
+  
+  public CompactionIterators() {
+    startRow = null;
+    endRow = null;
+    iterators = Collections.emptyList();
+  }
+  
+  @Override
+  public void write(DataOutput out) throws IOException {
+    out.writeBoolean(startRow != null);
+    if (startRow != null) {
+      out.writeInt(startRow.length);
+      out.write(startRow);
+    }
+    
+    out.writeBoolean(endRow != null);
+    if (endRow != null) {
+      out.writeInt(endRow.length);
+      out.write(endRow);
+    }
+    
+    out.writeInt(iterators.size());
+    for (IteratorSetting is : iterators) {
+      is.write(out);
+    }
+  }
+  
+  @Override
+  public void readFields(DataInput in) throws IOException {
+    if (in.readBoolean()) {
+      startRow = new byte[in.readInt()];
+      in.readFully(startRow);
+    } else {
+      startRow = null;
+    }
+    
+    if (in.readBoolean()) {
+      endRow = new byte[in.readInt()];
+      in.readFully(endRow);
+    } else {
+      endRow = null;
+    }
+    
+    int num = in.readInt();
+    iterators = new ArrayList<IteratorSetting>(num);
+    
+    for (int i = 0; i < num; i++) {
+      iterators.add(new IteratorSetting(in));
+    }
+  }
+  
+  public Text getEndRow() {
+    if (endRow == null)
+      return null;
+    return new Text(endRow);
+  }
+  
+  public Text getStartRow() {
+    if (startRow == null)
+      return null;
+    return new Text(startRow);
+  }
+  
+  public List<IteratorSetting> getIterators() {
+    return iterators;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/accumulo/blob/fc9363a0/server/base/src/main/java/org/apache/accumulo/server/tablets/TabletTime.java
----------------------------------------------------------------------
diff --git a/server/base/src/main/java/org/apache/accumulo/server/tablets/TabletTime.java b/server/base/src/main/java/org/apache/accumulo/server/tablets/TabletTime.java
new file mode 100644
index 0000000..bd4ceae
--- /dev/null
+++ b/server/base/src/main/java/org/apache/accumulo/server/tablets/TabletTime.java
@@ -0,0 +1,228 @@
+/*
+ * 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.server.tablets;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.accumulo.core.client.admin.TimeType;
+import org.apache.accumulo.core.data.Mutation;
+import org.apache.accumulo.server.data.ServerMutation;
+import org.apache.accumulo.server.util.time.RelativeTime;
+
+public abstract class TabletTime {
+  public static final char LOGICAL_TIME_ID = 'L';
+  public static final char MILLIS_TIME_ID = 'M';
+  
+  public static char getTimeID(TimeType timeType) {
+    switch (timeType) {
+      case LOGICAL:
+        return LOGICAL_TIME_ID;
+      case MILLIS:
+        return MILLIS_TIME_ID;
+    }
+    
+    throw new IllegalArgumentException("Unknown time type " + timeType);
+  }
+  
+  public abstract void useMaxTimeFromWALog(long time);
+  
+  public abstract String getMetadataValue(long time);
+  
+  public abstract String getMetadataValue();
+  
+  // abstract long setUpdateTimes(Mutation mutation);
+  public abstract long setUpdateTimes(List<Mutation> mutations);
+  
+  public abstract long getTime();
+  
+  public abstract long getAndUpdateTime();
+  
+  protected void setSystemTimes(Mutation mutation, long lastCommitTime) {
+    ServerMutation m = (ServerMutation) mutation;
+    m.setSystemTimestamp(lastCommitTime);
+  }
+  
+  public static TabletTime getInstance(String metadataValue) {
+    if (metadataValue.charAt(0) == LOGICAL_TIME_ID) {
+      return new LogicalTime(Long.parseLong(metadataValue.substring(1)));
+    } else if (metadataValue.charAt(0) == MILLIS_TIME_ID) {
+      return new MillisTime(Long.parseLong(metadataValue.substring(1)));
+    }
+    
+    throw new IllegalArgumentException("Time type unknown : " + metadataValue);
+    
+  }
+  
+  public static String maxMetadataTime(String mv1, String mv2) {
+    if (mv1 == null) {
+      checkType(mv2);
+      return mv2;
+    }
+    
+    if (mv2 == null) {
+      checkType(mv1);
+      return mv1;
+    }
+    
+    if (mv1.charAt(0) != mv2.charAt(0))
+      throw new IllegalArgumentException("Time types differ " + mv1 + " " + mv2);
+    checkType(mv1);
+    
+    long t1 = Long.parseLong(mv1.substring(1));
+    long t2 = Long.parseLong(mv2.substring(1));
+    
+    if (t1 < t2)
+      return mv2;
+    else
+      return mv1;
+    
+  }
+  
+  private static void checkType(String mv1) {
+    if (mv1.charAt(0) != LOGICAL_TIME_ID && mv1.charAt(0) != MILLIS_TIME_ID)
+      throw new IllegalArgumentException("Invalid time type " + mv1);
+  }
+  
+  static class MillisTime extends TabletTime {
+    
+    private long lastTime;
+    private long lastUpdateTime = 0;
+    
+    public MillisTime(long time) {
+      this.lastTime = time;
+    }
+    
+    @Override
+    public String getMetadataValue(long time) {
+      return MILLIS_TIME_ID + "" + time;
+    }
+    
+    @Override
+    public String getMetadataValue() {
+      return getMetadataValue(lastTime);
+    }
+    
+    @Override
+    public void useMaxTimeFromWALog(long time) {
+      if (time > lastTime)
+        lastTime = time;
+    }
+    
+    @Override
+    public long setUpdateTimes(List<Mutation> mutations) {
+      
+      long currTime = RelativeTime.currentTimeMillis();
+      
+      synchronized (this) {
+        if (mutations.size() == 0)
+          return lastTime;
+        
+        currTime = updateTime(currTime);
+      }
+      
+      for (Mutation mutation : mutations)
+        setSystemTimes(mutation, currTime);
+      
+      return currTime;
+    }
+    
+    private long updateTime(long currTime) {
+      if (currTime < lastTime) {
+        if (currTime - lastUpdateTime > 0) {
+          // not in same millisecond as last call
+          // to this method so move ahead slowly
+          lastTime++;
+        }
+        
+        lastUpdateTime = currTime;
+        
+        currTime = lastTime;
+      } else {
+        lastTime = currTime;
+      }
+      return currTime;
+    }
+    
+    @Override
+    public long getTime() {
+      return lastTime;
+    }
+    
+    @Override
+    public long getAndUpdateTime() {
+      long currTime = RelativeTime.currentTimeMillis();
+      
+      synchronized (this) {
+        currTime = updateTime(currTime);
+      }
+      
+      return currTime;
+    }
+    
+  }
+  
+  static class LogicalTime extends TabletTime {
+    AtomicLong nextTime;
+    
+    private LogicalTime(Long time) {
+      this.nextTime = new AtomicLong(time.longValue() + 1);
+    }
+    
+    @Override
+    public void useMaxTimeFromWALog(long time) {
+      time++;
+      
+      if (this.nextTime.get() < time) {
+        this.nextTime.set(time);
+      }
+    }
+    
+    @Override
+    public String getMetadataValue() {
+      return getMetadataValue(getTime());
+    }
+    
+    @Override
+    public String getMetadataValue(long time) {
+      return LOGICAL_TIME_ID + "" + time;
+    }
+    
+    @Override
+    public long setUpdateTimes(List<Mutation> mutations) {
+      if (mutations.size() == 0)
+        return getTime();
+      
+      long time = nextTime.getAndAdd(mutations.size());
+      for (Mutation mutation : mutations)
+        setSystemTimes(mutation, time++);
+      
+      return time - 1;
+    }
+    
+    @Override
+    public long getTime() {
+      return nextTime.get() - 1;
+    }
+    
+    @Override
+    public long getAndUpdateTime() {
+      return nextTime.getAndIncrement();
+    }
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/fc9363a0/server/base/src/main/java/org/apache/accumulo/server/tablets/UniqueNameAllocator.java
----------------------------------------------------------------------
diff --git a/server/base/src/main/java/org/apache/accumulo/server/tablets/UniqueNameAllocator.java b/server/base/src/main/java/org/apache/accumulo/server/tablets/UniqueNameAllocator.java
new file mode 100644
index 0000000..57b9b32
--- /dev/null
+++ b/server/base/src/main/java/org/apache/accumulo/server/tablets/UniqueNameAllocator.java
@@ -0,0 +1,79 @@
+/*
+ * 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.server.tablets;
+
+import java.util.Random;
+
+import org.apache.accumulo.core.Constants;
+import org.apache.accumulo.core.util.FastFormat;
+import org.apache.accumulo.core.zookeeper.ZooUtil;
+import org.apache.accumulo.server.client.HdfsZooInstance;
+import org.apache.accumulo.server.zookeeper.ZooReaderWriter;
+
+/**
+ * Allocates unique names for an accumulo instance. The names are unique for the lifetime of the instance.
+ * 
+ * This is useful for filenames because it makes caching easy.
+ * 
+ */
+
+public class UniqueNameAllocator {
+  private long next = 0;
+  private long maxAllocated = 0;
+  private String nextNamePath;
+  private Random rand;
+  
+  private UniqueNameAllocator() {
+    nextNamePath = Constants.ZROOT + "/" + HdfsZooInstance.getInstance().getInstanceID() + Constants.ZNEXT_FILE;
+    rand = new Random();
+  }
+  
+  public synchronized String getNextName() {
+    
+    while (next >= maxAllocated) {
+      final int allocate = 100 + rand.nextInt(100);
+      
+      try {
+        byte[] max = ZooReaderWriter.getRetryingInstance().mutate(nextNamePath, null, ZooUtil.PRIVATE, new ZooReaderWriter.Mutator() {
+          public byte[] mutate(byte[] currentValue) throws Exception {
+            long l = Long.parseLong(new String(currentValue), Character.MAX_RADIX);
+            l += allocate;
+            return Long.toString(l, Character.MAX_RADIX).getBytes();
+          }
+        });
+        
+        maxAllocated = Long.parseLong(new String(max), Character.MAX_RADIX);
+        next = maxAllocated - allocate;
+        
+      } catch (Exception e) {
+        throw new RuntimeException(e);
+      }
+    }
+    
+    return new String(FastFormat.toZeroPaddedString(next++, 7, Character.MAX_RADIX, new byte[0]));
+  }
+  
+  private static UniqueNameAllocator instance = null;
+  
+  public static synchronized UniqueNameAllocator getInstance() {
+    if (instance == null)
+      instance = new UniqueNameAllocator();
+    
+    return instance;
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/fc9363a0/server/base/src/main/java/org/apache/accumulo/server/tabletserver/TabletTime.java
----------------------------------------------------------------------
diff --git a/server/base/src/main/java/org/apache/accumulo/server/tabletserver/TabletTime.java b/server/base/src/main/java/org/apache/accumulo/server/tabletserver/TabletTime.java
deleted file mode 100644
index c7cfc59..0000000
--- a/server/base/src/main/java/org/apache/accumulo/server/tabletserver/TabletTime.java
+++ /dev/null
@@ -1,224 +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.server.tabletserver;
-
-import java.util.List;
-import java.util.concurrent.atomic.AtomicLong;
-
-import org.apache.accumulo.core.client.admin.TimeType;
-import org.apache.accumulo.core.data.Mutation;
-import org.apache.accumulo.server.data.ServerMutation;
-import org.apache.accumulo.server.util.time.RelativeTime;
-
-public abstract class TabletTime {
-  public static final char LOGICAL_TIME_ID = 'L';
-  public static final char MILLIS_TIME_ID = 'M';
-  
-  public static char getTimeID(TimeType timeType) {
-    switch (timeType) {
-      case LOGICAL:
-        return LOGICAL_TIME_ID;
-      case MILLIS:
-        return MILLIS_TIME_ID;
-    }
-    
-    throw new IllegalArgumentException("Unknown time type " + timeType);
-  }
-  
-  abstract void useMaxTimeFromWALog(long time);
-  
-  abstract String getMetadataValue(long time);
-  
-  abstract String getMetadataValue();
-  
-  // abstract long setUpdateTimes(Mutation mutation);
-  abstract long setUpdateTimes(List<Mutation> mutations);
-  
-  abstract long getTime();
-  
-  abstract long getAndUpdateTime();
-  
-  protected void setSystemTimes(Mutation mutation, long lastCommitTime) {
-    ServerMutation m = (ServerMutation)mutation;
-    m.setSystemTimestamp(lastCommitTime);
-  }
-  
-  static TabletTime getInstance(String metadataValue) {
-    if (metadataValue.charAt(0) == LOGICAL_TIME_ID) {
-      return new LogicalTime(Long.parseLong(metadataValue.substring(1)));
-    } else if (metadataValue.charAt(0) == MILLIS_TIME_ID) {
-      return new MillisTime(Long.parseLong(metadataValue.substring(1)));
-    }
-    
-    throw new IllegalArgumentException("Time type unknown : " + metadataValue);
-    
-  }
-  
-  public static String maxMetadataTime(String mv1, String mv2) {
-    if (mv1 == null) {
-      checkType(mv2);
-      return mv2;
-    }
-    
-    if (mv2 == null) {
-      checkType(mv1);
-      return mv1;
-    }
-    
-    if (mv1.charAt(0) != mv2.charAt(0)) throw new IllegalArgumentException("Time types differ " + mv1 + " " + mv2);
-    checkType(mv1);
-    
-    long t1 = Long.parseLong(mv1.substring(1));
-    long t2 = Long.parseLong(mv2.substring(1));
-    
-    if (t1 < t2) return mv2;
-    else return mv1;
-    
-  }
-  
-  private static void checkType(String mv1) {
-    if (mv1.charAt(0) != LOGICAL_TIME_ID && mv1.charAt(0) != MILLIS_TIME_ID) throw new IllegalArgumentException("Invalid time type " + mv1);
-  }
-  
-  static class MillisTime extends TabletTime {
-    
-    private long lastTime;
-    private long lastUpdateTime = 0;
-    
-    public MillisTime(long time) {
-      this.lastTime = time;
-    }
-    
-    @Override
-    String getMetadataValue(long time) {
-      return MILLIS_TIME_ID + "" + time;
-    }
-    
-    @Override
-    public String getMetadataValue() {
-      return getMetadataValue(lastTime);
-    }
-    
-    @Override
-    void useMaxTimeFromWALog(long time) {
-      if (time > lastTime)
-        lastTime = time;
-    }
-    
-    @Override
-    long setUpdateTimes(List<Mutation> mutations) {
-      
-      long currTime = RelativeTime.currentTimeMillis();
-      
-      synchronized (this) {
-        if (mutations.size() == 0)
-          return lastTime;
-        
-        currTime = updateTime(currTime);
-      }
-      
-      for (Mutation mutation : mutations)
-        setSystemTimes(mutation, currTime);
-      
-      return currTime;
-    }
-    
-    private long updateTime(long currTime) {
-      if (currTime < lastTime) {
-        if (currTime - lastUpdateTime > 0) {
-          // not in same millisecond as last call
-          // to this method so move ahead slowly
-          lastTime++;
-        }
-        
-        lastUpdateTime = currTime;
-        
-        currTime = lastTime;
-      } else {
-        lastTime = currTime;
-      }
-      return currTime;
-    }
-    
-    @Override
-    long getTime() {
-      return lastTime;
-    }
-    
-    @Override
-    long getAndUpdateTime() {
-      long currTime = RelativeTime.currentTimeMillis();
-      
-      synchronized (this) {
-        currTime = updateTime(currTime);
-      }
-      
-      return currTime;
-    }
-    
-  }
-  
-  static class LogicalTime extends TabletTime {
-    AtomicLong nextTime;
-    
-    private LogicalTime(Long time) {
-      this.nextTime = new AtomicLong(time.longValue() + 1);
-    }
-    
-    @Override
-    void useMaxTimeFromWALog(long time) {
-      time++;
-      
-      if (this.nextTime.get() < time) {
-        this.nextTime.set(time);
-      }
-    }
-    
-    @Override
-    public String getMetadataValue() {
-      return getMetadataValue(getTime());
-    }
-    
-    @Override
-    public String getMetadataValue(long time) {
-      return LOGICAL_TIME_ID + "" + time;
-    }
-    
-    @Override
-    long setUpdateTimes(List<Mutation> mutations) {
-      if (mutations.size() == 0)
-        return getTime();
-      
-      long time = nextTime.getAndAdd(mutations.size());
-      for (Mutation mutation : mutations)
-        setSystemTimes(mutation, time++);
-      
-      return time - 1;
-    }
-    
-    @Override
-    long getTime() {
-      return nextTime.get() - 1;
-    }
-    
-    @Override
-    long getAndUpdateTime() {
-      return nextTime.getAndIncrement();
-    }
-  }
-  
-}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/fc9363a0/server/base/src/main/java/org/apache/accumulo/server/tabletserver/UniqueNameAllocator.java
----------------------------------------------------------------------
diff --git a/server/base/src/main/java/org/apache/accumulo/server/tabletserver/UniqueNameAllocator.java b/server/base/src/main/java/org/apache/accumulo/server/tabletserver/UniqueNameAllocator.java
deleted file mode 100644
index 9629948..0000000
--- a/server/base/src/main/java/org/apache/accumulo/server/tabletserver/UniqueNameAllocator.java
+++ /dev/null
@@ -1,79 +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.server.tabletserver;
-
-import java.util.Random;
-
-import org.apache.accumulo.core.Constants;
-import org.apache.accumulo.core.util.FastFormat;
-import org.apache.accumulo.core.zookeeper.ZooUtil;
-import org.apache.accumulo.server.client.HdfsZooInstance;
-import org.apache.accumulo.server.zookeeper.ZooReaderWriter;
-
-/**
- * Allocates unique names for an accumulo instance. The names are unique for the lifetime of the instance.
- * 
- * This is useful for filenames because it makes caching easy.
- * 
- */
-
-public class UniqueNameAllocator {
-  private long next = 0;
-  private long maxAllocated = 0;
-  private String nextNamePath;
-  private Random rand;
-  
-  private UniqueNameAllocator() {
-    nextNamePath = Constants.ZROOT + "/" + HdfsZooInstance.getInstance().getInstanceID() + Constants.ZNEXT_FILE;
-    rand = new Random();
-  }
-  
-  public synchronized String getNextName() {
-    
-    while (next >= maxAllocated) {
-      final int allocate = 100 + rand.nextInt(100);
-      
-      try {
-        byte[] max = ZooReaderWriter.getRetryingInstance().mutate(nextNamePath, null, ZooUtil.PRIVATE, new ZooReaderWriter.Mutator() {
-          public byte[] mutate(byte[] currentValue) throws Exception {
-            long l = Long.parseLong(new String(currentValue), Character.MAX_RADIX);
-            l += allocate;
-            return Long.toString(l, Character.MAX_RADIX).getBytes();
-          }
-        });
-        
-        maxAllocated = Long.parseLong(new String(max), Character.MAX_RADIX);
-        next = maxAllocated - allocate;
-        
-      } catch (Exception e) {
-        throw new RuntimeException(e);
-      }
-    }
-    
-    return new String(FastFormat.toZeroPaddedString(next++, 7, Character.MAX_RADIX, new byte[0]));
-  }
-  
-  private static UniqueNameAllocator instance = null;
-  
-  public static synchronized UniqueNameAllocator getInstance() {
-    if (instance == null)
-      instance = new UniqueNameAllocator();
-    
-    return instance;
-  }
-  
-}


Mime
View raw message