private void ReinventoryFilesystem(Filesystem filesystem) { ServerPartition partition; DirectoryInfo filesystemDir = new DirectoryInfo(filesystem.FilesystemPath); foreach (DirectoryInfo partitionDir in filesystemDir.GetDirectories()) { if (GetServerPartition(partitionDir.Name, out partition) == false) { continue; } foreach (DirectoryInfo dateDir in partitionDir.GetDirectories()) { if (dateDir.FullName.EndsWith("Deleted", StringComparison.InvariantCultureIgnoreCase) || dateDir.FullName.EndsWith(ServerPlatform.ReconcileStorageFolder, StringComparison.InvariantCultureIgnoreCase)) { continue; } List <FileInfo> fileList; foreach (DirectoryInfo studyDir in dateDir.GetDirectories()) { if (studyDir.FullName.EndsWith("Deleted", StringComparison.InvariantCultureIgnoreCase)) { continue; } // Check for Cancel message if (CancelPending) { return; } String studyInstanceUid = studyDir.Name; StudyStorageLocation location; if (GetStudyStorageLocation(partition.Key, studyInstanceUid, out location)) { #region Study record exists in db int integrityQueueCount; int workQueueCount; Study theStudy = GetStudyAndQueues(location, out integrityQueueCount, out workQueueCount); if (theStudy != null) { continue; } if (integrityQueueCount != 0 && workQueueCount != 0) { continue; } fileList = LoadSopFiles(studyDir, false); if (fileList.Count == 0) { Platform.Log(LogLevel.Warn, "Found empty study folder with StorageLocation, deleteing StorageLocation: {0}\\{1}", dateDir.Name, studyDir.Name); studyDir.Delete(true); RemoveStudyStorage(location); continue; } // WriteLock the new study storage for study processing if (!location.QueueStudyStateEnum.Equals(QueueStudyStateEnum.ProcessingScheduled)) { string failureReason; if (!ServerHelper.LockStudy(location.Key, QueueStudyStateEnum.ProcessingScheduled, out failureReason)) { Platform.Log(LogLevel.Error, "Unable to lock study {0} for Study Processing", location.StudyInstanceUid); } } #endregion } else { #region Directory not in DB, fileList = LoadSopFiles(studyDir, true); if (fileList.Count == 0) { Platform.Log(LogLevel.Warn, "Found empty study folder: {0}\\{1}", dateDir.Name, studyDir.Name); continue; } DicomFile file = LoadFileFromList(fileList); if (file == null) { Platform.Log(LogLevel.Warn, "Found directory with no readable files: {0}\\{1}", dateDir.Name, studyDir.Name); continue; } // Do a second check, using the study instance uid from a file in the directory. // had an issue with trailing periods on uids causing us to not find the // study storage, and insert a new record into the database. studyInstanceUid = file.DataSet[DicomTags.StudyInstanceUid].ToString(); if (GetStudyStorageLocation(partition.Key, studyInstanceUid, out location)) { continue; } StudyStorage storage; if (GetStudyStorage(partition, studyInstanceUid, out storage)) { Platform.Log(LogLevel.Warn, "Study {0} on filesystem partition {1} is offline {2}", studyInstanceUid, partition.Description, studyDir.ToString()); continue; } Platform.Log(LogLevel.Info, "Reinventory inserting study storage location for {0} on partition {1}", studyInstanceUid, partition.Description); // Insert StudyStorage using (IUpdateContext update = _store.OpenUpdateContext(UpdateContextSyncMode.Flush)) { IInsertStudyStorage studyInsert = update.GetBroker <IInsertStudyStorage>(); InsertStudyStorageParameters insertParms = new InsertStudyStorageParameters { ServerPartitionKey = partition.GetKey(), StudyInstanceUid = studyInstanceUid, Folder = dateDir.Name, FilesystemKey = filesystem.GetKey(), QueueStudyStateEnum = QueueStudyStateEnum.Idle }; if (file.TransferSyntax.LosslessCompressed) { insertParms.TransferSyntaxUid = file.TransferSyntax.UidString; insertParms.StudyStatusEnum = StudyStatusEnum.OnlineLossless; } else if (file.TransferSyntax.LossyCompressed) { insertParms.TransferSyntaxUid = file.TransferSyntax.UidString; insertParms.StudyStatusEnum = StudyStatusEnum.OnlineLossy; } else { insertParms.TransferSyntaxUid = file.TransferSyntax.UidString; insertParms.StudyStatusEnum = StudyStatusEnum.Online; } location = studyInsert.FindOne(insertParms); // WriteLock the new study storage for study processing ILockStudy lockStudy = update.GetBroker <ILockStudy>(); LockStudyParameters lockParms = new LockStudyParameters { StudyStorageKey = location.Key, QueueStudyStateEnum = QueueStudyStateEnum.ProcessingScheduled }; if (!lockStudy.Execute(lockParms) || !lockParms.Successful) { Platform.Log(LogLevel.Error, "Unable to lock study {0} for Study Processing", location.StudyInstanceUid); } update.Commit(); } #endregion } string studyXml = location.GetStudyXmlPath(); if (File.Exists(studyXml)) { FileUtils.Delete(studyXml); } string studyGZipXml = location.GetCompressedStudyXmlPath(); if (File.Exists(studyGZipXml)) { FileUtils.Delete(studyGZipXml); } foreach (FileInfo sopFile in fileList) { String sopInstanceUid = sopFile.Name.Replace(sopFile.Extension, string.Empty); using (ServerExecutionContext context = new ServerExecutionContext()) { // Just use a read context here, in hopes of improving // performance. Every other place in the code should use // Update contexts when doing transactions. IInsertWorkQueue workQueueInsert = context.ReadContext.GetBroker <IInsertWorkQueue>(); InsertWorkQueueParameters queueInsertParms = new InsertWorkQueueParameters { WorkQueueTypeEnum = WorkQueueTypeEnum.StudyProcess, StudyStorageKey = location.GetKey(), ServerPartitionKey = partition.GetKey(), SeriesInstanceUid = sopFile.Directory.Name, SopInstanceUid = sopInstanceUid, ScheduledTime = Platform.Time }; if (workQueueInsert.FindOne(queueInsertParms) == null) { Platform.Log(LogLevel.Error, "Failure attempting to insert SOP Instance into WorkQueue during Reinventory."); } } } } // Cleanup the date directory, if its empty. DirectoryUtility.DeleteIfEmpty(dateDir.FullName); } } }