/// <summary> /// Constructor for ServiceLock processor. /// </summary> /// <param name="numberThreads">The number of threads allocated to the processor.</param> /// <param name="terminationEvent">Stop signal</param> public ServiceLockProcessor(int numberThreads, ManualResetEvent terminationEvent) { _terminationEvent = terminationEvent; _threadStop = new ManualResetEvent(false); _threadPool = new ServiceLockThreadPool(numberThreads); _threadPool.ThreadPoolName = "ServiceLock Pool"; ServiceLockFactoryExtensionPoint ep = new ServiceLockFactoryExtensionPoint(); object[] factories = ep.CreateExtensions(); if (factories == null || factories.Length == 0) { // No extension for the ServiceLock processor. Platform.Log(LogLevel.Warn, "No ServiceLockFactory Extension found."); } else { foreach (object obj in factories) { IServiceLockProcessorFactory factory = obj as IServiceLockProcessorFactory; if (factory != null) { ServiceLockTypeEnum type = factory.GetServiceLockType(); _extensions.Add(type, factory); } else { Platform.Log(LogLevel.Error, "Unexpected incorrect type loaded for extension: {0}", obj.GetType()); } } } }
/// <summary> /// The processing thread. /// </summary> /// <remarks> /// This method queries the database for ServiceLock entries to work on, and then uses /// a thread pool to process the entries. /// </remarks> public void Run() { // Start the thread pool if (!_threadPool.Active) { _threadPool.Start(); } // Reset any queue items related to this service that are have the Lock bit set. try { ResetLocked(); } catch (Exception e) { Platform.Log(LogLevel.Fatal, e, "Unable to reset ServiceLock items on startup. There may be ServiceLock items orphaned in the queue."); } Platform.Log(LogLevel.Info, "ServiceLock Processor is running"); while (true) { try { if (_threadPool.CanQueueItem) { Model.ServiceLock queueListItem; using (IUpdateContext updateContext = _store.OpenUpdateContext(UpdateContextSyncMode.Flush)) { IQueryServiceLock select = updateContext.GetBroker <IQueryServiceLock>(); ServiceLockQueryParameters parms = new ServiceLockQueryParameters(); parms.ProcessorId = ServerPlatform.ProcessorId; queueListItem = select.FindOne(parms); updateContext.Commit(); } if (queueListItem == null) { WaitHandle.WaitAny(new WaitHandle[] { _terminationEvent, _threadStop }, TimeSpan.FromSeconds(30), false); _threadStop.Reset(); } else { if (!_extensions.ContainsKey(queueListItem.ServiceLockTypeEnum)) { Platform.Log(LogLevel.Error, "No extensions loaded for ServiceLockTypeEnum item type: {0}. Failing item.", queueListItem.ServiceLockTypeEnum); //Just fail the ServiceLock item, not much else we can do ResetServiceLock(queueListItem); continue; } IServiceLockProcessorFactory factory = _extensions[queueListItem.ServiceLockTypeEnum]; IServiceLockItemProcessor processor; try { processor = factory.GetItemProcessor(); } catch (Exception e) { Platform.Log(LogLevel.Error, e, "Unexpected exception creating ServiceLock processor."); ResetServiceLock(queueListItem); continue; } _threadPool.Enqueue(processor, queueListItem, delegate(IServiceLockItemProcessor queueProcessor, Model.ServiceLock queueItem) { try { queueProcessor.Process(queueItem); } catch (Exception e) { Platform.Log(LogLevel.Error, e, "Unexpected exception when processing ServiceLock item of type {0}. Failing Queue item. (GUID: {1})", queueItem.ServiceLockTypeEnum, queueItem.GetKey()); ServerPlatform.Alert(AlertCategory.Application, AlertLevel.Error, "ServiceLockProcessor", AlertTypeCodes.UnableToProcess, null, TimeSpan.Zero, "Exception thrown when processing {0} ServiceLock item : {1}", queueItem.ServiceLockTypeEnum.Description, e.Message); ResetServiceLock(queueItem); } // Cleanup the processor queueProcessor.Dispose(); // Signal the thread to come out of sleep mode _threadStop.Set(); }); } } else { // Wait for only 5 seconds when the thread pool is all in use. WaitHandle.WaitAny(new WaitHandle[] { _terminationEvent, _threadStop }, TimeSpan.FromSeconds(5), false); _threadStop.Reset(); } } catch (Exception ex) { Platform.Log(LogLevel.Error, ex, "Exception has occurred : {0}. Retry later.", ex.Message); WaitHandle.WaitAny(new WaitHandle[] { _terminationEvent, _threadStop }, TimeSpan.FromSeconds(5), false); _threadStop.Reset(); } if (_stop) { return; } } }