public long doUpdate(Master master, UpdateRequest updateRequest) {
    incrementAccessAndMaybeRecalibrate(master);
    File f = updateRequest.getFile();
    Location accessLoc = updateRequest.getLocation();
    MasterMeta fm = master.map.get(f.getId());
    boolean allSucceeded = true;
    long maxDelay = -1;
    Set<Cluster> clustersToRemove = new HashSet<Cluster>();
    for (Cluster c : fm.instances) {
      boolean allNodesSucceeded = true;
      ClusterMeta cm = c.map.get(f.getId());
      if (!c.isHealthy()) {
        allNodesSucceeded = false;
      } else {
        double cDist = c.getLocation().distance(accessLoc);
        long networkTime = Util.networkTime(f.getSize(), cDist);
        for (Node n : cm.instances) {
          long writeTime = n.store(f);
          if (writeTime > 0) {
            maxDelay = Math.max(maxDelay, writeTime + networkTime);
          } else {
            allSucceeded = false;
            allNodesSucceeded = false;
            break;
          }
        }
      }
      if (!allNodesSucceeded) {
        for (Node n : cm.instances) {
          n.delete(f);
        }
        cm.instances.clear();
        clustersToRemove.add(c);
      }
    }
    fm.instances.removeAll(clustersToRemove);
    long rewriteTime = updateRewrite(master, f, accessLoc, clustersToRemove.size());
    return allSucceeded ? maxDelay : (rewriteTime > 0 ? maxDelay + rewriteTime : -1);
  }