private void runBuild(@NotNull MessageHandler msgHandler, @NotNull CanceledStatus cs) throws Throwable{
    final File dataStorageRoot = Utils.getDataStorageRoot(myProjectPath);
    final boolean storageFilesAbsent = !dataStorageRoot.exists() || !new File(dataStorageRoot, FS_STATE_FILE).exists();
    if (storageFilesAbsent) {
      // invoked the very first time for this project
      myBuildRunner.setForceCleanCaches(true);
      LOG.debug("Storage files are absent");
    }
    final ProjectDescriptor preloadedProject = myPreloadedData != null? myPreloadedData.getProjectDescriptor() : null;
    final DataInputStream fsStateStream =
      storageFilesAbsent || preloadedProject != null || myLoadUnloadedModules || myInitialFSDelta == null /*this will force FS rescan*/? null : createFSDataStream(dataStorageRoot, myInitialFSDelta.getOrdinal());

    if (fsStateStream != null || myPreloadedData != null) {
      // optimization: checking whether we can skip the build
      final boolean hasWorkFlag = fsStateStream != null? fsStateStream.readBoolean() : myPreloadedData.hasWorkToDo();
      LOG.debug("hasWorkFlag = " + hasWorkFlag);
      final boolean hasWorkToDoWithModules = hasWorkFlag || myInitialFSDelta == null;
      if ((myBuildType == BuildType.BUILD || myBuildType == BuildType.UP_TO_DATE_CHECK) &&
          !hasWorkToDoWithModules &&
          scopeContainsModulesOnlyForIncrementalMake(myScopes) &&
          !containsChanges(myInitialFSDelta)) {

        final DataInputStream storedFsData;
        if (myPreloadedData != null) {
          storedFsData = createFSDataStream(dataStorageRoot, myInitialFSDelta.getOrdinal());
          if (storedFsData != null) {
            storedFsData.readBoolean(); // skip hasWorkToDo flag
          }
        }
        else {
          storedFsData = fsStateStream;
        }

        if (storedFsData != null) {
          updateFsStateOnDisk(dataStorageRoot, storedFsData, myInitialFSDelta.getOrdinal());
          LOG.info("No changes found since last build. Exiting.");
          if (preloadedProject != null) {
            preloadedProject.release();
          }
          return;
        }
      }
    }
    LOG.debug("Fast up-to-date check didn't work, continue to regular build");

    final BuildFSState fsState = preloadedProject != null? preloadedProject.fsState : new BuildFSState(false);
    try {
      final ProjectDescriptor pd;
      if (preloadedProject != null) {
        pd = preloadedProject;
        final List<BuildMessage> preloadMessages = myPreloadedData.getLoadMessages();
        if (!preloadMessages.isEmpty()) {
          // replay preload-time messages, so that they are delivered to the IDE
          for (BuildMessage message : preloadMessages) {
            msgHandler.processMessage(message);
          }
        }
        if (myInitialFSDelta == null || myPreloadedData.getFsEventOrdinal() + 1L != myInitialFSDelta.getOrdinal()) {
          // FS rescan was forced
          fsState.clearAll();
        }
        else {
          // apply events to already loaded state
          try {
            applyFSEvent(pd, myInitialFSDelta, false);
          }
          catch (Throwable e) {
            LOG.error(e);
            fsState.clearAll();
          }
        }
      }
      else {
        // standard case
        pd = myBuildRunner.load(msgHandler, dataStorageRoot, fsState);
        TimingLog.LOG.debug("Project descriptor loaded");
        if (fsStateStream != null) {
          try {
            fsState.load(fsStateStream, pd.getModel(), pd.getBuildRootIndex());
            applyFSEvent(pd, myInitialFSDelta, false);
            TimingLog.LOG.debug("FS Delta loaded");
          }
          catch (Throwable e) {
            LOG.error(e);
            fsState.clearAll();
          }
        }
      }
      myProjectDescriptor = pd;
      if (myCacheLoadManager != null) myCacheLoadManager.updateBuildStatistic(myProjectDescriptor);

      myLastEventOrdinal.set(myInitialFSDelta != null? myInitialFSDelta.getOrdinal() : 0L);

      // free memory
      myInitialFSDelta = null;
      // ensure events from controller are processed after FSState initialization
      myEventsProcessor.startProcessing();

      myBuildRunner.runBuild(pd, cs, msgHandler, myBuildType, myScopes, false);
      TimingLog.LOG.debug("Build finished");
    }
    finally {
      saveData(fsState, dataStorageRoot);
    }
  }
private void runBuild(@NotNull MessageHandler msgHandler, @NotNull CanceledStatus cs)