Пример #1
0
        /// <summary>
        /// Handler for DivideProblemMessage.
        /// </summary>
        /// <param name="message">A DivideProblemMessage.</param>
        /// <exception cref="System.InvalidOperationException">
        ///     Thrown when:
        ///     - message is designated for TaskManger with different ID,
        ///     - problem type can't be divided with this TaskManager,
        ///     - dividing the problem cannot be started bacause no threads are available in thread pool.
        /// </exception>
        private void DivideProblemMessageHandler(DivideProblemMessage message)
        {
            if (Id != message.TaskManagerId)
            {
                // shouldn't ever get here - received message for other TaskManager
                throw new InvalidOperationException(
                          string.Format("TaskManager with ID={0} received message for TaskManager with ID={1}.", Id,
                                        message.TaskManagerId));
            }
            Type taskSolverType;

            if (!TaskSolvers.TryGetValue(message.ProblemType, out taskSolverType))
            {
                // shouldn't ever get here - received unsolvable problem
                throw new InvalidOperationException(
                          string.Format("\"{0}\" problem type can't be divided with this TaskManager.", message.ProblemType));
            }

            var actionDescription = string.Format("Dividing problem \"{0}\"(problem instance id={1})",
                                                  message.ProblemType, message.ProblemInstanceId);
            // should be started properly cause server sends at most as many tasks to do as count of component's threads in idle state
            var started = StartActionInNewThread(() =>
            {
                var taskSolver = (TaskSolver)Activator.CreateInstance(taskSolverType, message.ProblemData);
                taskSolver.ThrowIfError();

                var partialProblemsData = taskSolver.DivideProblem((int)message.ComputationalNodes);
                taskSolver.ThrowIfError();

                var partialProblems = new List <PartialProblemsMessage.PartialProblem>(partialProblemsData.GetLength(0));
                for (var i = 0; i < partialProblemsData.GetLength(0); i++)
                {
                    partialProblems.Add(new PartialProblemsMessage.PartialProblem
                    {
                        PartialProblemId = (ulong)i,
                        Data             = partialProblemsData[i],
                        TaskManagerId    = Id
                    });
                }

                var partialProblemsMessage = new PartialProblemsMessage
                {
                    ProblemType       = message.ProblemType,
                    ProblemInstanceId = message.ProblemInstanceId,
                    CommonData        = message.ProblemData,
                    PartialProblems   = partialProblems
                };

                EnqueueMessageToSend(partialProblemsMessage);
            }, actionDescription, message.ProblemType, message.ProblemInstanceId, null);

            if (!started)
            {
                throw new InvalidOperationException(
                          "Couldn't divide problem because couldn't start new thread.");
            }
        }
Пример #2
0
        /// <summary>
        /// Handler for PartialProblemsMessage.
        /// </summary>
        /// <param name="message">A PartialProblemsMessage.</param>
        /// <exception cref="System.InvalidOperationException">
        ///     Thrown when:
        ///     - problem type can't be solved with this ComputationalNode,
        ///     - received more partial problems than can be currently started.
        /// </exception>
        private void PartialProblemsMessageHandler(PartialProblemsMessage message)
        {
            Type taskSolverType;

            if (!TaskSolvers.TryGetValue(message.ProblemType, out taskSolverType))
            {
                // shouldn't ever get here - received unsolvable problem
                throw new InvalidOperationException(
                          string.Format("\"{0}\" problem type can't be solved with this ComputationalNode.",
                                        message.ProblemType));
            }
            var timeout = message.SolvingTimeout.HasValue
                ? TimeSpan.FromMilliseconds(message.SolvingTimeout.Value)
                : TimeSpan.MaxValue;

            foreach (var partialProblem in message.PartialProblems)
            {
                /* each partial problem should be started properly cause server sends at most
                 * as many partial problems as count of component's tasks in idle state */
                var actionDescription =
                    string.Format("Solving partial problem \"{0}\"(problem instance id={1})(partial problem id={2})",
                                  message.ProblemType, message.ProblemInstanceId, partialProblem.PartialProblemId);
                var started = StartActionInNewThread(() =>
                {
                    // not sure if TaskSolver can change CommonData during computations so recreate it for each partial problem
                    var taskSolver = (TaskSolver)Activator.CreateInstance(taskSolverType, message.CommonData);
                    taskSolver.ThrowIfError();

                    // measure time using DateTime cause StopWatch is not guaranteed to be thread safe
                    var start = DateTime.UtcNow;
                    var partialProblemSolutionData = taskSolver.Solve(partialProblem.Data, timeout);
                    var stop = DateTime.UtcNow;

                    taskSolver.ThrowIfError();

                    var solutions = new List <SolutionsMessage.Solution>
                    {
                        new SolutionsMessage.Solution
                        {
                            PartialProblemId = partialProblem.PartialProblemId,
                            TimeoutOccured   = taskSolver.State == TaskSolver.TaskSolverState.Timeout,
                            Type             = SolutionsMessage.SolutionType.Partial,
                            ComputationsTime = (ulong)(stop - start).TotalMilliseconds,
                            Data             = partialProblemSolutionData
                        }
                    };
                    var solutionsMessage = new SolutionsMessage
                    {
                        ProblemType       = message.ProblemType,
                        ProblemInstanceId = message.ProblemInstanceId,
                        CommonData        = message.CommonData,
                        Solutions         = solutions
                    };

                    EnqueueMessageToSend(solutionsMessage);
                }, actionDescription, message.ProblemType, message.ProblemInstanceId, partialProblem.PartialProblemId);
                if (!started)
                {
                    throw new InvalidOperationException("Received more partial problems than can be currently started.");
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Handler for SolutionsMessage.
        /// </summary>
        /// <param name="message">A SolutionsMessage.</param>
        /// <exception cref="System.InvalidOperationException">
        ///     Thrown when:
        ///     - problem type can't be merged with this TaskManager,
        ///     - merging the problem cannot be started bacause no threads are available in thread pool.
        /// </exception>
        private void SolutionsMessageHandler(SolutionsMessage message)
        {
            Type taskSolverType;

            if (!TaskSolvers.TryGetValue(message.ProblemType, out taskSolverType))
            {
                // shouldn't ever get here - received unsolvable problem
                throw new InvalidOperationException(
                          string.Format("\"{0}\" problem type can't be merged with this TaskManager.", message.ProblemType));
            }

            var actionDescription = string.Format("Merging partial problems \"{0}\"(problem instance id={1})",
                                                  message.ProblemType, message.ProblemInstanceId);
            // should be started properly cause server sends at most as many tasks to do as count of component's threads in idle state
            var started = StartActionInNewThread(() =>
            {
                ulong totalComputationsTime = 0;
                var timeoutOccured          = false;
                var solutionsData           = new byte[message.Solutions.Count][];
                for (var i = 0; i < message.Solutions.Count; i++)
                {
                    var solution = message.Solutions[i];

                    if (solution.Type != SolutionsMessage.SolutionType.Partial)
                    {
                        throw new InvalidOperationException(
                            string.Format("Received non-partial solution({0})(partial problem id={1}).",
                                          solution.Type, solution.PartialProblemId));
                    }
                    totalComputationsTime += solution.ComputationsTime;
                    timeoutOccured        |= solution.TimeoutOccured;
                    solutionsData[i]       = solution.Data;
                }

                var taskSolver = (TaskSolver)Activator.CreateInstance(taskSolverType, message.CommonData);
                taskSolver.ThrowIfError();

                // measure time using DateTime cause StopWatch is not guaranteed to be thread safe
                var start             = DateTime.UtcNow;
                var finalSolutionData = taskSolver.MergeSolution(solutionsData);
                var stop = DateTime.UtcNow;

                taskSolver.ThrowIfError();
                totalComputationsTime += (ulong)((stop - start).TotalMilliseconds);

                var finalSolution = new SolutionsMessage.Solution
                {
                    Type             = SolutionsMessage.SolutionType.Final,
                    ComputationsTime = totalComputationsTime,
                    TimeoutOccured   = timeoutOccured,
                    Data             = finalSolutionData
                };
                var finalSolutionMessage = new SolutionsMessage
                {
                    ProblemType       = message.ProblemType,
                    ProblemInstanceId = message.ProblemInstanceId,
                    CommonData        = message.CommonData,
                    Solutions         = new List <SolutionsMessage.Solution> {
                        finalSolution
                    }
                };

                EnqueueMessageToSend(finalSolutionMessage);
            }, actionDescription, message.ProblemType, message.ProblemInstanceId, null);

            if (!started)
            {
                throw new InvalidOperationException(
                          "Couldn't merge partial solutions because couldn't start new thread.");
            }
        }