static boolean unprotectedSetTimes(
      FSDirectory fsd, INodesInPath iip, long mtime, long atime, boolean force)
      throws FileNotFoundException {
    assert fsd.hasWriteLock();
    boolean status = false;
    INode inode = iip.getLastINode();
    if (inode == null) {
      throw new FileNotFoundException("File/Directory " + iip.getPath() +
          " does not exist.");
    }
    int latest = iip.getLatestSnapshotId();
    if (mtime >= 0) {
      inode = inode.setModificationTime(mtime, latest);
      status = true;
    }

    // if the last access time update was within the last precision interval,
    // then no need to store access time
    if (atime >= 0 && (status || force
        || atime > inode.getAccessTime() + fsd.getAccessTimePrecision())) {
      inode.setAccessTime(atime, latest,
          fsd.getFSNamesystem().getSnapshotManager().
          getSkipCaptureAccessTimeOnlyChange());
      status = true;
    }
    return status;
  }
@Test
  public void testUnprotectedSetTimes() throws Exception {
    // atime < access time + precision
    assertFalse("SetTimes should not update access time "
          + "because it's within the last precision interval",
        unprotectedSetTimes(100, 0, 1000, -1, false));

    // atime = access time + precision
    assertFalse("SetTimes should not update access time "
          + "because it's within the last precision interval",
        unprotectedSetTimes(1000, 0, 1000, -1, false));

    // atime > access time + precision
    assertTrue("SetTimes should update access time",
        unprotectedSetTimes(1011, 10, 1000, -1, false));

    // atime < access time + precision, but force is set
    assertTrue("SetTimes should update access time",
        unprotectedSetTimes(100, 0, 1000, -1, true));

    // atime < access time + precision, but mtime is set
    assertTrue("SetTimes should update access time",
        unprotectedSetTimes(100, 0, 1000, 1, false));
  }