/**
         * Execute Run operations using current graph
         */
        public bool Perform(
            BuildTarget target,
            bool isBuild,
            bool logIssues,
            bool forceVisitAll,
            Action <Model.NodeData, string, float> updateHandler)
        {
            if (m_targetGraph == null)
            {
                LogUtility.Logger.LogError(LogUtility.kTag, "Attempted to execute invalid graph (null)");
                return(false);
            }

            if (!AssetGraphPostprocessor.Postprocessor.PushController(this))
            {
                LogUtility.Logger.LogFormat(LogType.Log, "[Perform - Skip] Re-entering graph on stack: {0}", m_targetGraph.GetGraphName());
                return(false);
            }

            LogUtility.Logger.Log(LogType.Log, (isBuild) ? "---Build BEGIN---" : "---Setup BEGIN---");
            m_isBuilding = true;

            if (isBuild)
            {
                AssetBundleBuildReport.ClearReports();
            }

            foreach (var e in m_nodeExceptions)
            {
                var errorNode = m_targetGraph.Nodes.Find(n => n.Id == e.NodeId);
                // errorNode may not be found if user delete it on graph
                if (errorNode != null)
                {
                    LogUtility.Logger.LogFormat(LogType.Log, "[Perform] {0} is marked to revisit due to last error", errorNode.Name);
                    errorNode.NeedsRevisit = true;
                }
            }

            m_nodeExceptions.Clear();
            m_lastTarget = target;

            try {
                PerformGraph oldGraph = m_performGraph[gIndex];
                gIndex = (gIndex + 1) % 2;
                PerformGraph newGraph = m_performGraph[gIndex];
                newGraph.BuildGraphFromSaveData(m_targetGraph, target, oldGraph);

                PerformGraph.Perform performFunc =
                    (Model.NodeData data,
                     IEnumerable <PerformGraph.AssetGroups> incoming,
                     IEnumerable <Model.ConnectionData> connectionsToOutput,
                     PerformGraph.Output outputFunc) =>
                {
                    DoNodeOperation(target, data, incoming, connectionsToOutput, outputFunc, isBuild, updateHandler);
                };

                newGraph.VisitAll(performFunc, forceVisitAll);

                if (isBuild && m_nodeExceptions.Count == 0)
                {
                    Postprocess();
                }
            }
            catch (NodeException e) {
                m_nodeExceptions.Add(e);
            }
            // Minimize impact of errors happened during node operation
            catch (Exception e) {
                LogUtility.Logger.LogException(e);
            }

            m_isBuilding = false;
            LogUtility.Logger.Log(LogType.Log, (isBuild) ? "---Build END---" : "---Setup END---");

            if (logIssues)
            {
                LogIssues();
            }

            AssetGraphPostprocessor.Postprocessor.PopController();

            return(true);
        }