/// <summary>
 /// Fires the IntegrationStarted event.
 /// </summary>
 /// <param name="request">The integration request.</param>
 /// <param name="projectName"></param>
 protected virtual IntegrationStartedEventArgs.EventResult FireIntegrationStarted(IntegrationRequest request, string projectName)
 {
     IntegrationStartedEventArgs.EventResult result = IntegrationStartedEventArgs.EventResult.Continue;
     if (IntegrationStarted != null)
     {
         IntegrationStartedEventArgs args = new IntegrationStartedEventArgs(request, projectName);
         IntegrationStarted(this, args);
         result = args.Result;
     }
     return(result);
 }
        private bool Integrate()
        {
            bool ran = false;

            while (integrationQueue.IsBlocked)
            {
                Thread.Sleep(200);
            }

            IntegrationRequest ir = integrationQueue.GetNextRequest(project);

            if (ir != null && IsRunning)
            {
                IDisposable queueLock;
                if (!integrationQueue.TryLock(out queueLock))
                {
                    return(false);
                }

                using (queueLock)
                {
                    // Check to see if this integration request should proceed - Extension point
                    IntegrationStartedEventArgs.EventResult eventResult = FireIntegrationStarted(ir);
                    switch (eventResult)
                    {
                    case IntegrationStartedEventArgs.EventResult.Continue:
                        Log.Info(string.Format(System.Globalization.CultureInfo.CurrentCulture, "Project: '{0}' is first in queue: '{1}' and shall start integration.",
                                               project.Name, project.QueueName));

                        IntegrationStatus  status = IntegrationStatus.Unknown;
                        IIntegrationResult result = new IntegrationResult();
                        ran = true;

                        try
                        {
                            ir.PublishOnSourceControlException = (AmountOfSourceControlExceptions == project.MaxSourceControlRetries) ||
                                                                 (project.SourceControlErrorHandling == ThoughtWorks.CruiseControl.Core.Sourcecontrol.Common.SourceControlErrorHandlingPolicy.ReportEveryFailure);
                            result = project.Integrate(ir);
                            if (result != null)
                            {
                                status = result.Status;
                            }
                        }
                        catch
                        {
                            status = IntegrationStatus.Exception;
                            throw;
                        }
                        finally
                        {
                            RemoveCompletedRequestFromQueue();

                            // Tell any extensions that an integration has completed
                            FireIntegrationCompleted(ir, status);

                            // handle post build : check what to do if source control errors occured
                            if (result != null)
                            {
                                if (result.SourceControlError != null)
                                {
                                    AmountOfSourceControlExceptions++;
                                }
                                else
                                {
                                    AmountOfSourceControlExceptions = 0;
                                }
                            }

                            if ((AmountOfSourceControlExceptions > project.MaxSourceControlRetries) &&
                                (project.SourceControlErrorHandling == ThoughtWorks.CruiseControl.Core.Sourcecontrol.Common.SourceControlErrorHandlingPolicy.ReportOnEveryRetryAmount))
                            {
                                AmountOfSourceControlExceptions = 0;
                            }


                            if ((AmountOfSourceControlExceptions > project.MaxSourceControlRetries) &&
                                project.StopProjectOnReachingMaxSourceControlRetries)
                            {
                                Stopped();
                            }
                        }
                        break;

                    case IntegrationStartedEventArgs.EventResult.Delay:
                        // Log that the request has been cancelled and delay until the request is cleared - otherwise
                        // stuck in an endless loop until the extensions allow the request through
                        Log.Info(string.Format(System.Globalization.CultureInfo.CurrentCulture, "An external extension has delayed an integration - project '{0}' on queue '{1}'",
                                               project.Name,
                                               project.QueueName));
                        while (FireIntegrationStarted(ir) == IntegrationStartedEventArgs.EventResult.Delay)
                        {
                            Thread.Sleep(1000);
                        }
                        break;

                    case IntegrationStartedEventArgs.EventResult.Cancel:
                        Log.Info(string.Format(System.Globalization.CultureInfo.CurrentCulture, "An external extension has cancelled an integration - project '{0}' on queue '{1}'",
                                               project.Name,
                                               project.QueueName));
                        RemoveCompletedRequestFromQueue();
                        FireIntegrationCompleted(ir, IntegrationStatus.Cancelled);
                        break;
                    }
                }
            }
            else
            {
                PollTriggers();
                // If a build is queued for this project we need to hang around until either:
                // - the build gets started by reaching it's turn on the queue
                // - the build gets cancelled from the queue
                // - the thread gets killed
                // However, if the queue is blocked, do not hang around - we need to exit, so that we can come back to the queue
                // after the lock has been released (otherwise we could get stuck here forever
                while (IsRunning && integrationQueue.HasItemPendingOnQueue(project) && !integrationQueue.IsBlocked)
                {
                    Thread.Sleep(200);
                }
            }

            return(ran);
        }