private void removeFilesInIndex(
     List<Object> filesToRemove,
     List<IIndexFragmentFile> indexFilesToRemove,
     IProgressMonitor monitor)
     throws InterruptedException, CoreException {
   if (!filesToRemove.isEmpty() || !indexFilesToRemove.isEmpty()) {
     fIndex.acquireWriteLock();
     try {
       for (Object tu : filesToRemove) {
         if (monitor.isCanceled()) {
           return;
         }
         IIndexFileLocation ifl = fResolver.resolveFile(tu);
         if (ifl == null) continue;
         IIndexFragmentFile[] ifiles = fIndex.getWritableFiles(ifl);
         for (IIndexFragmentFile ifile : ifiles) {
           fIndex.clearFile(ifile);
         }
         incrementRequestedFilesCount(-1);
       }
       for (IIndexFragmentFile ifile : indexFilesToRemove) {
         if (monitor.isCanceled()) {
           return;
         }
         fIndex.clearFile(ifile);
         incrementRequestedFilesCount(-1);
       }
     } finally {
       fIndex.releaseWriteLock();
     }
   }
   filesToRemove.clear();
 }
 public IIndexFragmentFile[] getAvailableIndexFiles(int linkageID, IIndexFileLocation ifl)
     throws CoreException {
   IIndexFragmentFile[] files = fIndexFilesCache.get(ifl);
   if (files == null) {
     IIndexFragmentFile[] fragFiles = fIndex.getWritableFiles(linkageID, ifl);
     int j = 0;
     for (int i = 0; i < fragFiles.length; i++) {
       if (fragFiles[i].hasContent()) {
         if (j != i) fragFiles[j] = fragFiles[i];
         j++;
       }
     }
     if (j == fragFiles.length) {
       files = fragFiles;
     } else {
       files = new IIndexFragmentFile[j];
       System.arraycopy(fragFiles, 0, files, 0, j);
     }
     fIndexFilesCache.put(ifl, files);
   }
   return files;
 }
  private void extractFiles(
      HashMap<Integer, List<IIndexFileLocation>> files,
      List<IIndexFragmentFile> iFilesToRemove,
      IProgressMonitor monitor)
      throws CoreException {
    final boolean forceAll = (fUpdateFlags & IIndexManager.UPDATE_ALL) != 0;
    final boolean checkTimestamps = (fUpdateFlags & IIndexManager.UPDATE_CHECK_TIMESTAMPS) != 0;
    final boolean checkFileContentsHash =
        (fUpdateFlags & IIndexManager.UPDATE_CHECK_CONTENTS_HASH) != 0;
    final boolean forceUnresolvedIncludes =
        (fUpdateFlags & IIndexManager.UPDATE_UNRESOLVED_INCLUDES) != 0;
    final boolean both = fIndexHeadersWithoutContext == UnusedHeaderStrategy.useBoth;
    int count = 0;
    int forceFirst = fForceNumberFiles;
    BitSet linkages = new BitSet();
    for (final Object tu : fFilesToUpdate) {
      if (monitor.isCanceled()) return;

      final boolean force = forceAll || --forceFirst >= 0;
      final IIndexFileLocation ifl = fResolver.resolveFile(tu);
      if (ifl == null) continue;

      final IIndexFragmentFile[] indexFiles = fIndex.getWritableFiles(ifl);
      final boolean isSourceUnit = fResolver.isSourceUnit(tu);
      linkages.clear();
      final boolean regularContent = isRequiredInIndex(tu, ifl, isSourceUnit);
      final boolean indexedUnconditionally = fResolver.isIndexedUnconditionally(ifl);
      if (regularContent || indexedUnconditionally) {
        // Headers or sources required with a specific linkage
        final UpdateKind updateKind =
            isSourceUnit
                ? UpdateKind.REQUIRED_SOURCE
                : regularContent && both
                    ? UpdateKind.REQUIRED_HEADER
                    : UpdateKind.ONE_LINKAGE_HEADER;
        if (regularContent || indexFiles.length == 0) {
          AbstractLanguage[] langs = fResolver.getLanguages(tu, fIndexHeadersWithoutContext);
          for (AbstractLanguage lang : langs) {
            int linkageID = lang.getLinkageID();
            boolean foundInLinkage = false;
            for (int i = 0; i < indexFiles.length; i++) {
              IIndexFragmentFile ifile = indexFiles[i];
              if (ifile != null && ifile.getLinkageID() == linkageID && ifile.hasContent()) {
                foundInLinkage = true;
                indexFiles[i] = null; // Take the file.
                boolean update =
                    force
                        || (forceUnresolvedIncludes && ifile.hasUnresolvedInclude())
                        || isModified(checkTimestamps, checkFileContentsHash, ifl, tu, ifile);
                if (update && requestUpdate(linkageID, ifl, ifile, tu, updateKind)) {
                  count++;
                  linkages.set(linkageID);
                }
              }
            }
            if (!foundInLinkage && requestUpdate(linkageID, ifl, null, tu, updateKind)) {
              linkages.set(linkageID);
              count++;
            }
          }
        }
      }

      // Handle other files present in index.
      for (IIndexFragmentFile ifile : indexFiles) {
        if (ifile != null) {
          IIndexInclude ctx = ifile.getParsedInContext();
          if (ctx == null && !indexedUnconditionally && ifile.hasContent()) {
            iFilesToRemove.add(ifile);
            count++;
          } else {
            boolean update =
                force
                    || (forceUnresolvedIncludes && ifile.hasUnresolvedInclude())
                    || isModified(checkTimestamps, checkFileContentsHash, ifl, tu, ifile);
            final int linkageID = ifile.getLinkageID();
            if (update && requestUpdate(linkageID, ifl, ifile, tu, UpdateKind.OTHER_HEADER)) {
              count++;
              linkages.set(linkageID);
            }
          }
        }
      }
      for (int lid = linkages.nextSetBit(0); lid >= 0; lid = linkages.nextSetBit(lid + 1)) {
        addPerLinkage(lid, ifl, files);
      }
    }
    synchronized (this) {
      incrementRequestedFilesCount(count - fFilesToUpdate.length);
      fFilesToUpdate = null;
    }
  }