private void cachePeeledState(Ref oldLeaf, Ref newLeaf) {
    // TODO(spearce) Use an ExecutorService here
    try {
      RepositoryKey repo = repository.getRepositoryKey();
      RefKey key = RefKey.create(repo, newLeaf.getName());
      RefData oldData = ((DhtRef) oldLeaf).getRefData();
      RefData newData = ((DhtRef) newLeaf).getRefData();
      db.ref().compareAndPut(key, oldData, newData);
    } catch (TimeoutException e) {
      // Ignore a timeout here, we were only trying to update
      // a cached value to save peeling costs in the future.

    } catch (DhtException e) {
      // Ignore a database error, this was only an attempt to
      // fix a value that could be cached to save time later.
    }
  }
  @Override
  public DhtRefUpdate newUpdate(String refName, boolean detach) throws IOException {
    boolean detachingSymbolicRef = false;
    DhtRef ref = getOneRef(refName);
    if (ref == null) ref = new DhtObjectIdRef(refName, NONE);
    else detachingSymbolicRef = detach && ref.isSymbolic();

    if (detachingSymbolicRef) {
      RefData src = ((DhtRef) ref.getLeaf()).getRefData();
      RefData.Builder b = RefData.newBuilder(ref.getRefData());
      b.clearSymref();
      b.setTarget(src.getTarget());
      ref = new DhtObjectIdRef(refName, b.build());
    }

    RepositoryKey repo = repository.getRepositoryKey();
    DhtRefUpdate update = new DhtRefUpdate(this, repo, db, ref);
    if (detachingSymbolicRef) update.setDetachingSymbolicRef();
    return update;
  }
 private Set<Map.Entry<RefKey, RefData>> scan() throws DhtException, TimeoutException {
   // TODO(spearce) Do we need to perform READ_REPAIR here?
   RepositoryKey repo = repository.getRepositoryKey();
   return db.ref().getAll(Context.LOCAL, repo).entrySet();
 }