private static void invalidateIndex() {
   LOG.info("Marking VFS as corrupted");
   final File indexRoot = PathManager.getIndexRoot();
   if (indexRoot.exists()) {
     final String[] children = indexRoot.list();
     if (children != null && children.length > 0) {
       // create index corruption marker only if index directory exists and is non-empty
       // It is incorrect to consider non-existing indices "corrupted"
       FileUtil.createIfDoesntExist(new File(PathManager.getIndexRoot(), "corruption.marker"));
     }
   }
 }
    private static void init() {
      final File basePath = basePath();
      basePath.mkdirs();

      final File namesFile = new File(basePath, "names.dat");
      final File attributesFile = new File(basePath, "attrib.dat");
      final File contentsFile = new File(basePath, "content.dat");
      final File recordsFile = new File(basePath, "records.dat");

      if (!namesFile.exists()) {
        invalidateIndex();
      }

      try {
        if (getCorruptionMarkerFile().exists()) {
          invalidateIndex();
          throw new IOException("Corruption marker file found");
        }

        PagedFileStorage.StorageLockContext storageLockContext =
            new PagedFileStorage.StorageLock(false).myDefaultStorageLockContext;
        myNames = new PersistentStringEnumerator(namesFile, storageLockContext);
        myAttributes = new Storage(attributesFile.getCanonicalPath(), REASONABLY_SMALL);
        myContents =
            new RefCountingStorage(
                contentsFile.getCanonicalPath(),
                CapacityAllocationPolicy
                    .FIVE_PERCENT_FOR_GROWTH); // sources usually zipped with 4x ratio
        boolean aligned = PagedFileStorage.BUFFER_SIZE % RECORD_SIZE == 0;
        assert aligned; // for performance
        myRecords =
            new ResizeableMappedFile(
                recordsFile, 20 * 1024, storageLockContext, PagedFileStorage.BUFFER_SIZE, aligned);

        if (myRecords.length() == 0) {
          cleanRecord(0); // Clean header
          cleanRecord(1); // Create root record
          setCurrentVersion();
        }

        if (getVersion() != VERSION) {
          throw new IOException("FS repository version mismatch");
        }

        if (myRecords.getInt(HEADER_CONNECTION_STATUS_OFFSET) != SAFELY_CLOSED_MAGIC) {
          throw new IOException("FS repository wasn't safely shut down");
        }
        markDirty();
        scanFreeRecords();
      } catch (Exception e) { // IOException, IllegalArgumentException
        LOG.info(
            "Filesystem storage is corrupted or does not exist. [Re]Building. Reason: "
                + e.getMessage());
        try {
          closeFiles();

          boolean deleted = FileUtil.delete(getCorruptionMarkerFile());
          deleted &= deleteWithSubordinates(namesFile);
          deleted &= AbstractStorage.deleteFiles(attributesFile.getCanonicalPath());
          deleted &= AbstractStorage.deleteFiles(contentsFile.getCanonicalPath());
          deleted &= deleteWithSubordinates(recordsFile);

          if (!deleted) {
            throw new IOException("Cannot delete filesystem storage files");
          }
        } catch (final IOException e1) {
          final Runnable warnAndShutdown =
              new Runnable() {
                @Override
                public void run() {
                  if (ApplicationManager.getApplication().isUnitTestMode()) {
                    //noinspection CallToPrintStackTrace
                    e1.printStackTrace();
                  } else {
                    final String message =
                        "Files in "
                            + basePath.getPath()
                            + " are locked.\n"
                            + ApplicationNamesInfo.getInstance().getProductName()
                            + " will not be able to start up.";
                    if (!ApplicationManager.getApplication().isHeadlessEnvironment()) {
                      JOptionPane.showMessageDialog(
                          JOptionPane.getRootFrame(),
                          message,
                          "Fatal Error",
                          JOptionPane.ERROR_MESSAGE);
                    } else {
                      //noinspection UseOfSystemOutOrSystemErr
                      System.err.println(message);
                    }
                  }
                  Runtime.getRuntime().halt(1);
                }
              };

          if (EventQueue.isDispatchThread()) {
            warnAndShutdown.run();
          } else {
            //noinspection SSBasedInspection
            SwingUtilities.invokeLater(warnAndShutdown);
          }

          throw new RuntimeException("Can't rebuild filesystem storage ", e1);
        }

        init();
      }
    }
    static {
      File snapshotInfoFile = new File(new File(getJarsDir()), "snapshots_info");

      int currentVersion = -1;
      File versionFile = getVersionFile(snapshotInfoFile);
      if (versionFile.exists()) {
        try {
          DataInputStream versionStream =
              new DataInputStream(new BufferedInputStream(new FileInputStream(versionFile)));
          try {
            currentVersion = DataInputOutputUtil.readINT(versionStream);
          } finally {
            versionStream.close();
          }
        } catch (IOException ignore) {
        }
      }

      if (currentVersion != VERSION) {
        PersistentHashMap.deleteFilesStartingWith(snapshotInfoFile);
        saveVersion(versionFile);
      }

      PersistentHashMap<String, CacheLibraryInfo> info = null;
      for (int i = 0; i < 2; ++i) {
        try {
          info =
              new PersistentHashMap<String, CacheLibraryInfo>(
                  snapshotInfoFile,
                  new EnumeratorStringDescriptor(),
                  new DataExternalizer<CacheLibraryInfo>() {

                    @Override
                    public void save(@NotNull DataOutput out, CacheLibraryInfo value)
                        throws IOException {
                      IOUtil.writeUTF(out, value.mySnapshotPath);
                      out.writeLong(value.myModificationTime);
                      out.writeLong(value.myFileLength);
                    }

                    @Override
                    public CacheLibraryInfo read(@NotNull DataInput in) throws IOException {
                      return new CacheLibraryInfo(IOUtil.readUTF(in), in.readLong(), in.readLong());
                    }
                  });

          if (i == 0) removeStaleJarFilesIfNeeded(snapshotInfoFile, info);
          break;
        } catch (IOException ex) {
          PersistentHashMap.deleteFilesStartingWith(snapshotInfoFile);
          saveVersion(versionFile);
        }
      }

      assert info != null;
      ourCachedLibraryInfo = info;
      FlushingDaemon.everyFiveSeconds(
          new Runnable() {
            @Override
            public void run() {
              flushCachedLibraryInfos();
            }
          });

      ShutDownTracker.getInstance()
          .registerShutdownTask(
              new Runnable() {
                @Override
                public void run() {
                  flushCachedLibraryInfos();
                }
              });
    }