public void removeMap(String mapId) {
    IndexInformation info = cache.get(mapId);
    if (info == null || isUnderConstruction(info)) {
      return;
    }
    info = cache.remove(mapId);
    if (info != null) {
      totalMemoryUsed.addAndGet(-info.getSize());
      if (!queue.remove(mapId)) {
        LOG.warn("Map ID" + mapId + " not found in queue!!");
      }
    } else {
      LOG.info("Map ID " + mapId + " not found in cache");
    }
  }
@Test
  public void testRemoveMap() throws Exception {
    // This test case use two thread to call getIndexInformation and 
    // removeMap concurrently, in order to construct race condition.
    // This test case may not repeatable. But on my macbook this test 
    // fails with probability of 100% on code before MAPREDUCE-2541,
    // so it is repeatable in practice.
    fs.delete(p, true);
    conf.setInt(MRJobConfig.SHUFFLE_INDEX_CACHE, 10);
    // Make a big file so removeMapThread almost surely runs faster than 
    // getInfoThread 
    final int partsPerMap = 100000;
    final int bytesPerFile = partsPerMap * 24;
    final IndexCache cache = new IndexCache(conf);

    final Path big = new Path(p, "bigIndex");
    final String user = 
      UserGroupInformation.getCurrentUser().getShortUserName();
    writeFile(fs, big, bytesPerFile, partsPerMap);
    
    // run multiple times
    for (int i = 0; i < 20; ++i) {
      Thread getInfoThread = new Thread() {
        @Override
        public void run() {
          try {
            cache.getIndexInformation("bigIndex", partsPerMap, big, user);
          } catch (Exception e) {
            // should not be here
          }
        }
      };
      Thread removeMapThread = new Thread() {
        @Override
        public void run() {
          cache.removeMap("bigIndex");
        }
      };
      if (i%2==0) {
        getInfoThread.start();
        removeMapThread.start();        
      } else {
        removeMapThread.start();        
        getInfoThread.start();
      }
      getInfoThread.join();
      removeMapThread.join();
      assertTrue(cache.checkTotalMemoryUsed());
    }      
  }