DHT: Support removing a repository name

The first step to deleting a repository from the DHT storage is to
remove the name binding in the RepositoryIndexTable, making the
repository unavailable for lookup.

Change-Id: I469bf92f4bf2f555a15949569b21937c14cb142b
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
diff --git a/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/spi/RepositoryIndexTable.java b/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/spi/RepositoryIndexTable.java
index 794db6e..36afd13 100644
--- a/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/spi/RepositoryIndexTable.java
+++ b/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/spi/RepositoryIndexTable.java
@@ -87,4 +87,21 @@ public RepositoryKey get(RepositoryName name) throws DhtException,
 	 */
 	public void putUnique(RepositoryName name, RepositoryKey key)
 			throws DhtException, TimeoutException;
+
+	/**
+	 * Remove the association of a name to an identifier.
+	 * <p>
+	 * This method must use some sort of transaction system to ensure the name
+	 * is removed only if it currently references {@code key}. This may require
+	 * running some sort of lock management service in parallel to the database.
+	 *
+	 * @param name
+	 *            name of the repository.
+	 * @param key
+	 *            internal key defining the repository.
+	 * @throws DhtException
+	 * @throws TimeoutException
+	 */
+	public void remove(RepositoryName name, RepositoryKey key)
+			throws DhtException, TimeoutException;
 }
diff --git a/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/spi/cache/CacheRepositoryIndexTable.java b/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/spi/cache/CacheRepositoryIndexTable.java
index 5ff4391..b50092c 100644
--- a/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/spi/cache/CacheRepositoryIndexTable.java
+++ b/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/spi/cache/CacheRepositoryIndexTable.java
@@ -128,4 +128,18 @@ public void putUnique(RepositoryName name, RepositoryKey key)
 			throw new TimeoutException();
 		}
 	}
+
+	public void remove(RepositoryName name, RepositoryKey key)
+			throws DhtException, TimeoutException {
+		db.remove(name, key);
+
+		Sync<Void> sync = Sync.create();
+		CacheKey memKey = ns.key(name);
+		client.modify(singleton(Change.remove(memKey)), sync);
+		try {
+			sync.get(options.getTimeout());
+		} catch (InterruptedException e) {
+			throw new TimeoutException();
+		}
+	}
 }
diff --git a/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/spi/memory/MemRepositoryIndexTable.java b/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/spi/memory/MemRepositoryIndexTable.java
index 46a1fd6..000ff77 100644
--- a/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/spi/memory/MemRepositoryIndexTable.java
+++ b/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/spi/memory/MemRepositoryIndexTable.java
@@ -78,4 +78,16 @@ public void putUnique(RepositoryName name, RepositoryKey key)
 			throw new DhtException(MessageFormat.format(
 					DhtText.get().repositoryAlreadyExists, name.asString()));
 	}
+
+	public void remove(RepositoryName name, RepositoryKey key)
+			throws DhtException, TimeoutException {
+		boolean ok = table.compareAndSet(
+				name.asBytes(),
+				colId.name(),
+				key.asBytes(),
+				null);
+		if (!ok)
+			throw new DhtException(MessageFormat.format(
+					DhtText.get().repositoryAlreadyExists, name.asString()));
+	}
 }