예제 #1
0
        /// <summary>
        /// Schedules the service app process.
        /// </summary>
        /// <param name="process">The process to schedule.</param>
        /// <returns>
        /// Any errors that occured when trying to create the schedule.
        /// </returns>
        /// <exception cref="System.InvalidOperationException">Cannot schedule an uninitialized ServiceApp.</exception>
        public string ScheduleServiceApp(ServiceAppProcess process)
        {
            if (!process.IsProcessRunning)
            {
                throw new InvalidOperationException("Cannot schedule a service app that has not been started.");
            }

            string errorMessage = string.Empty;
            string appName      = process.ServiceApp.Name;

            if (process.ServiceApp.StartupTypeEnum == StartupType.Automatic)
            {
                if (string.IsNullOrEmpty(process.ServiceApp.Schedule))
                {
                    process.AddMessage(ServiceAppMessages.InvalidSchedule, ServiceAppState.Error);
                    errorMessage = string.Format("Schedule for service app '{0}' was not defined", appName);
                }
                else if (!HasJob(appName))
                {
                    AddJob(appName, process.ServiceApp.Schedule, () => { process.ExecuteServiceApp(); });
                }
            }
            else if (process.ServiceApp.StartupTypeEnum != StartupType.Manual)
            {
                errorMessage = string.Format("Cannot start '{0}'. The service app is disabled. Please enable the service app first before scheduling.", appName);
            }

            return(errorMessage);
        }
예제 #2
0
        /// <summary>
        /// Removes the specified service app from the container.
        /// </summary>
        /// <param name="appName">Name of the application.</param>
        /// <param name="dao">The DAO.</param>
        /// <param name="appListDao">The application list DAO.</param>
        /// <exception cref="System.IndexOutOfRangeException">The app name could not be found.</exception>
        /// <exception cref="System.InvalidOperationException">The ServiceApp was not stopped first.</exception>
        public void RemoveServiceApp(string appName, IServiceAppDao dao, IAppListDao appListDao)
        {
            ServiceAppProcess process = ServiceAppProcesses[appName];

            if (process != null)
            {
                if (process.IsProcessRunning)
                {
                    throw new InvalidOperationException(string.Format("ServiceApp '{0}' must be stopped before it can be updated or removed.", appName));
                }

                ServiceAppProcesses.Remove(process);

                // This will prevent leaks
                process.Started     -= ServiceAppProcess_Started;
                process.Error       -= ServiceAppProcess_Error;
                process.Executed    -= ServiceAppProcess_Executed;
                process.Performance -= ServiceAppProcess_Performance;
                process.Stopped     -= ServiceAppProcess_Stopped;
            }

            if (appListDao != null)
            {
                appListDao.DeleteServiceApp(appName);
            }

            if (dao != null)
            {
                dao.DeleteServiceApp(appName);
            }
        }
예제 #3
0
        public void Start_ServiceAppProcessCanStartSucessfully()
        {
            ILog log = Substitute.For <ILog>();
            bool monitorMethodCalled = false;

            IProcessWrapperFactory procFactory = Substitute.For <IProcessWrapperFactory>();

            procFactory.CreateProcess().Returns(new FakeStandardProcess());

            var serviceApp = new ServiceApp {
                Name = "Test", AppVersion = new Version()
            };
            ServiceAppProcess appProcToTest = new ServiceAppProcess(serviceApp, log, procFactory);

            appProcToTest.MonitorProcessCallback = () => { monitorMethodCalled = true; };

            Task t       = appProcToTest.Start();
            bool success = t.Wait(500);

            if (!success)
            {
                Assert.Fail("Start() took too long to finish");
            }

            log.DidNotReceive().Error(Arg.Any <object>(), Arg.Any <Exception>());
            log.DidNotReceive().Warn(Arg.Any <object>(), Arg.Any <Exception>());
            Assert.IsTrue(monitorMethodCalled, "MonitorProcessCallback() not called.");
        }
예제 #4
0
        /// <summary>
        /// Loads the service app which should be added to the pool of service apps.
        /// </summary>
        /// <param name="appName">Name of the application.</param>
        /// <param name="dao">The DAO.</param>
        /// <returns>A string containing an error message if a recoverable error occured.</returns>
        /// <exception cref="System.IndexOutOfRangeException">The ServiceApp could not be found in the container.</exception>
        /// <exception cref="System.InvalidOperationException">The ServiceApp is not in a stopped state.</exception>
        public string InitializeServiceApp(string appName, IServiceAppDao dao)
        {
            ServiceAppProcess process = this.ServiceAppProcesses[appName];

            if (process == null)
            {
                var e = new IndexOutOfRangeException(string.Format("ServiceApp '{0}' could not be found to initialize.", appName));
                this._log.Error("Error in InitializeServiceApp", e);
                throw e;
            }
            else if (process.IsProcessRunning)
            {
                var e = new InvalidOperationException(string.Format("ServiceApp '{0}' must be stopped before it can be reinitialized.", appName));
                this._log.Error("Error in InitializeServiceApp", e);
                throw e;
            }

            if (process.ServiceApp.StartupTypeEnum != StartupType.Disabled)
            {
                process.Start();
                return(string.Empty);
            }
            else
            {
                return(string.Format("ServiceApp '{0}' is disabled", appName));
            }
        }
예제 #5
0
        public void ProcessError_LoggingWorksWithUnrecognizedExceptionObject()
        {
            ILog log = Substitute.For <ILog>();
            IProcessWrapperFactory procFactory = Substitute.For <IProcessWrapperFactory>();

            procFactory.CreateProcess().Returns(new FakeStandardProcess());
            var serviceApp = new ServiceApp {
                Name = "Test", AppVersion = new Version()
            };
            ServiceAppProcess appProcToTest = new ServiceAppProcess(serviceApp, log, procFactory);
            Exception         testException = new InvalidOperationException("test");

            string exceptionMessage = string.Format(@"{{ error: {{
                    details: {{
                        type: ""{0}"",
                        message: ""{1}"",
                        source: ""{2}"",
                        stackTrace: ""{3}""
                    }},
                    exception: ""xxxxx""
                }} }}",
                                                    testException.GetType().ToString(),
                                                    testException.Message,
                                                    testException.Source,
                                                    testException.StackTrace);

            bool shouldExit = appProcToTest.ProcessMessage(exceptionMessage);

            log.Received().Warn(Arg.Any <string>());
            Assert.IsFalse(shouldExit, "Process message was not meant to return true");
        }
예제 #6
0
        public void Remove_CannotRemoveDomainFromEmptyCollection()
        {
            ServiceAppProcessCollection collection = new ServiceAppProcessCollection(new ServiceAppProcessComparer());
            ServiceAppProcess           saProc     = _serviceAppProcessFactory.CreateServiceAppProcess(null, null);

            bool success = collection.Remove(saProc);

            Assert.IsFalse(success);
        }
예제 #7
0
        public void Add_CanInsertUniqueDomainToCollection()
        {
            ServiceAppProcessCollection collection = new ServiceAppProcessCollection(new ServiceAppProcessComparer());
            ServiceAppProcess           saProc     = _serviceAppProcessFactory.CreateServiceAppProcess(null, null);

            collection.Add(saProc);

            Assert.AreEqual(1, collection.Count);
        }
예제 #8
0
        public void GetIndex_CanReturnServiceAppProcessFromCollectionUsingString()
        {
            ServiceAppProcessCollection collection = new ServiceAppProcessCollection(new ServiceAppProcessComparer());
            ServiceAppProcess           saProc     = _serviceAppProcessFactory.CreateServiceAppProcess(null, null);

            collection.Add(saProc);

            Assert.AreEqual(saProc, collection["__Test"]);
        }
예제 #9
0
        public void Remove_CanRemoveInstalledDomainFromCollection()
        {
            ServiceAppProcessCollection collection = new ServiceAppProcessCollection(new ServiceAppProcessComparer());
            ServiceAppProcess           saProc     = _serviceAppProcessFactory.CreateServiceAppProcess(null, null);

            collection.Add(saProc);

            bool success = collection.Remove(saProc);

            Assert.IsTrue(success);
        }
예제 #10
0
        public void Constructor_ServiceAppProcessConstructorHasNoSurprises()
        {
            IProcessWrapperFactory procFactory = Substitute.For <IProcessWrapperFactory>();

            procFactory.CreateProcess().Returns(new FakeStandardProcess());

            ServiceAppProcess appProcToTest = new ServiceAppProcess(
                new ServiceApp {
                Name = "Test"
            },
                Substitute.For <ILog>(),
                procFactory);
        }
예제 #11
0
        /// <summary>
        /// Stops the specified service app.
        /// </summary>
        /// <param name="appName">Name of the application.</param>
        /// <param name="dao">The DAO.</param>
        /// <param name="isExiting">Set to <c>true</c> if the service is in the middle of exiting.</param>
        /// <exception cref="System.IndexOutOfRangeException">The app name could not be found.</exception>
        public void StopServiceApp(string appName, IServiceAppDao dao, bool isExiting)
        {
            ServiceAppProcess process = this.ServiceAppProcesses[appName];

            if (process == null)
            {
                var e = new IndexOutOfRangeException(string.Format("appName '{0}' could not be found to stop.", appName));
                this._log.Error("Error in StopServiceApp", e);
            }
            else
            {
                process.Stop(isExiting);
                _schedulingService.RemoveJob(appName);
                dao.RecordServiceAppStop(appName);
            }
        }
예제 #12
0
        public void ProcessMessage_DebugIsLogged()
        {
            ILog log = Substitute.For <ILog>();
            IProcessWrapperFactory procFactory = Substitute.For <IProcessWrapperFactory>();

            procFactory.CreateProcess().Returns(new FakeStandardProcess());
            var serviceApp = new ServiceApp {
                Name = "Test", AppVersion = new Version()
            };
            ServiceAppProcess appProcToTest = new ServiceAppProcess(serviceApp, log, procFactory);

            bool shouldExit = appProcToTest.ProcessMessage("{debug:\"test\"}");

            log.Received().Debug("From Test: test");
            Assert.IsFalse(shouldExit, "Process message was not meant to return true");
        }
예제 #13
0
        /// <summary>
        /// Runs the service application immediately.
        /// </summary>
        /// <param name="appName">Name of the application.</param>
        public void RunServiceApp(string appName)
        {
            string            errorMessage = string.Empty;
            ServiceAppProcess process      = this.ServiceAppProcesses[appName];

            if (process == null)
            {
                throw new IndexOutOfRangeException(string.Format("ServiceApp '{0}' could not be found to execute.", appName));
            }
            else if (!process.IsProcessRunning)
            {
                throw new InvalidOperationException(string.Format("ServiceApp '{0}' must be started before it can be run.", appName));
            }

            // run the service app as if the timer elapsed
            process.ExecuteServiceApp();
        }
예제 #14
0
        /// <summary>
        /// Adds the service app to the container or updates it if it already exists and saves it to the AppList configuration.
        /// </summary>
        /// <param name="app">The application.</param>
        /// <param name="dao">The DAO.</param>
        /// <param name="appListDao">The application list DAO.</param>
        /// <exception cref="System.InvalidOperationException">The service app is added and is still running.</exception>
        public string SyncServiceApp(ServiceApp app, IServiceAppDao dao, IAppListDao appListDao)
        {
            string errorMessage = string.Empty;

            this.RemoveServiceApp(app.Name, dao);

            ServiceAppProcess process = _serviceAppFactory.CreateServiceAppProcess(app, this._log);

            try
            {
                this.ServiceAppProcesses.Add(process);
                process.EntropyValue = dao.SaveServiceApp(app);

                if (appListDao != null)
                {
                    try
                    {
                        appListDao.PersistServiceApp(app);
                    }
                    catch (Exception e)
                    {
                        this._log.Error(string.Format("{0} could not be saved to AppList", app.Name), e);
                        errorMessage = string.Format("ServiceApp '{0}' could not be saved to the configuration.", app.Name);
                    }
                }

                process.Started     += ServiceAppProcess_Started;
                process.Error       += ServiceAppProcess_Error;
                process.Executed    += ServiceAppProcess_Executed;
                process.Performance += ServiceAppProcess_Performance;
                process.Stopped     += ServiceAppProcess_Stopped;
            }
            catch (ArgumentException)
            {
                errorMessage = string.Format("ServiceApp '{0}' is already added.", app.Name);
            }

            return(errorMessage);
        }
예제 #15
0
        public void Add_CannotAddDuplicateDomainToCollection()
        {
            ServiceAppProcessCollection collection = new ServiceAppProcessCollection(new ServiceAppProcessComparer());
            ServiceAppProcess           saProc1    = _serviceAppProcessFactory.CreateServiceAppProcess(null, null);
            ServiceAppProcess           saProc2    = _serviceAppProcessFactory.CreateServiceAppProcess(null, null);

            collection.Add(saProc1);

            try
            {
                collection.Add(saProc2);
                Assert.Fail("Able to add duplicate domain.");
            }
            catch (AssertionException)
            {
                throw;
            }
            catch
            {
                Assert.AreEqual(1, collection.Count);
            }
        }
예제 #16
0
        /// <summary>
        /// Handles the Started event of the ServiceAppProcess object.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        private void ServiceAppProcess_Started(object sender, EventArgs e)
        {
            // TODO: this is so bad! but there's a bug here that disappeared as soon as I added this :(
            try
            {
                string            errorMessage = string.Empty;
                ServiceAppProcess process      = sender as ServiceAppProcess;

                if (process != null)
                {
                    if (process.IsProcessRunning)
                    {
                        using (var dao = _daoFactory.Create <IServiceAppDao>())
                        {
                            dao.RecordServiceAppStart(process.ServiceApp.Name);
                        }

                        if (process.ServiceApp.StartupTypeEnum == StartupType.Automatic)
                        {
                            errorMessage = _schedulingService.ScheduleServiceApp(process);
                        }
                    }
                    else
                    {
                        errorMessage = string.Format("Failed to initialize ServiceApp '{0}'", process.ServiceApp.Name);
                    }
                }

                if (!string.IsNullOrWhiteSpace(errorMessage))
                {
                    this._log.Warn(errorMessage);
                }
            }
            catch (Exception ex)
            {
                _log.Error("ServiceAppProcess_Started event failed", ex);
            }
        }