/// <summary> /// Do the actual Study migration. /// </summary> /// <param name="fs">The filesystem</param> /// <param name="item">The ServiceLock item being processed.</param> private void DoStudyMigrate(ServerFilesystemInfo fs, Model.ServiceLock item) { FilesystemQueueTypeEnum type = FilesystemQueueTypeEnum.TierMigrate; while (_bytesToRemove > 0) { TimeSpanStatistics queryTime = new TimeSpanStatistics("Query Time"); queryTime.Start(); IList <FilesystemQueue> list = GetFilesystemQueueCandidates(item, Platform.Time, type, false); queryTime.End(); Platform.Log(LogLevel.Info, "{1:0.0} MBs needs to be removed from '{0}'. Found {2} studies that can be migrated in {3} seconds", fs.Filesystem.Description, _bytesToRemove / (1024 * 1024), list.Count, queryTime.Value.TotalSeconds); if (list.Count > 0) { ProcessStudyMigrateCandidates(list); if (CancelPending) { break; } } else { break; } } }
/// <summary> /// Do the actual StudyPurge /// </summary> /// <param name="item"></param> /// <param name="fs">The filesystem being worked on.</param> private void DoStudyPurge(ServerFilesystemInfo fs, Model.ServiceLock item) { DateTime deleteTime = Platform.Time; FilesystemQueueTypeEnum type = FilesystemQueueTypeEnum.PurgeStudy; while (_bytesToRemove > 0) { Platform.Log(LogLevel.Debug, "{1:0.0} MBs needs to be removed from '{0}'. Querying for studies that can be purged", fs.Filesystem.Description, _bytesToRemove / (1024 * 1024)); IList <FilesystemQueue> list = GetFilesystemQueueCandidates(item, deleteTime, type, false); if (list.Count > 0) { ProcessStudyPurgeCandidates(list); if (CancelPending) { break; } } else { // No candidates break; } } }
public InsertFilesystemQueueCommand(FilesystemQueueTypeEnum queueType, ServerEntityKey filesystemKey, ServerEntityKey studyStorageKey, DateTime scheduledTime, XmlDocument queueXml) : base("Insert FilesystemQueue Record of type " + queueType) { _queueType = queueType; _filesystemKey = filesystemKey; _studyStorageKey = studyStorageKey; _scheduledTime = scheduledTime; _queueXml = queueXml; }
protected override void OnProcess(Model.ServiceLock item) { ServerFilesystemInfo fs = FilesystemMonitor.Instance.GetFilesystemInfo(item.FilesystemKey); Platform.Log(LogLevel.Info, "Starting check for studies to lossless compress on filesystem '{0}'.", fs.Filesystem.Description); int delayMinutes = ServiceLockSettings.Default.FilesystemLosslessCompressRecheckDelay; try { DateTime deleteTime = Platform.Time; FilesystemQueueTypeEnum type = FilesystemQueueTypeEnum.LosslessCompress; IList <FilesystemQueue> list = GetFilesystemQueueCandidates(item, deleteTime, type, false); if (list.Count > 0) { ProcessCompressCandidates(list, type); } } catch (Exception e) { Platform.Log(LogLevel.Error, e, "Unexpected exception when processing LosslessCompress records."); delayMinutes = 5; } DateTime scheduledTime = Platform.Time.AddMinutes(delayMinutes); if (_studiesInserted == 0) { Platform.Log(LogLevel.Info, "No eligible candidates to lossless compress from filesystem '{0}'. Next scheduled filesystem check {1}", fs.Filesystem.Description, scheduledTime); } else { Platform.Log(LogLevel.Info, "Completed inserting lossless compress candidates into WorkQueue: {0}. {1} studies inserted. Next scheduled filesystem check {2}", fs.Filesystem.Description, _studiesInserted, scheduledTime); } UnlockServiceLock(item, true, scheduledTime); }
/// <summary> /// Get a list of candidates from the <see cref="FilesystemQueue"/>. /// </summary> /// <param name="item">The ServiceLock item.</param> /// <param name="scheduledTime">The scheduled time to query against</param> /// <param name="type">The type of FilesystemQueue entry.</param> /// <param name="statusCheck">If true, check for specific status value WorkQueue entries already existing, otherwise check for any WorkQueue entry.</param> /// <returns>The list of queue entries.</returns> protected IList <FilesystemQueue> GetFilesystemQueueCandidates(Model.ServiceLock item, DateTime scheduledTime, FilesystemQueueTypeEnum type, bool statusCheck) { using (ServerExecutionContext context = new ServerExecutionContext()) { IFilesystemQueueEntityBroker broker = context.ReadContext.GetBroker <IFilesystemQueueEntityBroker>(); FilesystemQueueSelectCriteria fsQueueCriteria = new FilesystemQueueSelectCriteria(); fsQueueCriteria.FilesystemKey.EqualTo(item.FilesystemKey); fsQueueCriteria.ScheduledTime.LessThanOrEqualTo(scheduledTime); fsQueueCriteria.FilesystemQueueTypeEnum.EqualTo(type); // Do the select based on the QueueStudyState (used to be based on a link to the WorkQueue table) StudyStorageSelectCriteria studyStorageSearchCriteria = new StudyStorageSelectCriteria(); studyStorageSearchCriteria.QueueStudyStateEnum.EqualTo(QueueStudyStateEnum.Idle); fsQueueCriteria.StudyStorage.Exists(studyStorageSearchCriteria); fsQueueCriteria.ScheduledTime.SortAsc(0); IList <FilesystemQueue> list = broker.Find(fsQueueCriteria, 0, ServiceLockSettings.Default.FilesystemQueueResultCount); return(list); } }
/// <summary> /// Process StudyCompress Candidates retrieved from the <see cref="Model.FilesystemQueue"/> table /// </summary> /// <param name="candidateList">The list of candidate studies for deleting.</param> /// <param name="type">The type of compress candidate (lossy or lossless)</param> private void ProcessCompressCandidates(IEnumerable <FilesystemQueue> candidateList, FilesystemQueueTypeEnum type) { using (ServerExecutionContext context = new ServerExecutionContext()) { DateTime scheduledTime = Platform.Time.AddSeconds(10); foreach (FilesystemQueue queueItem in candidateList) { // Check for Shutdown/Cancel if (CancelPending) { break; } // First, get the StudyStorage locations for the study, and calculate the disk usage. StudyStorageLocation location; if (!FilesystemMonitor.Instance.GetWritableStudyStorageLocation(queueItem.StudyStorageKey, out location)) { continue; } StudyXml studyXml; try { studyXml = LoadStudyXml(location); } catch (Exception e) { Platform.Log(LogLevel.Error, e, "Skipping compress candidate, unexpected exception loading StudyXml file for {0}", location.GetStudyPath()); continue; } using ( IUpdateContext update = PersistentStoreRegistry.GetDefaultStore().OpenUpdateContext(UpdateContextSyncMode.Flush)) { ILockStudy lockstudy = update.GetBroker <ILockStudy>(); LockStudyParameters lockParms = new LockStudyParameters(); lockParms.StudyStorageKey = location.Key; lockParms.QueueStudyStateEnum = QueueStudyStateEnum.CompressScheduled; if (!lockstudy.Execute(lockParms) || !lockParms.Successful) { Platform.Log(LogLevel.Warn, "Unable to lock study for inserting Lossless Compress. Reason:{0}. Skipping study ({1})", lockParms.FailureReason, location.StudyInstanceUid); continue; } scheduledTime = scheduledTime.AddSeconds(3); IInsertWorkQueueFromFilesystemQueue workQueueInsert = update.GetBroker <IInsertWorkQueueFromFilesystemQueue>(); InsertWorkQueueFromFilesystemQueueParameters insertParms = new InsertWorkQueueFromFilesystemQueueParameters(); insertParms.WorkQueueTypeEnum = WorkQueueTypeEnum.CompressStudy; insertParms.FilesystemQueueTypeEnum = FilesystemQueueTypeEnum.LosslessCompress; insertParms.StudyStorageKey = location.GetKey(); insertParms.ServerPartitionKey = location.ServerPartitionKey; DateTime expirationTime = scheduledTime; insertParms.ScheduledTime = expirationTime; insertParms.DeleteFilesystemQueue = true; insertParms.Data = queueItem.QueueXml; insertParms.FilesystemQueueTypeEnum = type; insertParms.WorkQueueTypeEnum = WorkQueueTypeEnum.CompressStudy; try { WorkQueue entry = workQueueInsert.FindOne(insertParms); InsertWorkQueueUidFromStudyXml(studyXml, update, entry.GetKey()); update.Commit(); _studiesInserted++; } catch (Exception e) { Platform.Log(LogLevel.Error, e, "Skipping compress record, unexpected problem inserting 'CompressStudy' record into WorkQueue for Study {0}", location.StudyInstanceUid); // throw; -- would cause abort of inserts, go ahead and try everything } } } } }