@ApiStatus.Internal
  synchronized public void disconnect() {
    if (myConnected.compareAndSet(true, false)) {
      for (PersistentFsConnectionListener listener : PersistentFsConnectionListener.EP_NAME.getExtensionList()) {
        listener.beforeConnectionClosed();
      }

      LOG.info("VFS dispose started");
      long startedAtNs = System.nanoTime();
      try {
        //Give LFSystem a chance to clear caches/stop file watchers:
        //TODO RC: would be much better use PersistentFsConnectionListener or alike instead of direct calling
        //         (PFSImpl shouldn't even explicitly know that LocalFileSystem needs cleaning)
        ((LocalFileSystemImpl)LocalFileSystem.getInstance()).onDisconnecting();
        // TODO make sure we don't have files in memory
        myRoots.clear();
        myIdToDirCache.clear();
        missedRootIds.clear();
      }
      finally {
        FSRecordsImpl vfsPeer = this.vfsPeer;
        if (vfsPeer != null && !vfsPeer.isClosed()) {
          vfsPeer.close();
          //better not set this.vfsPeer=null, but leave it as-is: on access instead of just NPE we'll get
          // more understandable AlreadyDisposedException with additional diagnostic info
        }
      }
      LOG.info("VFS dispose completed in " + NANOSECONDS.toMillis(System.nanoTime() - startedAtNs) + " ms.");
    }
  }
@ApiStatus.Internal
  synchronized public void disconnect()