private @NotNull List<? extends ChildInfo> persistAllChildren(VirtualFile dir, int dirId) {
    NewVirtualFileSystem fs = getFileSystem(dir);

    //FIXME RC: this method is not thread-safe: it creates new file records from children names outside
    //          of lock, hence it is possible >1 child to be created for the same name, and only
    //          last children list remains written, while children created during invocations that
    //          lost the race are remains orphan
    try {
      String[] fsNames = VfsUtil.filterNames(
        fs instanceof LocalFileSystemImpl ? ((LocalFileSystemImpl)fs).listWithCaching(dir) : fs.list(dir)
      );

      Map<String, ChildInfo> justCreated = new HashMap<>();
      ListResult saved = vfsPeer.update(dir, dirId, current -> {
        List<? extends ChildInfo> currentChildren = current.children;
        if (fsNames.length == 0 && !currentChildren.isEmpty()) {
          return current;
        }
        // preserve current children which match fsNames (to have stable id)
        // (on case-insensitive systems, replace those from current with case-changes ones from fsNames preserving the id)
        // add those from fsNames which are absent from current
        boolean caseSensitive = dir.isCaseSensitive();
        Set<String> toAddNames = CollectionFactory.createFilePathSet(fsNames, caseSensitive);
        for (ChildInfo currentChild : currentChildren) {
          toAddNames.remove(currentChild.getName().toString());
        }

        List<ChildInfo> toAddChildren = new ArrayList<>(toAddNames.size());
        if (fs instanceof BatchingFileSystem) {
          Map<String, FileAttributes> map = ((BatchingFileSystem)fs).listWithAttributes(dir, toAddNames);
          for (Map.Entry<String, FileAttributes> entry : map.entrySet()) {
            String newName = entry.getKey();
            FileAttributes attrs = entry.getValue();
            String target = attrs.isSymLink() ? fs.resolveSymLink(new FakeVirtualFile(dir, newName)) : null;
            Pair<@NotNull FileAttributes, String> childData = getChildData(fs, dir, newName, attrs, target);
            ChildInfo newChild = justCreated.computeIfAbsent(newName, name -> makeChildRecord(dir, dirId, name, childData, fs, null));
            toAddChildren.add(newChild);
          }
        }
        else {
          for (String newName : toAddNames) {
            Pair<@NotNull FileAttributes, String> childData = getChildData(fs, dir, newName, null, null);
            if (childData != null) {
              ChildInfo newChild = justCreated.computeIfAbsent(newName, name -> makeChildRecord(dir, dirId, name, childData, fs, null));
              toAddChildren.add(newChild);
            }
          }
        }

        // some clients (e.g. RefreshWorker) expect subsequent list() calls to return equal arrays
        toAddChildren.sort(ChildInfo.BY_ID);
        return current.merge(vfsPeer, toAddChildren, caseSensitive);
      });

      setChildrenCached(dirId);

      return saved.children;
    }
    finally {
      if (fs instanceof LocalFileSystemImpl) {
        ((LocalFileSystemImpl)fs).clearListCache();
      }
    }
  }
private @NotNull List<? extends ChildInfo> persistAllChildren(VirtualFile dir, int dirId)