protected void ImporterLoop() { while (!IsSuspended) { // We handle three cases here: // 1) Job available - process job and continue // 2) No job available - sleep until a job is available or we are suspended // 3) Job cannot be processed - exit loop and suspend ImportJob job; while ((job = PeekImportJob()) != null) { Process(job); ImportJobState state = job.State; if (state == ImportJobState.Finished || state == ImportJobState.Erroneous || state == ImportJobState.Cancelled) { RemoveImportJob(job); // Maybe the queue was changed (cleared & filled again), so a simple call to Dequeue() could dequeue the wrong job } if (IsSuspended) { break; } } if (!IsImportJobAvailable) { WaitHandle.WaitAny(new WaitHandle[] { _importJobsReadyAvailableEvent, _suspendedEvent }); } } }
protected void CheckImportStillRunning(ImportJobState state) { CheckSuspended(null); if (state == ImportJobState.Cancelled || state == ImportJobState.Erroneous) { throw new ImportAbortException(); } }
public ImportJobInformation(ImportJobInformation other) { _jobType = other.JobType; _basePath = other.BasePath; _metadataExtractorIds = new HashSet <Guid>(other.MetadataExtractorIds); _includeSubDirectories = other.IncludeSubDirectories; _state = other.State; }
public ImportJobInformation(ImportJobType jobType, ResourcePath basePath, IEnumerable <Guid> metadataExtractorIds, bool includeSubDirectories) { _jobType = jobType; _basePath = basePath; _metadataExtractorIds = new HashSet <Guid>(metadataExtractorIds); _includeSubDirectories = includeSubDirectories; _state = ImportJobState.None; }
public ImportJobInformation(ImportJobType jobType, ResourcePath basePath, IEnumerable<Guid> metadataExtractorIds, bool includeSubDirectories) { _jobType = jobType; _basePath = basePath; _metadataExtractorIds = new HashSet<Guid>(metadataExtractorIds); _includeSubDirectories = includeSubDirectories; _state = ImportJobState.None; }
/// <summary> /// Executes the given <paramref name="importJob"/>. /// </summary> /// <remarks> /// This method automatically terminates if it encounters that this importer worker was suspended or that the /// given <paramref name="importJob"/> was cancelled. /// </remarks> /// <param name="importJob">Import job to be executed. The state variables of this parameter will be updated by /// this method.</param> protected void Process(ImportJob importJob) { ImportJobState state = importJob.State; if (state == ImportJobState.Finished || state == ImportJobState.Cancelled || state == ImportJobState.Erroneous) { return; } // Preparation IMediaAccessor mediaAccessor = ServiceRegistration.Get <IMediaAccessor>(); IImportResultHandler resultHandler; IMediaBrowsing mediaBrowsing; lock (_syncObj) { resultHandler = _importResultHandler; mediaBrowsing = _mediaBrowsingCallback; } if (mediaBrowsing == null || resultHandler == null) { // Can be the case if this importer worker was asynchronously suspended return; } try { try { ICollection <IMetadataExtractor> metadataExtractors = new List <IMetadataExtractor>(); foreach (Guid metadataExtractorId in importJob.MetadataExtractorIds) { IMetadataExtractor extractor; if (!mediaAccessor.LocalMetadataExtractors.TryGetValue(metadataExtractorId, out extractor)) { continue; } metadataExtractors.Add(extractor); } // Prepare import if (state == ImportJobState.Scheduled) { ServiceRegistration.Get <ILogger>().Info("ImporterWorker: Starting import job '{0}'", importJob); ImporterWorkerMessaging.SendImportMessage(ImporterWorkerMessaging.MessageType.ImportStarted, importJob.BasePath); IResourceAccessor ra; if (!importJob.BasePath.TryCreateLocalResourceAccessor(out ra)) { throw new ArgumentException(string.Format("Unable to access resource path '{0}'", importJob.BasePath)); } using (ra) { IFileSystemResourceAccessor fsra = ra as IFileSystemResourceAccessor; if (fsra != null) { // Prepare complex import process importJob.PendingResources.Add(new PendingImportResource(Guid.Empty, (IFileSystemResourceAccessor)fsra.Clone())); importJob.State = ImportJobState.Active; } else { // Simple resource import ImportSingleFile(importJob, ra, metadataExtractors, mediaBrowsing, resultHandler, mediaAccessor); lock (importJob.SyncObj) if (importJob.State == ImportJobState.Active) { importJob.State = ImportJobState.Finished; } return; } } } else { ServiceRegistration.Get <ILogger>().Info("ImporterWorker: Resuming import job '{0}' ({1} items pending)", importJob, importJob.PendingResources.Count); } // Actual import process while (importJob.HasPendingResources) { Thread.Sleep(0); CheckImportStillRunning(importJob.State); PendingImportResource pendingImportResource; lock (importJob.SyncObj) pendingImportResource = importJob.PendingResources.FirstOrDefault(); if (pendingImportResource.IsValid) { IFileSystemResourceAccessor fsra = pendingImportResource.ResourceAccessor; int numPending = importJob.PendingResources.Count; string moreResources = numPending > 1 ? string.Format(" ({0} more resources pending)", numPending) : string.Empty; ServiceRegistration.Get <ILogger>().Info("ImporterWorker: Importing '{0}'{1}", fsra.ResourcePathName, moreResources); if (fsra.IsFile && fsra.Exists) { ImportResource(importJob, fsra, pendingImportResource.ParentDirectory, metadataExtractors, resultHandler, mediaAccessor); } else if (!fsra.IsFile) { CheckImportStillRunning(importJob.State); Guid?currentDirectoryId = ImportDirectory(importJob, pendingImportResource.ParentDirectory, fsra, metadataExtractors, mediaBrowsing, resultHandler, mediaAccessor); CheckImportStillRunning(importJob.State); if (currentDirectoryId.HasValue && importJob.IncludeSubDirectories) { // Add subdirectories in front of work queue lock (importJob.SyncObj) { ICollection <IFileSystemResourceAccessor> directories = FileSystemResourceNavigator.GetChildDirectories(fsra, false); if (directories != null) { foreach (IFileSystemResourceAccessor childDirectory in directories) { importJob.PendingResources.Insert(0, new PendingImportResource(currentDirectoryId.Value, childDirectory)); } } } } } else { ServiceRegistration.Get <ILogger>().Warn("ImporterWorker: Cannot import resource '{0}': It's neither a file nor a directory", fsra.CanonicalLocalResourcePath.Serialize()); } } lock (importJob.SyncObj) importJob.PendingResources.Remove(pendingImportResource); pendingImportResource.Dispose(); } lock (importJob.SyncObj) if (importJob.State == ImportJobState.Active) { importJob.State = ImportJobState.Finished; } ServiceRegistration.Get <ILogger>().Info("ImporterWorker: Finished import job '{0}'", importJob); ImporterWorkerMessaging.SendImportMessage(ImporterWorkerMessaging.MessageType.ImportCompleted, importJob.BasePath); } catch (Exception e) { CheckSuspended(e); // Throw ImportAbortException if suspended - will skip warning and tagging job as erroneous ServiceRegistration.Get <ILogger>().Warn("ImporterWorker: Problem processing '{0}'", e, importJob); ImporterWorkerMessaging.SendImportMessage(ImporterWorkerMessaging.MessageType.ImportCompleted, importJob.BasePath); importJob.State = ImportJobState.Erroneous; } } catch (ImportSuspendedException) { ServiceRegistration.Get <ILogger>().Info("ImporterWorker: Suspending import job '{0}' ({1} items pending - will be continued next time)", importJob, importJob.PendingResources.Count); } catch (ImportAbortException) { ServiceRegistration.Get <ILogger>().Info("ImporterWorker: Aborting import job '{0}' ({1} items pending)", importJob, importJob.PendingResources.Count); } }
protected void CheckImportStillRunning(ImportJobState state) { CheckSuspended(null); if (state == ImportJobState.Cancelled || state == ImportJobState.Erroneous) throw new ImportAbortException(); }
public ImportJobInformation(ImportJobInformation other) { _jobType = other.JobType; _basePath = other.BasePath; _metadataExtractorIds = new HashSet<Guid>(other.MetadataExtractorIds); _includeSubDirectories = other.IncludeSubDirectories; _state = other.State; }