perform standard file validation @ detail This method performs standard file validation in either serial or @ parallel and updates file integrity metadata.
731def performStandardFileValidation(dictionary, io, parallelMode = False, multithreadedMode=False):
732 if io == "output":
733 if multithreadedMode:
734 os.environ['TRF_MULTITHREADED_VALIDATION'] = 'TRUE'
735 if parallelMode is False:
736 msg.info('Starting legacy (serial) file validation')
737 for (key, arg) in dictionary.items():
738 if not isinstance(arg, argFile):
739 continue
740 if not arg.io == io:
741 continue
742 if arg.auxiliaryFile:
743 continue
744
745 msg.info('Validating data type %s...', key)
746
747 for fname in arg.value:
748 msg.info('Validating file %s...', fname)
749
750 if io == "output":
751 msg.info('{0}: Testing corruption...'.format(fname))
752 if arg.getSingleMetadata(fname, 'integrity') is True:
753 msg.info('Corruption test passed.')
754 elif arg.getSingleMetadata(fname, 'integrity') is False:
755 msg.error('Corruption test failed.')
756 raise trfExceptions.TransformValidationException(trfExit.nameToCode('TRF_EXEC_VALIDATION_FAIL'), 'File %s did not pass corruption test' % fname)
757 elif arg.getSingleMetadata(fname, 'integrity') == 'UNDEFINED':
758 msg.info('No corruption test defined.')
759 elif arg.getSingleMetadata(fname, 'integrity') is None:
760 msg.error('Could not check for file integrity')
761 raise trfExceptions.TransformValidationException(trfExit.nameToCode('TRF_EXEC_VALIDATION_FAIL'), 'File %s might be missing' % fname)
762 else:
763 msg.error('Unknown rc from corruption test.')
764 raise trfExceptions.TransformValidationException(trfExit.nameToCode('TRF_EXEC_VALIDATION_FAIL'), 'File %s did not pass corruption test' % fname)
765
766
767 msg.info('{0}: Testing event count...'.format(fname))
768 if arg.getSingleMetadata(fname, 'nentries') is not None:
769 msg.info('Event counting test passed ({0!s} events).'.format(arg.getSingleMetadata(fname, 'nentries')))
770 else:
771 msg.error('Event counting test failed.')
772 raise trfExceptions.TransformValidationException(trfExit.nameToCode('TRF_EXEC_VALIDATION_FAIL'), 'File %s did not pass corruption test' % fname)
773
774
775 msg.info('{0}: Checking if guid exists...'.format(fname))
776 if arg.getSingleMetadata(fname, 'file_guid') is None:
777 msg.error('Guid could not be determined.')
778 raise trfExceptions.TransformValidationException(trfExit.nameToCode('TRF_EXEC_VALIDATION_FAIL'), 'File %s did not pass corruption test' % fname)
779 elif arg.getSingleMetadata(fname, 'file_guid') == 'UNDEFINED':
780 msg.info('Guid not defined.')
781 else:
782 msg.info('Guid is %s', arg.getSingleMetadata(fname, 'file_guid'))
783 msg.info('Stopping legacy (serial) file validation')
784 elif parallelMode is True:
785 msg.info('Starting parallel file validation')
786
787
788 fileList = []
789 argList = []
790
791 integrityFunctionList = []
792
793
794 jobs = []
795 msg.debug('Collating list of files for validation')
796 for (key, arg) in dictionary.items():
797 if not isinstance(arg, argFile):
798 continue
799 if not arg.io == io:
800 continue
801 for fname in arg.value:
802 msg.debug('Appending file {fileName} to list of files for validation'.format(fileName = str(fname)))
803
804 fileList.append(fname)
805
806 argList.append(arg)
807
808
809
810 if io == "output":
811 try:
812 integrityFunctionList.append(arg.integrityFunction)
813 except AttributeError as e:
814 errmsg = f'Validation function for file {fname} of type'\
815 f' {type(arg).__name__!r} not available for parallel file validation: {e}'
816 msg.error(errmsg)
817 raise trfExceptions.TransformValidationException(
818 trfExit.nameToCode('TRF_EXEC_VALIDATION_FAIL'), errmsg)
819
820
821
822 jobs.append(
823 trfUtils.Job(
824 name = "validation of file {fileName}".format(
825 fileName = str(fname)),
826 workFunction = returnIntegrityOfFile,
827 workFunctionKeywordArguments = {
828 'file': fname,
829 'functionName': arg.integrityFunction,
830 'level': msg.getEffectiveLevel(),
831 },
832 workFunctionTimeout = 600
833 )
834 )
835
836
837 if io == "output":
838 jobGroup1 = trfUtils.JobGroup(
839 name = "standard file validation",
840 jobs = jobs
841 )
842
843 parallelJobProcessor1 = trfUtils.ParallelJobProcessor(numberOfProcesses=len(jobs))
844
845 msg.info('Submitting file validation jobs to parallel job processor')
846 parallelJobProcessor1.submit(jobSubmission = jobGroup1)
847 resultsList = parallelJobProcessor1.getResults()
848 msg.info('Parallel file validation complete')
849
850
851 msg.info('Processing file integrity results')
852 for currentFile, currentArg, currentIntegrityFunction, currentResult in zip(fileList, argList, integrityFunctionList, resultsList):
853 msg.info('{IO} file {fileName} has integrity status {integrityStatus} as determined by integrity function {integrityFunction}'.format(
854 IO = str(io),
855 fileName = str(currentFile),
856 integrityStatus = str(currentResult),
857 integrityFunction = str(currentIntegrityFunction)
858 ))
859
860
861
862 if currentResult[0] is True:
863 msg.info('Updating integrity metadata for file {fileName}'.format(fileName = str(currentFile)))
864 currentArg._setMetadata(files=[currentFile,], metadataKeys={'integrity': currentResult[0]})
865 else:
866 exceptionMessage = "{IO} file validation failure on file {fileName} with integrity status {integrityStatus} as determined by integrity function {integrityFunction}".format(
867 IO = str(io),
868 fileName = str(currentFile),
869 integrityStatus = str(currentResult),
870 integrityFunction = str(currentIntegrityFunction)
871 )
872 msg.error("exception message: {exceptionMessage}".format(
873 exceptionMessage = exceptionMessage
874 ))
875 exitCodeName = 'TRF_OUTPUT_FILE_VALIDATION_FAIL'
876 raise trfExceptions.TransformValidationException(
877 trfExit.nameToCode(exitCodeName),
878 exceptionMessage
879 )
880
881
882 if currentArg.getSingleMetadata(currentFile, metadataKey = 'integrity', populate = False) == currentResult[0]:
883 msg.debug("file integrity metadata update successful")
884 else:
885 msg.error("file integrity metadata update unsuccessful")
886
887 metadataKeys = ('nentries', 'file_guid')
888 msg.info(f"{', '.join(fileList)}: Checking {', '.join(map(repr, metadataKeys))} ...")
889 metadata = {fname: arg.getMetadata(fname, metadataKeys=metadataKeys)[fname]
890 for fname, arg in zip(fileList, argList, strict=True)}
891 success = {fname: md for fname, md in metadata.items() if None not in md.values()}
892 if len(success):
893 lines = [
894 f"{fname}: {' '.join(f'{k}={v}' for k, v in md.items())}"
895 for fname, md in success.items()
896 ]
897 msg.info("Checked\n\t" + "\n\t".join(lines))
898 if len(success) != len(metadata):
899 missing = ", ".join(fname for fname in metadata if fname not in success)
900 keys = '" and/or "'.join(metadataKeys)
901 errmsg = f'{missing}: Could not determine "{keys}"'
902 msg.error(errmsg)
903 raise trfExceptions.TransformValidationException(trfExit.nameToCode('TRF_EXEC_VALIDATION_FAIL'), errmsg)
904 msg.info('Stopping parallel file validation')
905
906