Exemplo n.º 1
0
        public void PartialProblemsMessageXmlIsProperlySerializedAndDeserialized()
        {
            var pp = new PartialProblemsMessage.PartialProblem
            {
                Data             = new byte[] { 1, 2, 3 },
                TaskManagerId    = 5,
                PartialProblemId = 10
            };

            var message = new PartialProblemsMessage
            {
                CommonData      = new byte[] { 1, 2, 3, 4, 5 },
                PartialProblems = new List <PartialProblemsMessage.PartialProblem> {
                    pp
                },
                ProblemInstanceId = 15,
                ProblemType       = "Dvrp",
                SolvingTimeout    = 20
            };

            var serializedMessage   = _serializer.Serialize(message);
            var deserializedMessage = _serializer.Deserialize(serializedMessage);

            Assert.IsInstanceOfType(deserializedMessage, typeof(PartialProblemsMessage));
        }
Exemplo n.º 2
0
        /// <summary>
        /// Create partial problems message that can be send to a computational node.
        /// </summary>
        /// <returns>Partial problems message.</returns>
        public override Message CreateMessage()
        {
            var msgPartialProblems = new List <PartialProblemsMessage.PartialProblem>(PartialProblems.Count);

            foreach (var pp in PartialProblems)
            {
                var msgPp = new PartialProblemsMessage.PartialProblem
                {
                    Data             = pp.PrivateData,
                    PartialProblemId = pp.Id,
                    TaskManagerId    = pp.Problem.DividingNodeId.Value
                };
                msgPartialProblems.Add(msgPp);
            }

            var problem = PartialProblems[0].Problem;

            var message = new PartialProblemsMessage
            {
                CommonData        = problem.CommonData,
                PartialProblems   = msgPartialProblems,
                ProblemInstanceId = problem.Id,
                ProblemType       = problem.Type,
                SolvingTimeout    = problem.SolvingTimeout
            };

            return(message);
        }
Exemplo n.º 3
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.");
            }
        }
Exemplo n.º 4
0
        private void ProcessDivideProblem()
        {
            DivideProblemMessage processedMessage = null;

            lock (divideProblemMessageQueue)
            {
                if (divideProblemMessageQueue.Count > 0)
                {
                    processedMessage = divideProblemMessageQueue.Dequeue();
                }
            }
            if (processedMessage == null)
            {
                return;
            }

            _logger.Debug("Processing divideMessage. " + processedMessage.Id);

            TaskSolverDVRP taskSolver = CreateTaskSolver(processedMessage.ProblemType, processedMessage.Data);

            var dividedProblem = taskSolver.DivideProblem((int)processedMessage.ComputationalNodes);

            _logger.Debug("Finished dividing problem");


            var solutionsMessage = new PartialProblemsMessage()
            {
                CommonData              = processedMessage.Data,
                Id                      = processedMessage.Id,
                ProblemType             = processedMessage.ProblemType,
                SolvingTimeout          = (ulong)Timeout.TotalMilliseconds,
                SolvingTimeoutSpecified = true,
                PartialProblems         = new SolvePartialProblemsPartialProblem[(int)processedMessage.ComputationalNodes]
            };

            solutionsMessage.PartialProblems = new SolvePartialProblemsPartialProblem[dividedProblem.Length];

            for (int i = 0; i < dividedProblem.Length; i++)
            {
                solutionsMessage.PartialProblems[i] = new SolvePartialProblemsPartialProblem()
                {
                    Data   = dividedProblem[i],
                    TaskId = (ulong)i
                };
            }

            var socket = communicationModule.SetupClient();

            communicationModule.Connect(socket);
            var message = SerializeMessage(solutionsMessage);

            communicationModule.SendData(message, socket);
            communicationModule.CloseSocket(socket);
        }
Exemplo n.º 5
0
        private ComputationMessage GetTaskForComputationalNode(NodeEntry node)
        {
            PartialProblemsMessage partialProblem = null;

            lock (partialProblems)
            {
                partialProblem = partialProblems.FirstOrDefault(x => node.SolvingProblems.Contains(x.ProblemType));
                if (partialProblem != null)
                {
                    partialProblems.Remove(partialProblem);
                }
            }
            return(partialProblem);
        }
Exemplo n.º 6
0
        private List <PartialProblemsMessage> DividePartialProblems(PartialProblemsMessage partialProblemsMessage)
        {
            var partialProblemsList = new List <PartialProblemsMessage>();

            for (int i = 0; i < partialProblemsMessage.PartialProblems.Length; i++)
            {
                var partialProblem = new PartialProblemsMessage()
                {
                    Id              = partialProblemsMessage.Id,
                    CommonData      = partialProblemsMessage.CommonData,
                    ProblemType     = partialProblemsMessage.ProblemType,
                    PartialProblems =
                        new SolvePartialProblemsPartialProblem[1] {
                        partialProblemsMessage.PartialProblems[i]
                    },
                    SolvingTimeout          = partialProblemsMessage.SolvingTimeout,
                    SolvingTimeoutSpecified = partialProblemsMessage.SolvingTimeoutSpecified
                };
                partialProblemsList.Add(partialProblem);
            }
            return(partialProblemsList);
        }
Exemplo n.º 7
0
        public void PartialProblemsMessageSerialization()
        {
            string testData   = System.IO.File.ReadAllText(@"XMLTestData\PartialProblemsMessage.xml");
            var    serializer = new ComputationSerializer <PartialProblemsMessage>();

            SolvePartialProblemsPartialProblem pp = new SolvePartialProblemsPartialProblem()
            {
                TaskId = 20,
                Data   = new byte[] { 0, 0, 10 }
            };

            var partialProblemsMessage = new PartialProblemsMessage()
            {
                ProblemType             = "TSP",
                Id                      = 1,
                CommonData              = new byte[] { 0, 0, 25 },
                SolvingTimeout          = 50,
                SolvingTimeoutSpecified = true,
                PartialProblems         = new SolvePartialProblemsPartialProblem[] { pp }
            };
            var result = serializer.Serialize(partialProblemsMessage);

            Assert.AreEqual(result, testData);
        }
        private void SolvePartialProblemsMessage(PartialProblemsMessage partialProblemsMessage)
        {
            Trace.WriteLine("\n\nStarting solving problem id: " + partialProblemsMessage.Id);

            //All PartialProblems which were sent in single PartialProblemsMessage
            Queue <SolvePartialProblemsPartialProblem> q = new Queue <SolvePartialProblemsPartialProblem>(partialProblemsMessage.PartialProblems);

            Trace.WriteLine("\n\nSOLVING " + q.Count + " subproblems of PartialProblem\n\n");

            TaskSolverDVRP taskSolverDvrp = new TaskSolverDVRP(partialProblemsMessage.CommonData);

            SolutionsMessage solutionsMessage = new SolutionsMessage()
            {
                CommonData  = partialProblemsMessage.CommonData,
                Id          = partialProblemsMessage.Id,
                ProblemType = partialProblemsMessage.ProblemType,
                Solutions   = new Solution[q.Count],
            };

            lock ((this.solutionsMessagesList))
            {
                this.solutionsMessagesList.Add(solutionsMessage);
            }

            int idleThreadIndex;

            while (q.Count > 0)
            {
                lock (this.statusOfComputingThreads)
                {
                    //Get index number of the idle thread, which can compute
                    idleThreadIndex = this.GetIdleThreadIndex();
                }

                //If there is no idle thread, wait and try again
                if (idleThreadIndex == -1)
                {
                    Thread.Sleep(4000);
                }

                else
                {
                    SolvePartialProblemsPartialProblem problem = q.Dequeue();

                    this.statusOfComputingThreads[idleThreadIndex].ProblemInstanceId =
                        partialProblemsMessage.Id;

                    this.statusOfComputingThreads[idleThreadIndex].ProblemType =
                        partialProblemsMessage.ProblemType;

                    this.statusOfComputingThreads[idleThreadIndex].TaskId =
                        problem.TaskId;

                    this.computingThreads[idleThreadIndex] = new Thread(() =>
                                                                        this.Solve(problem, idleThreadIndex, taskSolverDvrp,
                                                                                   (int)partialProblemsMessage.SolvingTimeout, partialProblemsMessage.Id));

                    this.computingThreads[idleThreadIndex].Start();
                }
            }
        }
Exemplo n.º 9
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.");
                }
            }
        }
Exemplo n.º 10
0
        /// <summary>
        /// Handle partial problems message.
        /// </summary>
        /// <param name="msg">Partial problems message.</param>
        /// <param name="metadata">Information about data and the TCP connection it came from.</param>
        /// <returns>List of response messages.</returns>
        private List <Message> HandleMessage(PartialProblemsMessage msg, TcpDataProviderMetadata metadata)
        {
            var responses = new List <Message>();

            var senderId = _workManager.GetProcessingNodeId(msg.ProblemInstanceId);

            if (!senderId.HasValue)
            {
                Logger.Error("Couldn't identify the sender.");
                var errorMsg = new ErrorMessage
                {
                    ErrorType = ErrorType.UnknownSender,
                    ErrorText = "The server couldn't identify the sender component."
                };

                responses.Add(errorMsg);
            }
            else if (!_componentOverseer.IsRegistered(senderId.Value))
            {
                Logger.Warn("The component is not registered (id: " + senderId + ").");
                var errorMsg = new ErrorMessage
                {
                    ErrorType = ErrorType.UnknownSender,
                    ErrorText = "Component unregistered."
                };

                responses.Add(errorMsg);
            }
            else
            {
                _componentOverseer.UpdateTimestamp(senderId.Value);

                var problem = _workManager.GetProblem(msg.ProblemInstanceId);

                if (problem.CommonData != null)
                {
                    Logger.Warn("Common data shouldn't be set.");
                }

                problem.CommonData = msg.CommonData;
                foreach (var pp in msg.PartialProblems)
                {
                    _workManager.AddPartialProblem(msg.ProblemInstanceId, pp.PartialProblemId, pp.Data);
                }


                var  component = _componentOverseer.GetComponent(senderId.Value) as SolverNodeInfo;
                Work work;
                _workManager.TryAssignWork(component, out work);

                if (work != null)
                {
                    responses.Add(work.CreateMessage());
                }
            }

            if (responses.Count == 0)
            {
                responses.Add(CreateNoOperationMessage());
            }

            return(responses);
        }