Skip to content
Snippets Groups Projects
Commit e0ccb58d authored by sveseli's avatar sveseli
Browse files

changes that allow simultaneous data acquisitions for the same experiment

parent b1b99190
No related branches found
No related tags found
No related merge requests found
...@@ -4,6 +4,7 @@ import os ...@@ -4,6 +4,7 @@ import os
from dm.common.utility.loggingManager import LoggingManager from dm.common.utility.loggingManager import LoggingManager
from dm.common.processing.plugins.fileProcessor import FileProcessor from dm.common.processing.plugins.fileProcessor import FileProcessor
from uploadTracker import UploadTracker from uploadTracker import UploadTracker
from daqTracker import DaqTracker
class DaqProcessingCompleteNotificationPlugin(FileProcessor): class DaqProcessingCompleteNotificationPlugin(FileProcessor):
...@@ -12,18 +13,24 @@ class DaqProcessingCompleteNotificationPlugin(FileProcessor): ...@@ -12,18 +13,24 @@ class DaqProcessingCompleteNotificationPlugin(FileProcessor):
self.logger = LoggingManager.getInstance().getLogger(self.__class__.__name__) self.logger = LoggingManager.getInstance().getLogger(self.__class__.__name__)
def processFile(self, fileInfo): def processFile(self, fileInfo):
uploadId = fileInfo.get('uploadId')
filePath = fileInfo.get('filePath') filePath = fileInfo.get('filePath')
uploadId = fileInfo.get('uploadId')
daqId = fileInfo.get('daqInfo', {}).get('id')
trackedInfo = None
if uploadId != None: if uploadId != None:
self.logger.debug('Upload id for file %s: %s' %(filePath, uploadId)) self.logger.debug('Upload id for file %s: %s' %(filePath, uploadId))
uploadInfo = UploadTracker.getInstance().get(uploadId) trackedInfo = UploadTracker.getInstance().get(uploadId)
if uploadInfo != None: if daqId != None:
fileDict = uploadInfo.get('fileDict', {}) self.logger.debug('Daq id for file %s: %s' %(filePath, daqId))
uploadFileInfo = fileDict.get(filePath) trackedInfo = DaqTracker.getInstance().get(daqId)
if uploadFileInfo: if trackedInfo != None:
uploadFileInfo['processed'] = True fileDict = trackedInfo.get('fileDict', {})
trackedFileInfo = fileDict.get(filePath)
if trackedFileInfo:
trackedFileInfo['processed'] = True
else: else:
self.logger.error('Upload tracker does not have upload id %s' %(uploadId)) self.logger.error('%s object does not have file path %s' %(trackedInfo, filePath))
trackedInfo.updateStatus()
####################################################################### #######################################################################
......
#!/usr/bin/env python #!/usr/bin/env python
import os import os
import copy
from dm.common.utility.loggingManager import LoggingManager from dm.common.utility.loggingManager import LoggingManager
from dm.common.processing.plugins.fileProcessor import FileProcessor from dm.common.processing.plugins.fileProcessor import FileProcessor
from dm.ds_web_service.api.dsRestApiFactory import DsRestApiFactory from dm.ds_web_service.api.dsRestApiFactory import DsRestApiFactory
...@@ -14,15 +15,17 @@ class DsProcessFileNotificationPlugin(FileProcessor): ...@@ -14,15 +15,17 @@ class DsProcessFileNotificationPlugin(FileProcessor):
def processFile(self, fileInfo): def processFile(self, fileInfo):
experimentFilePath = fileInfo.get('experimentFilePath') experimentFilePath = fileInfo.get('experimentFilePath')
experiment = fileInfo.get('experiment') experimentName = fileInfo.get('experimentName')
experimentName = experiment.get('name')
self.logger.debug('Processing file %s for experiment %s' % (experimentFilePath, experimentName)) self.logger.debug('Processing file %s for experiment %s' % (experimentFilePath, experimentName))
daqInfo = copy.deepcopy(fileInfo.get('daqInfo', {}))
if daqInfo.has_key('fileDict'):
del daqInfo['fileDict']
# Prepare dictionary for processing. Only send needed data. # Prepare dictionary for processing. Only send needed data.
fileInfo2 = {} fileInfo2 = {}
fileInfo2['experimentFilePath'] = experimentFilePath fileInfo2['experimentFilePath'] = experimentFilePath
fileInfo2['experimentName'] = experimentName fileInfo2['experimentName'] = experimentName
fileInfo2['daqInfo'] = experiment.get('daqInfo') fileInfo2['daqInfo'] = daqInfo
self.dsFileApi.processFile(experimentFilePath, experimentName, fileInfo2) self.dsFileApi.processFile(experimentFilePath, experimentName, fileInfo2)
####################################################################### #######################################################################
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
import os import os
import time import time
import uuid import uuid
import copy
from dm.common.objects.experiment import Experiment from dm.common.objects.experiment import Experiment
from dm.common.objects.dmObjectManager import DmObjectManager from dm.common.objects.dmObjectManager import DmObjectManager
...@@ -16,9 +17,12 @@ from dm.common.objects.observedFile import ObservedFile ...@@ -16,9 +17,12 @@ from dm.common.objects.observedFile import ObservedFile
from dm.common.objects.uploadInfo import UploadInfo from dm.common.objects.uploadInfo import UploadInfo
from dm.common.processing.fileProcessingManager import FileProcessingManager from dm.common.processing.fileProcessingManager import FileProcessingManager
from dm.common.utility.fileUtility import FileUtility from dm.common.utility.fileUtility import FileUtility
from dm.common.utility.timeUtility import TimeUtility
from dm.common.utility.dictUtility import DictUtility
from dm.ds_web_service.api.dsRestApiFactory import DsRestApiFactory from dm.ds_web_service.api.dsRestApiFactory import DsRestApiFactory
from experimentTracker import ExperimentTracker from experimentTracker import ExperimentTracker
from uploadTracker import UploadTracker from uploadTracker import UploadTracker
from daqTracker import DaqTracker
from fileSystemObserver import FileSystemObserver from fileSystemObserver import FileSystemObserver
class ExperimentSessionControllerImpl(DmObjectManager): class ExperimentSessionControllerImpl(DmObjectManager):
...@@ -30,58 +34,56 @@ class ExperimentSessionControllerImpl(DmObjectManager): ...@@ -30,58 +34,56 @@ class ExperimentSessionControllerImpl(DmObjectManager):
def startDaq(self, experimentName, dataDirectory, daqInfo): def startDaq(self, experimentName, dataDirectory, daqInfo):
FileSystemObserver.getInstance().createDirectory(dataDirectory) FileSystemObserver.getInstance().createDirectory(dataDirectory)
if daqInfo is None:
daqInfo={}
daqInfo['experimentName'] = experimentName
daqInfo['dataDirectory'] = dataDirectory
experiment = ExperimentTracker.getInstance().get(experimentName)
if experiment is not None:
oldDaqInfo = experiment.get('daqInfo')
if oldDaqInfo.get('daqEndTime') is None:
raise InvalidRequest('DAQ for experiment %s is already active in directory %s.' % (experimentName,oldDaqInfo.get('dataDirectory')))
experiment = self.dsExperimentApi.getExperimentByName(experimentName) experiment = self.dsExperimentApi.getExperimentByName(experimentName)
storageDirectory = experiment.get('storageDirectory') storageDirectory = experiment.get('storageDirectory')
if storageDirectory is None: if storageDirectory is None:
raise InvalidRequest('Experiment %s has not been started.' % experimentName) raise InvalidRequest('Experiment %s has not been started.' % experimentName)
startTime = time.time() daqInfo = DaqTracker.getInstance().startDaq(experiment, dataDirectory, daqInfo)
daqInfo['daqStartTime'] = startTime
experiment['daqInfo'] = daqInfo
self.logger.debug('Starting DAQ %s' % daqInfo)
FileSystemObserver.getInstance().startObservingPath(dataDirectory, experiment) FileSystemObserver.getInstance().startObservingPath(dataDirectory, experiment)
ExperimentTracker.getInstance().put(experimentName, experiment) return daqInfo
return experiment
def stopDaq(self, experimentName): def stopDaq(self, experimentName, dataDirectory):
experiment = ExperimentTracker.getInstance().get(experimentName) experiment = self.dsExperimentApi.getExperimentByName(experimentName)
if experiment is not None: daqInfo = DaqTracker.getInstance().stopDaq(experiment, dataDirectory)
daqInfo = experiment.get('daqInfo')
if experiment is None or daqInfo.get('daqEndTime') is not None:
raise InvalidRequest('Experiment %s is not active.' % experimentName)
dataDirectory = daqInfo.get('dataDirectory')
daqInfo['daqEndTime'] = time.time()
FileSystemObserver.getInstance().stopObservingPath(dataDirectory, experiment) FileSystemObserver.getInstance().stopObservingPath(dataDirectory, experiment)
return experiment return daqInfo.scrub()
def upload(self, daqInfo): def getDaqInfo(self, id):
experimentName = daqInfo.get('experimentName') daqInfo = DaqTracker.getInstance().getDaqInfo(id)
if not daqInfo:
raise ObjectNotFound('Daq id %s not found.' % id)
daqInfo.updateStatus()
return daqInfo.scrub()
def upload(self, experimentName, dataDirectory, daqInfo):
experiment = self.dsExperimentApi.getExperimentByName(experimentName) experiment = self.dsExperimentApi.getExperimentByName(experimentName)
experiment['daqInfo'] = daqInfo experiment['daqInfo'] = daqInfo
storageDirectory = experiment.get('storageDirectory') storageDirectory = experiment.get('storageDirectory')
if storageDirectory is None: if storageDirectory is None:
raise InvalidRequest('Experiment %s has not been started.' % experimentName) raise InvalidRequest('Experiment %s has not been started.' % experimentName)
dataDirectory = daqInfo.get('dataDirectory')
filePaths = FileSystemObserver.getInstance().getFiles(dataDirectory) filePaths = FileSystemObserver.getInstance().getFiles(dataDirectory)
fileProcessingManager = FileProcessingManager.getInstance() fileProcessingManager = FileProcessingManager.getInstance()
uploadId = str(uuid.uuid4()) uploadId = str(uuid.uuid4())
self.logger.debug('Starting upload id %s' % uploadId) self.logger.debug('Starting upload id %s' % uploadId)
uploadInfo = UploadInfo() uploadInfo = UploadInfo(daqInfo)
uploadInfo['id'] = uploadId uploadInfo['id'] = uploadId
uploadInfo['experiment'] = experimentName uploadInfo['experimentName'] = experimentName
uploadInfo['storageDirectory'] = experiment.get('storageDirectory')
uploadInfo['storageHost'] = experiment.get('storageHost')
uploadInfo['dataDirectory'] = dataDirectory uploadInfo['dataDirectory'] = dataDirectory
startTime = time.time()
uploadInfo['startTime'] = startTime
uploadInfo['startTimestamp '] = TimeUtility.formatLocalTimeStamp(startTime)
daqInfo['experimentName'] = experimentName
daqInfo['storageDirectory'] = experiment.get('storageDirectory')
daqInfo['storageHost'] = experiment.get('storageHost')
daqInfo['dataDirectory'] = dataDirectory
daqInfo['uploadId'] = uploadId
fileDict = {} fileDict = {}
for filePath in filePaths: for filePath in filePaths:
fileInfo = ObservedFile(filePath=filePath, dataDirectory=dataDirectory, experiment=experiment) fileInfo = ObservedFile(filePath=filePath, dataDirectory=dataDirectory, experiment=experiment)
fileInfo['daqInfo'] = daqInfo
fileInfo['uploadId'] = uploadId fileInfo['uploadId'] = uploadId
fileUploadInfo = { 'processed' : False } fileUploadInfo = { 'processed' : False }
FileUtility.statFile(filePath, fileUploadInfo) FileUtility.statFile(filePath, fileUploadInfo)
...@@ -89,33 +91,14 @@ class ExperimentSessionControllerImpl(DmObjectManager): ...@@ -89,33 +91,14 @@ class ExperimentSessionControllerImpl(DmObjectManager):
fileProcessingManager.processFile(fileInfo) fileProcessingManager.processFile(fileInfo)
uploadInfo['fileDict'] = fileDict uploadInfo['fileDict'] = fileDict
#self.logger.debug('Upload info %s' % uploadInfo) #self.logger.debug('Upload info %s' % uploadInfo)
ExperimentTracker.getInstance().put(experimentName, experiment)
UploadTracker.getInstance().put(uploadId, uploadInfo) UploadTracker.getInstance().put(uploadId, uploadInfo)
return uploadInfo return uploadInfo.scrub()
def getUploadInfo(self, id): def getUploadInfo(self, id):
uploadInfo = UploadTracker.getInstance().get(id) uploadInfo = UploadTracker.getInstance().get(id)
if not uploadInfo: if not uploadInfo:
raise ObjectNotFound('Upload id %s not found.' % id) raise ObjectNotFound('Upload id %s not found.' % id)
uploadStatus = uploadInfo.get('status', 'running') uploadInfo.updateStatus()
if uploadStatus == 'complete': return uploadInfo.scrub()
return uploadInfo
fileDict = uploadInfo.get('fileDict')
nFiles = len(fileDict)
nProcessedFiles = 0
for (filePath,uploadFileInfo) in fileDict.items():
if uploadFileInfo.get('processed'):
nProcessedFiles += 1
# need to handle 'failed' uploads
if nProcessedFiles == nFiles:
uploadStatus = 'complete'
uploadInfo['status'] = uploadStatus
uploadInfo['nProcessedFiles'] = '%s/%s' % (nProcessedFiles,nFiles)
percentageComplete = 100.0
if nFiles > 0:
percentageComplete = float(nProcessedFiles)/float(nFiles)*100.0
uploadInfo['percentageComplete'] = '%.2f' % percentageComplete
return uploadInfo
...@@ -14,6 +14,7 @@ from dm.common.utility.threadingUtility import ThreadingUtility ...@@ -14,6 +14,7 @@ from dm.common.utility.threadingUtility import ThreadingUtility
from dm.common.processing.fileProcessingManager import FileProcessingManager from dm.common.processing.fileProcessingManager import FileProcessingManager
from dmFileSystemEventHandler import DmFileSystemEventHandler from dmFileSystemEventHandler import DmFileSystemEventHandler
from daqTracker import DaqTracker
class FileSystemObserver(threading.Thread,Singleton): class FileSystemObserver(threading.Thread,Singleton):
...@@ -84,8 +85,13 @@ class FileSystemObserver(threading.Thread,Singleton): ...@@ -84,8 +85,13 @@ class FileSystemObserver(threading.Thread,Singleton):
@ThreadingUtility.synchronize @ThreadingUtility.synchronize
def fileUpdated(self, filePath, dataDirectory, experiment): def fileUpdated(self, filePath, dataDirectory, experiment):
daqInfo = DaqTracker.getInstance().getDaqInfoByExperimentAndDataDirectory(experiment, dataDirectory)
observedFile = self.observedFileMap.get(filePath, ObservedFile(filePath=filePath, dataDirectory=dataDirectory, experiment=experiment)) observedFile = self.observedFileMap.get(filePath, ObservedFile(filePath=filePath, dataDirectory=dataDirectory, experiment=experiment))
observedFile.setLastUpdatedTimestampToNow() observedFile.setLastUpdateTimeToNow()
if daqInfo:
daqFileDict = daqInfo['fileDict']
daqFileDict[filePath] = observedFile
observedFile['daqInfo'] = daqInfo.toDictWithOriginalKeys()
self.observedFileMap[filePath] = observedFile self.observedFileMap[filePath] = observedFile
self.logger.debug('Observed file updated: %s', observedFile) self.logger.debug('Observed file updated: %s', observedFile)
...@@ -94,7 +100,7 @@ class FileSystemObserver(threading.Thread,Singleton): ...@@ -94,7 +100,7 @@ class FileSystemObserver(threading.Thread,Singleton):
now = time.time() now = time.time()
filePathsForProcessing = [] filePathsForProcessing = []
for (filePath,observedFile) in self.observedFileMap.items(): for (filePath,observedFile) in self.observedFileMap.items():
timestamp = observedFile.get('lastUpdateTimestamp') timestamp = observedFile.get('lastUpdateTime')
deltaT = now - timestamp deltaT = now - timestamp
if deltaT > self.minFileProcessingDelayInSeconds: if deltaT > self.minFileProcessingDelayInSeconds:
self.logger.debug('File %s was last modified %s seconds ago, will process it.' % (filePath, deltaT)) self.logger.debug('File %s was last modified %s seconds ago, will process it.' % (filePath, deltaT))
...@@ -124,9 +130,9 @@ class FileSystemObserver(threading.Thread,Singleton): ...@@ -124,9 +130,9 @@ class FileSystemObserver(threading.Thread,Singleton):
self.logger.debug('Exit flag set, %s done' % self.getName()) self.logger.debug('Exit flag set, %s done' % self.getName())
break break
try: try:
self.logger.debug('Checking observed files')
filePathsForProcessing = self.checkObservedFilesForProcessing() filePathsForProcessing = self.checkObservedFilesForProcessing()
if len(filePathsForProcessing):
self.logger.debug('Checking observed files')
for filePath in filePathsForProcessing: for filePath in filePathsForProcessing:
self.processFile(filePath) self.processFile(filePath)
except Exception, ex: except Exception, ex:
......
...@@ -7,6 +7,7 @@ class UploadTracker(ObjectTracker): ...@@ -7,6 +7,7 @@ class UploadTracker(ObjectTracker):
# Cache configuration # Cache configuration
objectClass = UploadInfo objectClass = UploadInfo
cacheSize = 100
#################################################################### ####################################################################
# Testing # Testing
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment