@VisibleForTesting
  public void refreshEntries(final Collection<MountTable> entries) {
    // The tree read/write must be atomic
    writeLock.lock();
    try {
      // New entries
      Map<String, MountTable> newEntries = new ConcurrentHashMap<>();
      for (MountTable entry : entries) {
        String srcPath = entry.getSourcePath();
        newEntries.put(srcPath, entry);
      }

      // Old entries (reversed to sort from the leaves to the root)
      Set<String> oldEntries = new TreeSet<>(Collections.reverseOrder());
      for (MountTable entry : getTreeValues("/")) {
        String srcPath = entry.getSourcePath();
        oldEntries.add(srcPath);
      }

      // Entries that need to be removed
      for (String srcPath : oldEntries) {
        if (!newEntries.containsKey(srcPath)) {
          this.tree.remove(srcPath);
          invalidateLocationCache(srcPath);
          LOG.info("Removed stale mount point {} from resolver", srcPath);
        }
      }

      // Entries that need to be added
      for (MountTable entry : entries) {
        String srcPath = entry.getSourcePath();
        if (!oldEntries.contains(srcPath)) {
          // Add node, it does not exist
          this.tree.put(srcPath, entry);
          invalidateLocationCache(srcPath);
          LOG.info("Added new mount point {} to resolver", srcPath);
        } else {
          // Node exists, check for updates
          MountTable existingEntry = this.tree.get(srcPath);
          if (existingEntry != null && !existingEntry.equals(entry)) {
            LOG.info("Entry has changed from \"{}\" to \"{}\"",
                existingEntry, entry);
            this.tree.put(srcPath, entry);
            invalidateLocationCache(srcPath);
            LOG.info("Updated mount point {} in resolver", srcPath);
          }
        }
      }
    } finally {
      writeLock.unlock();
    }
    this.init = true;
  }
@Test
  public void testRefreshEntries()
      throws UnsupportedOperationException, IOException {

    // Initial table loaded
    testDestination();
    assertEquals(10, mountTable.getMounts("/").size());

    // Replace table with /1 and /2
    List<MountTable> records = new ArrayList<>();
    Map<String, String> map1 = getMountTableEntry("1", "/");
    records.add(MountTable.newInstance("/1", map1));
    Map<String, String> map2 = getMountTableEntry("2", "/");
    records.add(MountTable.newInstance("/2", map2));
    mountTable.refreshEntries(records);

    // Verify addition
    PathLocation destination1 = mountTable.getDestinationForPath("/1");
    RemoteLocation defaultLoc1 = destination1.getDefaultLocation();
    assertEquals("1", defaultLoc1.getNameserviceId());

    PathLocation destination2 = mountTable.getDestinationForPath("/2");
    RemoteLocation defaultLoc2 = destination2.getDefaultLocation();
    assertEquals("2", defaultLoc2.getNameserviceId());

    // Verify existing entries were removed
    assertEquals(2, mountTable.getMounts("/").size());
    boolean assertionThrown = false;
    try {
      testDestination();
      fail();
    } catch (AssertionError e) {
      // The / entry was removed, so it triggers an exception
      assertionThrown = true;
    }
    assertTrue(assertionThrown);
  }