Fixing memory handling of AliHLTMUONHitReconstructorComponent during error conditions...
authoraszostak <aszostak@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 16 May 2008 13:41:43 +0000 (13:41 +0000)
committeraszostak <aszostak@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 16 May 2008 13:41:43 +0000 (13:41 +0000)
Adding parameters to HeaderOk and IntegrityOk methods in AliHLTMUONUtils, so that the reason for the data structure problem is optionally returned.

HLT/MUON/AliHLTMUONUtils.cxx
HLT/MUON/AliHLTMUONUtils.h
HLT/MUON/OnlineAnalysis/AliHLTMUONHitReconstructor.cxx
HLT/MUON/OnlineAnalysis/AliHLTMUONHitReconstructor.h
HLT/MUON/OnlineAnalysis/AliHLTMUONHitReconstructorComponent.cxx

index cc39f9b28d0cf7131d6faefc7a1a416572d59160..1ac4a169c770d981de90627f4fe170d5810a57f1 100644 (file)
@@ -426,18 +426,82 @@ AliHLTMUONDataBlockType AliHLTMUONUtils::ParseCommandLineTypeString(const char*
 }
 
 
+const char* AliHLTMUONUtils::FailureReasonToString(WhyNotValid reason)
+{
+       /// This method converts the WhyNotValid enumeration to a string representation.
+       
+       switch (reason)
+       {
+       case kNoReason: return "kNoReason";
+       case kHeaderContainsWrongType: return "kHeaderContainsWrongType";
+       case kHeaderContainsWrongRecordWidth: return "kHeaderContainsWrongRecordWidth";
+       case kReservedBitsNotZero: return "kReservedBitsNotZero";
+       case kParticleSignBitsNotValid: return "kParticleSignBitsNotValid";
+       case kHitNotMarkedAsNil: return "kHitNotMarkedAsNil";
+       case kFoundDuplicateIDs: return "kFoundDuplicateIDs";
+       case kPtValueNotValid: return "kPtValueNotValid";
+       case kFoundDuplicateTriggers: return "kFoundDuplicateTriggers";
+       case kPairTrackIdsAreIdentical: return "kPairTrackIdsAreIdentical";
+       case kMassValueNotValid: return "kMassValueNotValid";
+       case kLowPtCountInvalid: return "kLowPtCountInvalid";
+       case kHighPtCountInvalid: return "kHighPtCountInvalid";
+       default: return "INVALID";
+       }
+}
+
+
+const char* AliHLTMUONUtils::FailureReasonToMessage(WhyNotValid reason)
+{
+       /// This method returns a string containing a user readable message explaining
+       /// the reason for failure described by the WhyNotValid enumeration.
+       
+       switch (reason)
+       {
+       case kNoReason:
+               return "There was no problem with the data block.";
+       case kHeaderContainsWrongType:
+               return "The common data header contains an incorrect type identifier.";
+       case kHeaderContainsWrongRecordWidth:
+               return "The common data header contains an incorrect data record width.";
+       case kReservedBitsNotZero:
+               return "Reserved bits have not been set to zero.";
+       case kParticleSignBitsNotValid:
+               return "The particle sign bits are not a valid value.";
+       case kHitNotMarkedAsNil:
+               return "A hit was marked as not found, but the corresponding hit"
+                       " structure was not set to nil.";
+       case kFoundDuplicateIDs:
+               return "Found duplicate data record identifiers, but they should all be unique.";
+       case kPtValueNotValid:
+               return "The pT value is not positive, nor -1 indicating an invalid value.";
+       case kFoundDuplicateTriggers:
+               return "Found duplicate trigger decisions.";
+       case kPairTrackIdsAreIdentical:
+               return "The track identifiers of the track pair are identical.";
+       case kMassValueNotValid:
+               return "The invariant mass value is not positive, nor -1 indicating an invalid value.";
+       case kLowPtCountInvalid:
+               return "The low pT trigger count is greater than 2, which is invalid.";
+       case kHighPtCountInvalid:
+               return "The high pT trigger count is greater than 2, which is invalid.";
+       default:
+               return "UNKNOWN REASON CODE";
+       }
+}
+
+
 bool AliHLTMUONUtils::HeaderOk(
                const AliHLTMUONTriggerRecordsBlockStruct& block,
                WhyNotValid* reason
        )
 {
-       ///
-       /// Methods used to check if the header information corresponds to the
-       /// supposed type of the data block.
-       /// If the 'reason' parameter is not NULL then these methods will fill the
-       /// memory pointed to by reason with a code describing of why the header
-       /// is not valid, if and only if a problem is found with the data.
-       ///
+       /// Method used to check if the header information corresponds to the
+       /// supposed type of the raw dHLT data block.
+       /// [in]  \param block  The data block to check.
+       /// [out] \param reason  If this is not NULL, then it will be filled with
+       ///      the reason code describing why the header is not valid, if and
+       ///      only if a problem is found with the data.
+       /// \returns  true if there is no problem with the header and false otherwise.
         
        // The block must have the correct type.
        if (block.fHeader.fType != kTriggerRecordsDataBlock)
@@ -457,187 +521,352 @@ bool AliHLTMUONUtils::HeaderOk(
 }
 
 
-bool AliHLTMUONUtils::HeaderOk(const AliHLTMUONTrigRecsDebugBlockStruct& block)
+bool AliHLTMUONUtils::HeaderOk(
+               const AliHLTMUONTrigRecsDebugBlockStruct& block,
+               WhyNotValid* reason
+       )
 {
-       ///
-       /// Methods used to check if the header information corresponds to the
-       /// supposed type of the data block.
-       ///
+       /// Method used to check if the header information corresponds to the
+       /// supposed type of the raw dHLT data block.
+       /// [in]  \param block  The data block to check.
+       /// [out] \param reason  If this is not NULL, then it will be filled with
+       ///      the reason code describing why the header is not valid, if and
+       ///      only if a problem is found with the data.
+       /// \returns  true if there is no problem with the header and false otherwise.
        
        // The block must have the correct type.
-       if (block.fHeader.fType != kTrigRecsDebugDataBlock) return false;
+       if (block.fHeader.fType != kTrigRecsDebugDataBlock)
+       {
+               if (reason != NULL) *reason = kHeaderContainsWrongType;
+               return false;
+       }
+       
        // The block's record width must be the correct size.
        if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONTrigRecInfoStruct))
+       {
+               if (reason != NULL) *reason = kHeaderContainsWrongRecordWidth;
                return false;
+       }
+       
        return true;
 }
 
 
-bool AliHLTMUONUtils::HeaderOk(const AliHLTMUONTriggerChannelsBlockStruct& block)
+bool AliHLTMUONUtils::HeaderOk(
+               const AliHLTMUONTriggerChannelsBlockStruct& block,
+               WhyNotValid* reason
+       )
 {
-       ///
-       /// Methods used to check if the header information corresponds to the
-       /// supposed type of the data block.
-       ///
+       /// Method used to check if the header information corresponds to the
+       /// supposed type of the raw dHLT data block.
+       /// [in]  \param block  The data block to check.
+       /// [out] \param reason  If this is not NULL, then it will be filled with
+       ///      the reason code describing why the header is not valid, if and
+       ///      only if a problem is found with the data.
+       /// \returns  true if there is no problem with the header and false otherwise.
        
        // The block must have the correct type.
-       if (block.fHeader.fType != kTriggerChannelsDataBlock) return false;
+       if (block.fHeader.fType != kTriggerChannelsDataBlock)
+       {
+               if (reason != NULL) *reason = kHeaderContainsWrongType;
+               return false;
+       }
+       
        // The block's record width must be the correct size.
        if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONTriggerChannelStruct))
+       {
+               if (reason != NULL) *reason = kHeaderContainsWrongRecordWidth;
                return false;
+       }
+       
        return true;
 }
 
 
-bool AliHLTMUONUtils::HeaderOk(const AliHLTMUONRecHitsBlockStruct& block)
+bool AliHLTMUONUtils::HeaderOk(
+               const AliHLTMUONRecHitsBlockStruct& block,
+               WhyNotValid* reason
+       )
 {
-       ///
-       /// Methods used to check if the header information corresponds to the
-       /// supposed type of the data block.
-       ///
+       /// Method used to check if the header information corresponds to the
+       /// supposed type of the raw dHLT data block.
+       /// [in]  \param block  The data block to check.
+       /// [out] \param reason  If this is not NULL, then it will be filled with
+       ///      the reason code describing why the header is not valid, if and
+       ///      only if a problem is found with the data.
+       /// \returns  true if there is no problem with the header and false otherwise.
        
        // The block must have the correct type.
-       if (block.fHeader.fType != kRecHitsDataBlock) return false;
+       if (block.fHeader.fType != kRecHitsDataBlock)
+       {
+               if (reason != NULL) *reason = kHeaderContainsWrongType;
+               return false;
+       }
+       
        // The block's record width must be the correct size.
        if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONRecHitStruct))
+       {
+               if (reason != NULL) *reason = kHeaderContainsWrongRecordWidth;
                return false;
+       }
+       
        return true;
 }
 
 
-bool AliHLTMUONUtils::HeaderOk(const AliHLTMUONClustersBlockStruct& block)
+bool AliHLTMUONUtils::HeaderOk(
+               const AliHLTMUONClustersBlockStruct& block,
+               WhyNotValid* reason
+       )
 {
-       ///
-       /// Methods used to check if the header information corresponds to the
-       /// supposed type of the data block.
-       ///
+       /// Method used to check if the header information corresponds to the
+       /// supposed type of the raw dHLT data block.
+       /// [in]  \param block  The data block to check.
+       /// [out] \param reason  If this is not NULL, then it will be filled with
+       ///      the reason code describing why the header is not valid, if and
+       ///      only if a problem is found with the data.
+       /// \returns  true if there is no problem with the header and false otherwise.
        
        // The block must have the correct type.
-       if (block.fHeader.fType != kClustersDataBlock) return false;
+       if (block.fHeader.fType != kClustersDataBlock)
+       {
+               if (reason != NULL) *reason = kHeaderContainsWrongType;
+               return false;
+       }
+       
        // The block's record width must be the correct size.
        if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONClusterStruct))
+       {
+               if (reason != NULL) *reason = kHeaderContainsWrongRecordWidth;
                return false;
+       }
+       
        return true;
 }
 
 
-bool AliHLTMUONUtils::HeaderOk(const AliHLTMUONChannelsBlockStruct& block)
+bool AliHLTMUONUtils::HeaderOk(
+               const AliHLTMUONChannelsBlockStruct& block,
+               WhyNotValid* reason
+       )
 {
-       ///
-       /// Methods used to check if the header information corresponds to the
-       /// supposed type of the data block.
-       ///
+       /// Method used to check if the header information corresponds to the
+       /// supposed type of the raw dHLT data block.
+       /// [in]  \param block  The data block to check.
+       /// [out] \param reason  If this is not NULL, then it will be filled with
+       ///      the reason code describing why the header is not valid, if and
+       ///      only if a problem is found with the data.
+       /// \returns  true if there is no problem with the header and false otherwise.
        
        // The block must have the correct type.
-       if (block.fHeader.fType != kChannelsDataBlock) return false;
+       if (block.fHeader.fType != kChannelsDataBlock)
+       {
+               if (reason != NULL) *reason = kHeaderContainsWrongType;
+               return false;
+       }
+       
        // The block's record width must be the correct size.
        if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONChannelStruct))
+       {
+               if (reason != NULL) *reason = kHeaderContainsWrongRecordWidth;
                return false;
+       }
+       
        return true;
 }
 
 
-bool AliHLTMUONUtils::HeaderOk(const AliHLTMUONMansoTracksBlockStruct& block)
+bool AliHLTMUONUtils::HeaderOk(
+               const AliHLTMUONMansoTracksBlockStruct& block,
+               WhyNotValid* reason
+       )
 {
-       ///
-       /// Methods used to check if the header information corresponds to the
-       /// supposed type of the data block.
-       ///
+       /// Method used to check if the header information corresponds to the
+       /// supposed type of the raw dHLT data block.
+       /// [in]  \param block  The data block to check.
+       /// [out] \param reason  If this is not NULL, then it will be filled with
+       ///      the reason code describing why the header is not valid, if and
+       ///      only if a problem is found with the data.
+       /// \returns  true if there is no problem with the header and false otherwise.
        
        // The block must have the correct type.
-       if (block.fHeader.fType != kMansoTracksDataBlock) return false;
+       if (block.fHeader.fType != kMansoTracksDataBlock)
+       {
+               if (reason != NULL) *reason = kHeaderContainsWrongType;
+               return false;
+       }
+       
        // The block's record width must be the correct size.
        if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONMansoTrackStruct))
+       {
+               if (reason != NULL) *reason = kHeaderContainsWrongRecordWidth;
                return false;
+       }
+       
        return true;
 }
 
 
-bool AliHLTMUONUtils::HeaderOk(const AliHLTMUONMansoCandidatesBlockStruct& block)
+bool AliHLTMUONUtils::HeaderOk(
+               const AliHLTMUONMansoCandidatesBlockStruct& block,
+               WhyNotValid* reason
+       )
 {
-       ///
-       /// Methods used to check if the header information corresponds to the
-       /// supposed type of the data block.
-       ///
+       /// Method used to check if the header information corresponds to the
+       /// supposed type of the raw dHLT data block.
+       /// [in]  \param block  The data block to check.
+       /// [out] \param reason  If this is not NULL, then it will be filled with
+       ///      the reason code describing why the header is not valid, if and
+       ///      only if a problem is found with the data.
+       /// \returns  true if there is no problem with the header and false otherwise.
        
        // The block must have the correct type.
-       if (block.fHeader.fType != kMansoCandidatesDataBlock) return false;
+       if (block.fHeader.fType != kMansoCandidatesDataBlock)
+       {
+               if (reason != NULL) *reason = kHeaderContainsWrongType;
+               return false;
+       }
+       
        // The block's record width must be the correct size.
        if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONMansoCandidateStruct))
+       {
+               if (reason != NULL) *reason = kHeaderContainsWrongRecordWidth;
                return false;
+       }
+       
        return true;
 }
 
 
-bool AliHLTMUONUtils::HeaderOk(const AliHLTMUONSinglesDecisionBlockStruct& block)
+bool AliHLTMUONUtils::HeaderOk(
+               const AliHLTMUONSinglesDecisionBlockStruct& block,
+               WhyNotValid* reason
+       )
 {
-       ///
-       /// Methods used to check if the header information corresponds to the
-       /// supposed type of the data block.
-       ///
+       /// Method used to check if the header information corresponds to the
+       /// supposed type of the raw dHLT data block.
+       /// [in]  \param block  The data block to check.
+       /// [out] \param reason  If this is not NULL, then it will be filled with
+       ///      the reason code describing why the header is not valid, if and
+       ///      only if a problem is found with the data.
+       /// \returns  true if there is no problem with the header and false otherwise.
        
        // The block must have the correct type.
-       if (block.fHeader.fType != kSinglesDecisionDataBlock) return false;
+       if (block.fHeader.fType != kSinglesDecisionDataBlock)
+       {
+               if (reason != NULL) *reason = kHeaderContainsWrongType;
+               return false;
+       }
+       
        // The block's record width must be the correct size.
        if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONTrackDecisionStruct))
+       {
+               if (reason != NULL) *reason = kHeaderContainsWrongRecordWidth;
                return false;
+       }
+       
        return true;
 }
 
 
-bool AliHLTMUONUtils::HeaderOk(const AliHLTMUONPairsDecisionBlockStruct& block)
+bool AliHLTMUONUtils::HeaderOk(
+               const AliHLTMUONPairsDecisionBlockStruct& block,
+               WhyNotValid* reason
+       )
 {
-       ///
-       /// Methods used to check if the header information corresponds to the
-       /// supposed type of the data block.
-       ///
+       /// Method used to check if the header information corresponds to the
+       /// supposed type of the raw dHLT data block.
+       /// [in]  \param block  The data block to check.
+       /// [out] \param reason  If this is not NULL, then it will be filled with
+       ///      the reason code describing why the header is not valid, if and
+       ///      only if a problem is found with the data.
+       /// \returns  true if there is no problem with the header and false otherwise.
        
        // The block must have the correct type.
-       if (block.fHeader.fType != kPairsDecisionDataBlock) return false;
+       if (block.fHeader.fType != kPairsDecisionDataBlock)
+       {
+               if (reason != NULL) *reason = kHeaderContainsWrongType;
+               return false;
+       }
+       
        // The block's record width must be the correct size.
        if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONPairDecisionStruct))
+       {
+               if (reason != NULL) *reason = kHeaderContainsWrongRecordWidth;
                return false;
+       }
+       
        return true;
 }
 
 
-bool AliHLTMUONUtils::IntegrityOk(const AliHLTMUONTriggerRecordStruct& tr)
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONTriggerRecordStruct& tr,
+               WhyNotValid* reason
+       )
 {
-       ///
-       /// Methods used to check more extensively if the integrity of various
-       /// types of data blocks are Ok and returns true in that case.
-       /// These can be slow and should generally only be used for debugging.
-       ///
+       /// This method is used to check more extensively if the integrity of the
+       /// trigger record structure is OK and returns true in that case.
+       /// [in] \param tr  The trigger record structure to check.
+       /// [out] \param reason  If this is not NULL, then it will be filled with
+       ///      the reason code describing why the structure is not valid, if and
+       ///      only if a problem is found with the data.
+       /// \returns  true if there is no problem with the structure and false otherwise.
        
        // Make sure that the reserved bits in the fFlags field are set
        // to zero.
-       if ((tr.fFlags & 0x3FFFFFF0) != 0) return false;
+       if ((tr.fFlags & 0x3FFFFFF0) != 0)
+       {
+               if (reason != NULL) *reason = kReservedBitsNotZero;
+               return false;
+       }
 
        // Make sure the sign is not invalid.
-       if ((tr.fFlags & 0xC0000000) == 3) return false;
+       if ((tr.fFlags & 0xC0000000) == 0xC0000000)
+       {
+               if (reason != NULL) *reason = kParticleSignBitsNotValid;
+               return false;
+       }
 
        // Check that fHit[i] is nil if the corresponding bit in the
        // flags word is zero.
        const AliHLTMUONRecHitStruct& nilhit
                = AliHLTMUONConstants::NilRecHitStruct();
-       if ((tr.fFlags & 0x1) == 0 and tr.fHit[0] != nilhit) return false;
-       if ((tr.fFlags & 0x2) == 0 and tr.fHit[1] != nilhit) return false;
-       if ((tr.fFlags & 0x4) == 0 and tr.fHit[2] != nilhit) return false;
-       if ((tr.fFlags & 0x8) == 0 and tr.fHit[3] != nilhit) return false;
+       if ( ((tr.fFlags & 0x1) == 0 and tr.fHit[0] != nilhit) or
+            ((tr.fFlags & 0x2) == 0 and tr.fHit[1] != nilhit) or
+            ((tr.fFlags & 0x4) == 0 and tr.fHit[2] != nilhit) or
+            ((tr.fFlags & 0x8) == 0 and tr.fHit[3] != nilhit)
+          )
+       {
+               if (reason != NULL) *reason = kHitNotMarkedAsNil;
+               return false;
+       }
 
        return true;
 }
 
 
-bool AliHLTMUONUtils::IntegrityOk(const AliHLTMUONTriggerRecordsBlockStruct& block)
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONTriggerRecordsBlockStruct& block,
+               WhyNotValid* reason,
+               AliHLTUInt32_t* recordNum
+       )
 {
-       ///
-       /// Methods used to check more extensively if the integrity of various
-       /// types of data blocks are Ok and returns true in that case.
-       /// These can be slow and should generally only be used for debugging.
-       ///
+       /// This method is used to check more extensively if the integrity of the
+       /// dHLT raw internal data block is OK and returns true in that case.
+       /// [in] \param block  The trigger record data block to check.
+       /// [out] \param reason  If this is not NULL, then it will be filled with
+       ///      the reason code describing why the data block is not valid, if and
+       ///      only if a problem is found with the data.
+       /// [out] \param recordNum  If this is not NULL, then it will be filled with
+       ///      the number of the trigger record that had a problem. This value will
+       ///      only contain a valid value if 'reason' contains one of:
+       ///        - kReservedBitsNotZero
+       ///        - kParticleSignBitsNotValid
+       ///        - kHitNotMarkedAsNil
+       /// \returns  true if there is no problem with the data and false otherwise.
        
-       if (not HeaderOk(block)) return false;
+       if (not HeaderOk(block, reason)) return false;
        
        const AliHLTMUONTriggerRecordStruct* triggerRecord =
                reinterpret_cast<const AliHLTMUONTriggerRecordStruct*>(&block + 1);
@@ -649,68 +878,95 @@ bool AliHLTMUONUtils::IntegrityOk(const AliHLTMUONTriggerRecordsBlockStruct& blo
                for (AliHLTUInt32_t j = i+1; i < block.fHeader.fNrecords; j++)
                {
                        if (id == triggerRecord[j].fId)
+                       {
+                               if (reason != NULL) *reason = kFoundDuplicateIDs;
                                return false;
+                       }
                }
        }
 
        // Check integrity of individual trigger records.
        for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
        {
-               if (not IntegrityOk(triggerRecord[i])) return false;
+               if (not IntegrityOk(triggerRecord[i], reason))
+               {
+                       if (recordNum != NULL) *recordNum = i;
+                       return false;
+               }
        }
 
        return true;
 }
 
 
-bool AliHLTMUONUtils::IntegrityOk(const AliHLTMUONTrigRecsDebugBlockStruct& block)
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONTrigRecsDebugBlockStruct& block,
+               WhyNotValid* reason
+       )
 {
-       ///
-       /// Methods used to check more extensively if the integrity of various
-       /// types of data blocks are Ok and returns true in that case.
-       /// These can be slow and should generally only be used for debugging.
-       ///
+       /// This method is used to check more extensively if the integrity of the
+       /// dHLT raw internal data block is OK and returns true in that case.
+       /// [in] \param block  The trigger record debugging information data block to check.
+       /// [out] \param reason  If this is not NULL, then it will be filled with
+       ///      the reason code describing why the data block is not valid, if and
+       ///      only if a problem is found with the data.
+       /// \returns  true if there is no problem with the data and false otherwise.
        
-       if (not HeaderOk(block)) return false;
+       if (not HeaderOk(block, reason)) return false;
        return true;
 }
 
 
-bool AliHLTMUONUtils::IntegrityOk(const AliHLTMUONTriggerChannelsBlockStruct& block)
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONTriggerChannelsBlockStruct& block,
+               WhyNotValid* reason
+       )
 {
-       ///
-       /// Methods used to check more extensively if the integrity of various
-       /// types of data blocks are Ok and returns true in that case.
-       /// These can be slow and should generally only be used for debugging.
-       ///
+       /// This method is used to check more extensively if the integrity of the
+       /// dHLT raw internal data block is OK and returns true in that case.
+       /// [in] \param block  The trigger channels data block to check.
+       /// [out] \param reason  If this is not NULL, then it will be filled with
+       ///      the reason code describing why the data block is not valid, if and
+       ///      only if a problem is found with the data.
+       /// \returns  true if there is no problem with the data and false otherwise.
        
-       if (not HeaderOk(block)) return false;
+       if (not HeaderOk(block, reason)) return false;
        return true;
 }
 
 
-bool AliHLTMUONUtils::IntegrityOk(const AliHLTMUONRecHitsBlockStruct& block)
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONRecHitsBlockStruct& block,
+               WhyNotValid* reason
+       )
 {
-       ///
-       /// Methods used to check more extensively if the integrity of various
-       /// types of data blocks are Ok and returns true in that case.
-       /// These can be slow and should generally only be used for debugging.
-       ///
+       /// This method is used to check more extensively if the integrity of the
+       /// dHLT raw internal data block is OK and returns true in that case.
+       /// [in] \param block  The reconstructed hits data block to check.
+       /// [out] \param reason  If this is not NULL, then it will be filled with
+       ///      the reason code describing why the data block is not valid, if and
+       ///      only if a problem is found with the data.
+       /// \returns  true if there is no problem with the data and false otherwise.
        
-       if (not HeaderOk(block)) return false;
+       if (not HeaderOk(block, reason)) return false;
        return true;
 }
 
 
-bool AliHLTMUONUtils::IntegrityOk(const AliHLTMUONClustersBlockStruct& block)
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONClustersBlockStruct& block,
+               WhyNotValid* reason
+       )
 {
-       ///
-       /// Methods used to check more extensively if the integrity of various
-       /// types of data blocks are Ok and returns true in that case.
-       /// These can be slow and should generally only be used for debugging.
-       ///
+       /// This method is used to check more extensively if the integrity of the
+       /// dHLT raw internal data block is OK and returns true in that case.
+       /// [in] \param block  The clusters data block to check.
+       /// [out] \param reason  If this is not NULL, then it will be filled with
+       ///      the reason code describing why the data block is not valid, if and
+       ///      only if a problem is found with the data.
+       /// \returns  true if there is no problem with the data and false otherwise.
        
-       if (not HeaderOk(block)) return false;
+       if (not HeaderOk(block, reason)) return false;
 
        const AliHLTMUONClusterStruct* cluster =
                reinterpret_cast<const AliHLTMUONClusterStruct*>(&block + 1);
@@ -722,7 +978,10 @@ bool AliHLTMUONUtils::IntegrityOk(const AliHLTMUONClustersBlockStruct& block)
                for (AliHLTUInt32_t j = i+1; i < block.fHeader.fNrecords; j++)
                {
                        if (id == cluster[j].fId)
+                       {
+                               if (reason != NULL) *reason = kFoundDuplicateIDs;
                                return false;
+                       }
                }
        }
        
@@ -730,187 +989,363 @@ bool AliHLTMUONUtils::IntegrityOk(const AliHLTMUONClustersBlockStruct& block)
 }
 
 
-bool AliHLTMUONUtils::IntegrityOk(const AliHLTMUONChannelsBlockStruct& block)
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONChannelsBlockStruct& block,
+               WhyNotValid* reason
+       )
 {
-       ///
-       /// Methods used to check more extensively if the integrity of various
-       /// types of data blocks are Ok and returns true in that case.
-       /// These can be slow and should generally only be used for debugging.
-       ///
+       /// This method is used to check more extensively if the integrity of the
+       /// dHLT raw internal data block is OK and returns true in that case.
+       /// [in] \param block  The ADC channels data block to check.
+       /// [out] \param reason  If this is not NULL, then it will be filled with
+       ///      the reason code describing why the data block is not valid, if and
+       ///      only if a problem is found with the data.
+       /// \returns  true if there is no problem with the data and false otherwise.
        
-       if (not HeaderOk(block)) return false;
+       if (not HeaderOk(block, reason)) return false;
        return true;
 }
 
 
-bool AliHLTMUONUtils::IntegrityOk(const AliHLTMUONMansoTrackStruct& track)
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONMansoTrackStruct& track,
+               WhyNotValid* reason
+       )
 {
-       ///
-       /// Methods used to check more extensively if the integrity of various
-       /// types of data blocks are Ok and returns true in that case.
-       /// These can be slow and should generally only be used for debugging.
-       ///
+       /// This method is used to check more extensively if the integrity of the
+       /// Manso track structure is OK and returns true in that case.
+       /// [in] \param track  The track structure to check.
+       /// [out] \param reason  If this is not NULL, then it will be filled with
+       ///      the reason code describing why the structure is not valid, if and
+       ///      only if a problem is found with the data.
+       /// \returns  true if there is no problem with the structure and false otherwise.
        
        // Make sure that the reserved bits in the fFlags field are set
        // to zero.
-       if ((track.fFlags & 0x3FFFFFF0) != 0) return false;
+       if ((track.fFlags & 0x3FFFFFF0) != 0)
+       {
+               if (reason != NULL) *reason = kReservedBitsNotZero;
+               return false;
+       }
 
        // Make sure the sign is not invalid.
-       if ((track.fFlags & 0xC0000000) == 0xC0000000) return false;
+       if ((track.fFlags & 0xC0000000) == 0xC0000000)
+       {
+               if (reason != NULL) *reason = kParticleSignBitsNotValid;
+               return false;
+       }
 
        // Check that fHit[i] is nil if the corresponding bit in the
        // flags word is zero.
        const AliHLTMUONRecHitStruct& nilhit
                = AliHLTMUONConstants::NilRecHitStruct();
-       if ((track.fFlags & 0x1) == 0 and track.fHit[0] != nilhit) return false;
-       if ((track.fFlags & 0x2) == 0 and track.fHit[1] != nilhit) return false;
-       if ((track.fFlags & 0x4) == 0 and track.fHit[2] != nilhit) return false;
-       if ((track.fFlags & 0x8) == 0 and track.fHit[3] != nilhit) return false;
+       if ( ((track.fFlags & 0x1) == 0 and track.fHit[0] != nilhit) or
+            ((track.fFlags & 0x2) == 0 and track.fHit[1] != nilhit) or
+            ((track.fFlags & 0x4) == 0 and track.fHit[2] != nilhit) or
+            ((track.fFlags & 0x8) == 0 and track.fHit[3] != nilhit)
+          )
+       {
+               if (reason != NULL) *reason = kHitNotMarkedAsNil;
+               return false;
+       }
        
        return true;
 }
 
 
-bool AliHLTMUONUtils::IntegrityOk(const AliHLTMUONMansoTracksBlockStruct& block)
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONMansoTracksBlockStruct& block,
+               WhyNotValid* reason,
+               AliHLTUInt32_t* recordNum
+       )
 {
-       ///
-       /// Methods used to check more extensively if the integrity of various
-       /// types of data blocks are Ok and returns true in that case.
-       /// These can be slow and should generally only be used for debugging.
-       ///
+       /// This method is used to check more extensively if the integrity of the
+       /// dHLT raw internal data block is OK and returns true in that case.
+       /// [in] \param block  The Manso track data block to check.
+       /// [out] \param reason  If this is not NULL, then it will be filled with
+       ///      the reason code describing why the data block is not valid, if and
+       ///      only if a problem is found with the data.
+       /// [out] \param recordNum  If this is not NULL, then it will be filled with
+       ///      the number of the track that had a problem. This value will only
+       ///      contain a valid value if 'reason' contains one of:
+       ///        - kReservedBitsNotZero
+       ///        - kParticleSignBitsNotValid
+       ///        - kHitNotMarkedAsNil
+       /// \returns  true if there is no problem with the data and false otherwise.
        
-       if (not HeaderOk(block)) return false;
+       if (not HeaderOk(block, reason)) return false;
 
        const AliHLTMUONMansoTrackStruct* track =
                reinterpret_cast<const AliHLTMUONMansoTrackStruct*>(&block + 1);
        
-       // Check if any ID is duplicated.
+       // Check if any track ID is duplicated.
        for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
        {
                AliHLTInt32_t id = track[i].fId;
                for (AliHLTUInt32_t j = i+1; i < block.fHeader.fNrecords; j++)
                {
                        if (id == track[j].fId)
+                       {
+                               if (reason != NULL) *reason = kFoundDuplicateIDs;
                                return false;
+                       }
                }
        }
 
        // Check that the tracks have integrity.
        for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
        {
-               if (not IntegrityOk(track[i])) return false;
+               if (not IntegrityOk(track[i], reason))
+               {
+                       if (recordNum != NULL) *recordNum = i;
+                       return false;
+               }
        }
 
        return true;
 }
 
 
-bool AliHLTMUONUtils::IntegrityOk(const AliHLTMUONMansoCandidatesBlockStruct& block)
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONMansoCandidatesBlockStruct& block,
+               WhyNotValid* reason,
+               AliHLTUInt32_t* recordNum
+       )
 {
-       ///
-       /// Methods used to check more extensively if the integrity of various
-       /// types of data blocks are Ok and returns true in that case.
-       /// These can be slow and should generally only be used for debugging.
-       ///
+       /// This method is used to check more extensively if the integrity of the
+       /// dHLT raw internal data block is OK and returns true in that case.
+       /// [in] \param block  The Manso track candidate data block to check.
+       /// [out] \param reason  If this is not NULL, then it will be filled with
+       ///      the reason code describing why the data block is not valid, if and
+       ///      only if a problem is found with the data.
+       /// [out] \param recordNum  If this is not NULL, then it will be filled with
+       ///      the number of the track candidate that had a problem. This value will
+       ///      only contain a valid value if 'reason' contains one of:
+       ///        - kReservedBitsNotZero
+       ///        - kParticleSignBitsNotValid
+       ///        - kHitNotMarkedAsNil
+       /// \returns  true if there is no problem with the data and false otherwise.
        
-       if (not HeaderOk(block)) return false;
+       if (not HeaderOk(block, reason)) return false;
 
        const AliHLTMUONMansoCandidateStruct* candidate =
                reinterpret_cast<const AliHLTMUONMansoCandidateStruct*>(&block + 1);
        
+       // Check if any candidate track ID is duplicated.
+       for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
+       {
+               AliHLTInt32_t id = candidate[i].fTrack.fId;
+               for (AliHLTUInt32_t j = i+1; i < block.fHeader.fNrecords; j++)
+               {
+                       if (id == candidate[j].fTrack.fId)
+                       {
+                               if (reason != NULL) *reason = kFoundDuplicateIDs;
+                               return false;
+                       }
+               }
+       }
+       
        // Check that the tracks have integrity.
        for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
        {
-               if (not IntegrityOk(candidate[i].fTrack)) return false;
+               if (not IntegrityOk(candidate[i].fTrack, reason))
+               {
+                       if (recordNum != NULL) *recordNum = i;
+                       return false;
+               }
        }
        
        return true;
 }
 
 
-bool AliHLTMUONUtils::IntegrityOk(const AliHLTMUONTrackDecisionStruct& decision)
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONTrackDecisionStruct& decision,
+               WhyNotValid* reason
+       )
 {
-       ///
-       /// Methods used to check more extensively if the integrity of various
-       /// types of data blocks are Ok and returns true in that case.
-       /// These can be slow and should generally only be used for debugging.
-       ///
+       /// This method is used to check more extensively if the integrity of the
+       /// single track trigger decision structure is OK and returns true in that case.
+       /// [in] \param decision  The trigger decision structure to check.
+       /// [out] \param reason  If this is not NULL, then it will be filled with
+       ///      the reason code describing why the structure is not valid, if and
+       ///      only if a problem is found with the data.
+       /// \returns  true if there is no problem with the structure and false otherwise.
        
        // Make sure that the reserved bits in the fTriggerBits field are set
        // to zero.
-       if ((decision.fTriggerBits & 0xFFFFFFFC) != 0) return false;
+       if ((decision.fTriggerBits & 0xFFFFFFFC) != 0)
+       {
+               if (reason != NULL) *reason = kReservedBitsNotZero;
+               return false;
+       }
+       
+       // The pT should be -1 or a positive number.
+       if (decision.fPt != -1. and decision.fPt < 0.)
+       {
+               if (reason != NULL) *reason = kPtValueNotValid;
+               return false;
+       }
+       
        return true;
 }
 
 
-bool AliHLTMUONUtils::IntegrityOk(const AliHLTMUONSinglesDecisionBlockStruct& block)
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONSinglesDecisionBlockStruct& block,
+               WhyNotValid* reason,
+               AliHLTUInt32_t* recordNum
+       )
 {
-       ///
-       /// Methods used to check more extensively if the integrity of various
-       /// types of data blocks are Ok and returns true in that case.
-       /// These can be slow and should generally only be used for debugging.
-       ///
+       /// This method is used to check more extensively if the integrity of the
+       /// dHLT raw internal data block is OK and returns true in that case.
+       /// [in] \param block  The single track trigger decision data block to check.
+       /// [out] \param reason  If this is not NULL, then it will be filled with
+       ///      the reason code describing why the data block is not valid, if and
+       ///      only if a problem is found with the data.
+       /// [out] \param recordNum  If this is not NULL, then it will be filled with
+       ///      the number of the trigger decisions that had a problem. This value will
+       ///      only contain a valid value if 'reason' contains one of:
+       ///        - kReservedBitsNotZero
+       ///        - kPtValueNotValid
+       /// \returns  true if there is no problem with the data and false otherwise.
        
-       if (not HeaderOk(block)) return false;
+       if (not HeaderOk(block, reason)) return false;
        
        const AliHLTMUONTrackDecisionStruct* decision =
                reinterpret_cast<const AliHLTMUONTrackDecisionStruct*>(&block + 1);
 
+       // Check that there are no duplicate trigger entries.
+       for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
+       {
+               AliHLTInt32_t id = decision[i].fTrackId;
+               for (AliHLTUInt32_t j = i+1; i < block.fHeader.fNrecords; j++)
+               {
+                       if (id == decision[j].fTrackId)
+                       {
+                               if (reason != NULL) *reason = kFoundDuplicateTriggers;
+                               return false;
+                       }
+               }
+       }
+       
        // Check that the trigger bits for each track have integrity.
        for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
        {
-               if (not IntegrityOk(decision[i])) return false;
+               if (not IntegrityOk(decision[i], reason))
+               {
+                       if (recordNum != NULL) *recordNum = i;
+                       return false;
+               }
        }
        
        return true;
 }
 
 
-bool AliHLTMUONUtils::IntegrityOk(const AliHLTMUONPairDecisionStruct& decision)
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONPairDecisionStruct& decision,
+               WhyNotValid* reason
+       )
 {
-       ///
-       /// Methods used to check more extensively if the integrity of various
-       /// types of data blocks are Ok and returns true in that case.
-       /// These can be slow and should generally only be used for debugging.
-       ///
+       /// This method is used to check more extensively if the integrity of the
+       /// track pair trigger decision structure is OK and returns true in that case.
+       /// [in] \param decision  The trigger decision structure to check.
+       /// [out] \param reason  If this is not NULL, then it will be filled with
+       ///      the reason code describing why the structure is not valid, if and
+       ///      only if a problem is found with the data.
+       /// \returns  true if there is no problem with the structure and false otherwise.
        
        // Make sure that the reserved bits in the fTriggerBits field are set
        // to zero.
-       if ((decision.fTriggerBits & 0xFFFFFF80) != 0) return false;
+       if ((decision.fTriggerBits & 0xFFFFFF80) != 0)
+       {
+               if (reason != NULL) *reason = kReservedBitsNotZero;
+               return false;
+       }
        
-       // The high mass or low mass bits can only be set if unlike bit is set.
-       if ((decision.fTriggerBits & 0x00000010) == 0
-           and (decision.fTriggerBits & 0x00000060) != 0
-          )
+       // Check that the track IDs are not the same.
+       if (decision.fTrackAId == decision.fTrackBId)
+       {
+               if (reason != NULL) *reason = kPairTrackIdsAreIdentical;
+               return false;
+       }
+       
+       // The invariant mass should be -1 or a positive number.
+       if (decision.fInvMass != -1. and decision.fInvMass < 0.)
+       {
+               if (reason != NULL) *reason = kMassValueNotValid;
                return false;
+       }
        
        // Neither the high pt (hipt) or low pt (lopt) count bits can be > 2.
-       // And the sum must not be > 2.
        AliHLTUInt8_t lowPtCount = (decision.fTriggerBits & 0x00000003);
        AliHLTUInt8_t highPtCount = (decision.fTriggerBits & 0x0000000C) >> 2;
-       if (lowPtCount + highPtCount > 2) return false;
+       if (lowPtCount > 2)
+       {
+               if (reason != NULL) *reason = kLowPtCountInvalid;
+               return false;
+       }
+       if (highPtCount > 2)
+       {
+               if (reason != NULL) *reason = kHighPtCountInvalid;
+               return false;
+       }
        
        return true;
 }
 
 
-bool AliHLTMUONUtils::IntegrityOk(const AliHLTMUONPairsDecisionBlockStruct& block)
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONPairsDecisionBlockStruct& block,
+               WhyNotValid* reason,
+               AliHLTUInt32_t* recordNum
+       )
 {
-       ///
-       /// Methods used to check more extensively if the integrity of various
-       /// types of data blocks are Ok and returns true in that case.
-       /// These can be slow and should generally only be used for debugging.
-       ///
+       /// This method is used to check more extensively if the integrity of the
+       /// dHLT raw internal data block is OK and returns true in that case.
+       /// [in] \param block  The track pair trigger decision data block to check.
+       /// [out] \param reason  If this is not NULL, then it will be filled with
+       ///      the reason code describing why the data block is not valid, if and
+       ///      only if a problem is found with the data.
+       /// [out] \param recordNum  If this is not NULL, then it will be filled with
+       ///      the number of the trigger decisions that had a problem. This value will
+       ///      only contain a valid value if 'reason' contains one of:
+       ///        - kReservedBitsNotZero
+       ///        - kPairTrackIdsAreIdentical
+       ///        - kMassValueNotValid
+       ///        - kLowPtCountInvalid
+       ///        - kHighPtCountInvalid
+       /// \returns  true if there is no problem with the data and false otherwise.
        
-       if (not HeaderOk(block)) return false;
+       if (not HeaderOk(block, reason)) return false;
 
        const AliHLTMUONPairDecisionStruct* decision =
                reinterpret_cast<const AliHLTMUONPairDecisionStruct*>(&block + 1);
        
+       // Check that there are no duplicate trigger entries.
+       for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
+       {
+               AliHLTInt32_t ta = decision[i].fTrackAId;
+               AliHLTInt32_t tb = decision[i].fTrackBId;
+               for (AliHLTUInt32_t j = i+1; i < block.fHeader.fNrecords; j++)
+               {
+                       if (ta == decision[j].fTrackAId and tb == decision[j].fTrackBId)
+                       {
+                               if (reason != NULL) *reason = kFoundDuplicateTriggers;
+                               return false;
+                       }
+               }
+       }
+       
        // Check that the trigger bits for each track pair have integrity.
        for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
        {
-               if (not IntegrityOk(decision[i])) return false;
+               if (not IntegrityOk(decision[i], reason))
+               {
+                       if (recordNum != NULL) *recordNum = i;
+                       return false;
+               }
        }
        
        return true;
index ff70c267ff74766cbb26c7f0c339747ae4645d42..648d906623ff49ca4444698b16a56210db6b917b 100644 (file)
@@ -13,6 +13,7 @@
 ///
 
 #include "AliHLTMUONDataTypes.h"
+#include <ostream>
 
 // Forward declare structures.
 extern "C" {
@@ -283,48 +284,94 @@ public:
         */
        enum WhyNotValid
        {
-               kNoReason,
-               kHeaderContainsWrongType,
-               kHeaderContainsWrongRecordWidth
+               kNoReason,   ///< There was no reason for failure.
+               kHeaderContainsWrongType,  ///< The common header contains an incorrect type ID.
+               kHeaderContainsWrongRecordWidth,  ///< The common header contains an incorrect data record width.
+               kReservedBitsNotZero,  ///< Reserved bits have not been set to zero.
+               kParticleSignBitsNotValid,  ///< The particle sign bits are not a valid value.
+               kHitNotMarkedAsNil,  ///< A hit was marked as not found, but the corresponding hit structure was not set to nil.
+               kFoundDuplicateIDs,  ///< Found duplicate identifiers, but they should all be unique.
+               kPtValueNotValid,  ///< The pT value is not positive nor -1 indicating an invalid value.
+               kFoundDuplicateTriggers,  ///< Found duplicate trigger decisions.
+               kPairTrackIdsAreIdentical,  ///< The track IDs of the track pair are identical.
+               kMassValueNotValid,  ///< The invariant mass value is not positive nor -1 indicating an invalid value.
+               kLowPtCountInvalid,  ///< The low pT trigger count is greater than 2, which is invalid.
+               kHighPtCountInvalid  ///< The high pT trigger count is greater than 2, which is invalid.
        };
+       
+       /**
+        * This method converts the WhyNotValid enumeration to a string representation.
+        */
+       static const char* FailureReasonToString(WhyNotValid reason);
+       
+       /**
+        * This method returns a string containing a user readable message explaining
+        * the reason for failure described by the WhyNotValid enumeration.
+        */
+       static const char* FailureReasonToMessage(WhyNotValid reason);
 
        /**
         * Methods used to check if the header information corresponds to the
         * supposed type of the data block.
         * If the 'reason' parameter is not NULL then these methods will fill the
-        * memory pointed to by reason with a code describing of why the header
-        * is not valid, if and only if a problem is found with the data.
+        * memory pointed to by reason with a code describing why the header is
+        * not valid, if and only if a problem is found with the data.
+        * These methods will return either kHeaderContainsWrongType or
+        * kHeaderContainsWrongRecordWidth as the reason.
         */
        static bool HeaderOk(const AliHLTMUONTriggerRecordsBlockStruct& block, WhyNotValid* reason = NULL);
-       static bool HeaderOk(const AliHLTMUONTrigRecsDebugBlockStruct& block);
-       static bool HeaderOk(const AliHLTMUONTriggerChannelsBlockStruct& block);
-       static bool HeaderOk(const AliHLTMUONRecHitsBlockStruct& block);
-       static bool HeaderOk(const AliHLTMUONClustersBlockStruct& block);
-       static bool HeaderOk(const AliHLTMUONChannelsBlockStruct& block);
-       static bool HeaderOk(const AliHLTMUONMansoTracksBlockStruct& block);
-       static bool HeaderOk(const AliHLTMUONMansoCandidatesBlockStruct& block);
-       static bool HeaderOk(const AliHLTMUONSinglesDecisionBlockStruct& block);
-       static bool HeaderOk(const AliHLTMUONPairsDecisionBlockStruct& block);
+       static bool HeaderOk(const AliHLTMUONTrigRecsDebugBlockStruct& block, WhyNotValid* reason = NULL);
+       static bool HeaderOk(const AliHLTMUONTriggerChannelsBlockStruct& block, WhyNotValid* reason = NULL);
+       static bool HeaderOk(const AliHLTMUONRecHitsBlockStruct& block, WhyNotValid* reason = NULL);
+       static bool HeaderOk(const AliHLTMUONClustersBlockStruct& block, WhyNotValid* reason = NULL);
+       static bool HeaderOk(const AliHLTMUONChannelsBlockStruct& block, WhyNotValid* reason = NULL);
+       static bool HeaderOk(const AliHLTMUONMansoTracksBlockStruct& block, WhyNotValid* reason = NULL);
+       static bool HeaderOk(const AliHLTMUONMansoCandidatesBlockStruct& block, WhyNotValid* reason = NULL);
+       static bool HeaderOk(const AliHLTMUONSinglesDecisionBlockStruct& block, WhyNotValid* reason = NULL);
+       static bool HeaderOk(const AliHLTMUONPairsDecisionBlockStruct& block, WhyNotValid* reason = NULL);
 
        /**
         * Methods used to check more extensively if the integrity of various
         * types of data blocks are Ok and returns true in that case.
         * These can be slow and should generally only be used for debugging.
         */
-       static bool IntegrityOk(const AliHLTMUONTriggerRecordStruct& tr);
-       static bool IntegrityOk(const AliHLTMUONTriggerRecordsBlockStruct& block);
-       static bool IntegrityOk(const AliHLTMUONTrigRecsDebugBlockStruct& block);
-       static bool IntegrityOk(const AliHLTMUONTriggerChannelsBlockStruct& block);
-       static bool IntegrityOk(const AliHLTMUONRecHitsBlockStruct& block);
-       static bool IntegrityOk(const AliHLTMUONClustersBlockStruct& block);
-       static bool IntegrityOk(const AliHLTMUONChannelsBlockStruct& block);
-       static bool IntegrityOk(const AliHLTMUONMansoTrackStruct& track);
-       static bool IntegrityOk(const AliHLTMUONMansoTracksBlockStruct& block);
-       static bool IntegrityOk(const AliHLTMUONMansoCandidatesBlockStruct& block);
-       static bool IntegrityOk(const AliHLTMUONTrackDecisionStruct& decision);
-       static bool IntegrityOk(const AliHLTMUONSinglesDecisionBlockStruct& block);
-       static bool IntegrityOk(const AliHLTMUONPairDecisionStruct& decision);
-       static bool IntegrityOk(const AliHLTMUONPairsDecisionBlockStruct& block);
+       static bool IntegrityOk(const AliHLTMUONTriggerRecordStruct& tr, WhyNotValid* reason = NULL);
+       
+       static bool IntegrityOk(
+                       const AliHLTMUONTriggerRecordsBlockStruct& block,
+                       WhyNotValid* reason = NULL, AliHLTUInt32_t* recordNum = NULL
+               );
+               
+       static bool IntegrityOk(const AliHLTMUONTrigRecsDebugBlockStruct& block, WhyNotValid* reason = NULL);
+       static bool IntegrityOk(const AliHLTMUONTriggerChannelsBlockStruct& block, WhyNotValid* reason = NULL);
+       static bool IntegrityOk(const AliHLTMUONRecHitsBlockStruct& block, WhyNotValid* reason = NULL);
+       static bool IntegrityOk(const AliHLTMUONClustersBlockStruct& block, WhyNotValid* reason = NULL);
+       static bool IntegrityOk(const AliHLTMUONChannelsBlockStruct& block, WhyNotValid* reason = NULL);
+       static bool IntegrityOk(const AliHLTMUONMansoTrackStruct& track, WhyNotValid* reason = NULL);
+       
+       static bool IntegrityOk(
+                       const AliHLTMUONMansoTracksBlockStruct& block,
+                       WhyNotValid* reason = NULL, AliHLTUInt32_t* recordNum = NULL
+               );
+       
+       static bool IntegrityOk(
+                       const AliHLTMUONMansoCandidatesBlockStruct& block,
+                       WhyNotValid* reason = NULL, AliHLTUInt32_t* recordNum = NULL
+               );
+       
+       static bool IntegrityOk(const AliHLTMUONTrackDecisionStruct& decision, WhyNotValid* reason = NULL);
+       
+       static bool IntegrityOk(
+                       const AliHLTMUONSinglesDecisionBlockStruct& block,
+                       WhyNotValid* reason = NULL, AliHLTUInt32_t* recordNum = NULL
+               );
+       
+       static bool IntegrityOk(const AliHLTMUONPairDecisionStruct& decision, WhyNotValid* reason = NULL);
+       
+       static bool IntegrityOk(
+                       const AliHLTMUONPairsDecisionBlockStruct& block,
+                       WhyNotValid* reason = NULL, AliHLTUInt32_t* recordNum = NULL
+               );
 
 private:
        // Should never have to create or destroy this object.
@@ -334,6 +381,18 @@ private:
 
 //_____________________________________________________________________________
 
+inline std::ostream& operator << (std::ostream& stream, AliHLTMUONUtils::WhyNotValid reason)
+{
+       /// Stream operator for the WhyNotValid enumeration for usage with
+       /// std::ostream classes. Allows usages such as:
+       /// AliHLTMUONUtils::WhyNotValid r; std::cout << r;
+       
+       stream << AliHLTMUONUtils::FailureReasonToString(reason);
+       return stream;
+}
+
+//_____________________________________________________________________________
+
 // Since c++ is missing a finally "keyword" we define one. Its usage is identical
 // to a try..finally statement in Java etc.. however, since it is officialy a macro
 // one must use the ( ) brackets instead of { }
@@ -350,16 +409,6 @@ private:
                code
 #endif // __BORLANDC__
 
-// If we do not already have them, then define logical operators that are easier
-// to read. 'and' = &&, 'or' = ||, 'not' = !
-#if ! defined(__GNUC__) && ! defined(__CINT__)
-// TODO: Should use iso646.h
-#      define and &&
-#      define or ||
-#      define not !
-#endif // __GNUC__ | __CINT__
-
-
 // Here we define the DebugTrace(message) macro for easy embedding of debug
 // information into the dimuon HLT code. Its usage is meant to be for generating
 // traces of the program which are only useful during full scale debugging.
index 7d4617d22c0cf2a24b006e9ac3baeace733f57ed..1cfe02787ebc53ecd1307268acb92a8a231f49ca 100644 (file)
@@ -70,7 +70,6 @@ AliHLTMUONHitReconstructor::AliHLTMUONHitReconstructor() :
        fNofBChannel(NULL),
        fNofNBChannel(NULL),
        fNofFiredDetElem(0),
-       //fDebugLevel(0),  //TODO: remove
        fIdToEntry()
 {
        /// Default constructor
@@ -85,7 +84,7 @@ AliHLTMUONHitReconstructor::AliHLTMUONHitReconstructor() :
        }
        catch (const std::bad_alloc&)
        {
-               HLTError("Dynamic memory allocation failed for AliHLTMUONHitReconstructor::fPadData in constructor.");
+               HLTError("Dynamic memory allocation failed for fPadData in constructor.");
                throw;
        }
        
@@ -160,7 +159,6 @@ bool AliHLTMUONHitReconstructor::Run(
 
   if (not FindRecHits()) {
     HLTError("Failed to generate RecHits");
-    Clear();
     return false;
   }
 
@@ -198,81 +196,140 @@ bool AliHLTMUONHitReconstructor::DecodeDDL(const AliHLTUInt32_t* rawData,AliHLTU
 
 bool AliHLTMUONHitReconstructor::FindRecHits()
 {
-  // fuction that calls hit reconstruction detector element-wise   
+  // fuction that calls hit reconstruction detector element-wise.
+
+  assert( fCentralChargeB == NULL );
+  assert( fCentralChargeNB == NULL );
+  assert( fRecX == NULL );
+  assert( fRecY == NULL );
+  assert( fAvgChargeX == NULL );
+  assert( fAvgChargeY == NULL );
+  assert( fNofBChannel == NULL );
+  assert( fNofNBChannel == NULL );
+  
+  bool resultOk = false;
 
-  for(int iDet=0; iDet<fNofFiredDetElem ; iDet++){
-    
-    fCentralCountB = 0 ;
-    fCentralCountNB = 0 ;
+  for(int iDet=0; iDet<fNofFiredDetElem ; iDet++)
+  {
+    fCentralCountB = 0;
+    fCentralCountNB = 0;
 
-    
-    try{
+    try
+    {
       fCentralChargeB = new int[fMaxFiredPerDetElem[iDet]];
+      HLTDebug("Allocated fCentralChargeB with %d elements.", fMaxFiredPerDetElem[iDet]);
       fCentralChargeNB = new int[fMaxFiredPerDetElem[iDet]];
+      HLTDebug("Allocated fCentralChargeNB with %d elements.", fMaxFiredPerDetElem[iDet]);
+      resultOk = true;
     }
-    catch(const std::bad_alloc&){
-      HLTError("Dynamic memory allocation failed for AliHLTMUONHitReconstructor::fCentralChargeNB and fCentralChargeB");
-      return false;
+    catch(const std::bad_alloc&)
+    {
+      HLTError("Dynamic memory allocation failed for fCentralChargeNB and fCentralChargeB");
+      resultOk = false;
     }
 
-    if(iDet>0)
-      FindCentralHits(fMaxFiredPerDetElem[iDet-1],fMaxFiredPerDetElem[iDet]);
-    else
-      FindCentralHits(1,fMaxFiredPerDetElem[iDet]); // minimum value is 1 because dataCount in ReadDDL starts from 1 instead of 0;
-
-    if(!RecXRecY()){
-      HLTError("Failed to find RecX and RecY hits\n");
-      return false;
+    // Continue processing, but check if everything is OK as we do, otherwise
+    // do not execute the next steps.
+    if (resultOk)
+    {
+      if(iDet>0)
+        FindCentralHits(fMaxFiredPerDetElem[iDet-1],fMaxFiredPerDetElem[iDet]);
+      else
+        // minimum value is 1 because dataCount in ReadDDL starts from 1 instead of 0;
+        FindCentralHits(1,fMaxFiredPerDetElem[iDet]);
+
+      try
+      {
+        fRecY = new float[fCentralCountB];
+        HLTDebug("Allocated fRecY with %d elements.", fCentralCountB);
+        fRecX = new float[fCentralCountNB];
+        HLTDebug("Allocated fRecX with %d elements.", fCentralCountNB);
+        fAvgChargeY = new float[fCentralCountB];
+        HLTDebug("Allocated fAvgChargeY with %d elements.", fCentralCountB);
+        fAvgChargeX = new float[fCentralCountNB];
+        HLTDebug("Allocated fAvgChargeX with %d elements.", fCentralCountNB);
+        fNofBChannel = new int[fCentralCountB];
+        HLTDebug("Allocated fNofBChannel with %d elements.", fCentralCountB);
+        fNofNBChannel = new int[fCentralCountNB];
+        HLTDebug("Allocated fNofNBChannel with %d elements.", fCentralCountNB);
+        resultOk = true;
+      }
+      catch(const std::bad_alloc&){
+        HLTError("Dynamic memory allocation failed for internal arrays.");
+        resultOk = false;
+      }
     }
 
-
-    if(!MergeRecHits()){
-      HLTError("Failed to merge hits\n");
-      return false;
+    if (resultOk) RecXRecY();
+    if (resultOk)
+    {
+      resultOk = MergeRecHits();
+    }
+    if (resultOk)
+    {
+      if(iDet==0)
+        // minimum value in loop is 1 because dataCount in ReadDDL starts from 1 instead of 0;
+        for(int i=1;i<fMaxFiredPerDetElem[iDet];i++)
+          fGetIdTotalData[fPadData[i].fIX][fPadData[i].fIY][fPadData[i].fPlane] = 0;
+      else
+        for(int i=fMaxFiredPerDetElem[iDet-1];i<fMaxFiredPerDetElem[iDet];i++)
+          fGetIdTotalData[fPadData[i].fIX][fPadData[i].fIY][fPadData[i].fPlane] = 0;
     }
 
-
-    if(iDet==0)
-      for(int i=1;i<fMaxFiredPerDetElem[iDet];i++) // minimum value is 1 because dataCount in ReadDDL starts from 1 instead of 0;
-       fGetIdTotalData[fPadData[i].fIX][fPadData[i].fIY][fPadData[i].fPlane] = 0;
-    else
-      for(int i=fMaxFiredPerDetElem[iDet-1];i<fMaxFiredPerDetElem[iDet];i++)
-       fGetIdTotalData[fPadData[i].fIX][fPadData[i].fIY][fPadData[i].fPlane] = 0;
-
-
-
-    if(fCentralChargeB){
-      delete []fCentralChargeB;
+    // Make sure to release any memory that was allocated.
+    if (fCentralChargeB != NULL)
+    {
+      delete [] fCentralChargeB;
+      HLTDebug("Released fCentralChargeB array.");
       fCentralChargeB = NULL;
     }
-    
-    if(fCentralChargeNB){
-      delete []fCentralChargeNB;
+    if (fCentralChargeNB != NULL)
+    {
+      delete [] fCentralChargeNB;
+      HLTDebug("Released fCentralChargeNB array.");
       fCentralChargeNB = NULL;
     }
-
-
+    if (fRecX != NULL)
+    {
+      delete [] fRecX;
+      HLTDebug("Released fRecX array.");
+      fRecX = NULL;
+    }
+    if (fRecY != NULL)
+    {
+      delete [] fRecY;
+      HLTDebug("Released fRecY array.");
+      fRecY = NULL;
+    }
+    if (fAvgChargeX != NULL)
+    {
+      delete [] fAvgChargeX;
+      HLTDebug("Released fAvgChargeX array.");
+      fAvgChargeX = NULL;
+    }
+    if (fAvgChargeY != NULL)
+    {
+      delete [] fAvgChargeY;
+      HLTDebug("Released fAvgChargeY array.");
+      fAvgChargeY = NULL;
+    }
+    if (fNofBChannel != NULL)
+    {
+      delete [] fNofBChannel;
+      HLTDebug("Released fNofBChannel array.");
+      fNofBChannel = NULL;
+    }
+    if (fNofNBChannel != NULL)
+    {
+      delete [] fNofNBChannel;
+      HLTDebug("Released fNofNBChannel array.");
+      fNofNBChannel = NULL;
+    }
   }
 
-  for(int iPad=1;iPad<fDigitPerDDL;iPad++){
-    fGetIdTotalData[fPadData[iPad].fIX][fPadData[iPad].fIY][fPadData[iPad].fPlane] = 0;
-    fPadData[iPad].fDetElemId = 0;
-    fPadData[iPad].fIX = 0 ;
-    fPadData[iPad].fIY = 0 ;
-    fPadData[iPad].fRealX = 0.0 ;
-    fPadData[iPad].fRealY = 0.0 ;
-    fPadData[iPad].fRealZ = 0.0 ;
-    fPadData[iPad].fHalfPadSize = 0.0 ;
-    fPadData[iPad].fPlane = -1 ;
-    fPadData[iPad].fCharge = 0 ;
-  }  
-  
-  for(int i=0;i<13;i++)
-    fMaxFiredPerDetElem[i] = 0;
-
-  Clear();
+  Clear();  // clear internal arrays.
 
-  return true;
+  return resultOk;
 }
 
 
@@ -280,6 +337,9 @@ void AliHLTMUONHitReconstructor::FindCentralHits(int minPadId, int maxPadId)
 {
   // to find central hit associated with each cluster
 
+  assert( fCentralChargeB != NULL );
+  assert( fCentralChargeNB != NULL );
+
   int b,nb;
   int idManuChannelCentral;
   bool hasFind;
@@ -371,30 +431,23 @@ void AliHLTMUONHitReconstructor::FindCentralHits(int minPadId, int maxPadId)
 }
 
 
-bool AliHLTMUONHitReconstructor::RecXRecY()
+void AliHLTMUONHitReconstructor::RecXRecY()
 {
   // find reconstructed X and Y for each plane separately
+
+  assert( fRecX != NULL );
+  assert( fRecY != NULL );
+  assert( fAvgChargeX != NULL );
+  assert( fAvgChargeY != NULL );
+  assert( fNofBChannel != NULL );
+  assert( fNofNBChannel != NULL );
+
   int b,nb;
   int idCentral;
   int idLower = 0;
   int idUpper = 0;
   int idRight = 0;
   int idLeft = 0;
-
-  try{
-    fRecY = new float[fCentralCountB];
-    fRecX = new float[fCentralCountNB];
-    
-    fAvgChargeY = new float[fCentralCountB];
-    fAvgChargeX = new float[fCentralCountNB];
-    
-    fNofBChannel = new int[fCentralCountB];
-    fNofNBChannel = new int[fCentralCountNB];
-  }
-  catch(const std::bad_alloc&){
-    HLTError("Dynamic memory allocation failed for AliHLTMUONHitReconstructor::fRecY and others at method RecXRecY()");
-    return false;
-  }
   
   for(b=0;b<fCentralCountB;b++){
     idCentral = fCentralChargeB[b];
@@ -471,9 +524,6 @@ bool AliHLTMUONHitReconstructor::RecXRecY()
     HLTDebug("RecX[%d] : %f",nb,fRecX[nb]);
 
   }
-
-  return true;
-  
 }
 
 
@@ -481,6 +531,13 @@ bool AliHLTMUONHitReconstructor::MergeRecHits()
 {
   // Merge reconstructed hits first over same plane then bending plane with non-bending plane
 
+  assert( fRecX != NULL );
+  assert( fRecY != NULL );
+  assert( fAvgChargeX != NULL );
+  assert( fAvgChargeY != NULL );
+  assert( fNofBChannel != NULL );
+  assert( fNofNBChannel != NULL );
+
   int idCentralB,idCentralNB ;
   float padCenterXB;
   float padCenterYNB;
@@ -603,7 +660,7 @@ bool AliHLTMUONHitReconstructor::MergeRecHits()
            
            // First check that we have not overflowed the buffer.
            if((*fRecPointsCount) == fMaxRecPointsCount){
-             HLTError("Nof RecHit (i.e. %d) exceeds the max nof RecHit limit %d\n",(*fRecPointsCount),fMaxRecPointsCount);
+             HLTError("Number of RecHit (i.e. %d) exceeds the max number of RecHit limit %d.",(*fRecPointsCount),fMaxRecPointsCount);
              return false;
            }
            
@@ -623,43 +680,13 @@ bool AliHLTMUONHitReconstructor::MergeRecHits()
     }// condn on fRecY[b] !=  0.0
   }// loop over B side;
 
-  if(fRecX){
-    delete []fRecX;
-    fRecX = NULL;
-  }
-
-  if(fRecY){
-    delete []fRecY;
-    fRecY = NULL;
-  }
-
-  if(fAvgChargeX){
-    delete []fAvgChargeX;
-    fAvgChargeX = NULL;
-  }
-
-  if(fAvgChargeY){
-    delete []fAvgChargeY;
-    fAvgChargeY = NULL;
-  }
-
-  if(fNofBChannel){
-    delete []fNofBChannel;
-    fNofBChannel = NULL;
-  }
-
-  if(fNofNBChannel){
-    delete []fNofNBChannel;
-    fNofNBChannel = NULL;
-  }
-
   return true;
 }
 
 
 void AliHLTMUONHitReconstructor::Clear()
 {
-  // function to clear internal arrays and release the allocated memory.
+  // function to clear internal arrays.
 
   for(int iPad=1;iPad<fDigitPerDDL;iPad++){
     fGetIdTotalData[fPadData[iPad].fIX][fPadData[iPad].fIY][fPadData[iPad].fPlane] = 0;
@@ -676,47 +703,6 @@ void AliHLTMUONHitReconstructor::Clear()
   
   for(int i=0;i<13;i++)
     fMaxFiredPerDetElem[i] = 0;
-
-  if(fCentralChargeB){
-    delete []fCentralChargeB;
-    fCentralChargeB = NULL;
-  }
-
-  if(fCentralChargeNB){
-    delete []fCentralChargeNB;
-    fCentralChargeNB = NULL;
-  }
-
-  if(fRecX){
-    delete []fRecX;
-    fRecX = NULL;
-  }
-
-  if(fRecY){
-    delete []fRecY;
-    fRecY = NULL;
-  }
-
-  if(fAvgChargeX){
-    delete []fAvgChargeX;
-    fAvgChargeX = NULL;
-  }
-
-  if(fAvgChargeY){
-    delete []fAvgChargeY;
-    fAvgChargeY = NULL;
-  }
-
-  if(fNofBChannel){
-    delete []fNofBChannel;
-    fNofBChannel = NULL;
-  }
-
-  if(fNofNBChannel){
-    delete []fNofNBChannel;
-    fNofNBChannel = NULL;
-  }
-
 }
 
 
@@ -746,6 +732,36 @@ AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::~AliHLTMUONRawDecoder()
 }
 
 
+void AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::OnNewBuffer(const void* buffer, UInt_t /*bufferSize*/)
+{
+       /// Called for every new raw DDL data payload being processed.
+       /// Just clears internal counters.
+       /// \param buffer  The pointer to the raw data buffer.
+
+       assert( buffer != NULL );
+       fBufferStart = buffer;
+       // dataCount starts from 1 because the 0-th element of fPadData is used as null value.
+       fDataCount = 1;
+       *fNofFiredDetElem = 0;
+       fPrevDetElemId = 0 ;
+};
+
+
+void AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::OnError(ErrorCode code, const void* location)
+{
+       /// Called if there was an error detected in the raw DDL data.
+       /// Logs an error message.
+       /// \param code  The error code describing the problem.
+       /// \param location  A pointer to the location in the raw data buffer
+       ///      where the problem was found.
+       
+       long bytepos = long(location) - long(fBufferStart) + sizeof(AliRawDataHeader);
+       HLTError("There is a problem with decoding the raw data. %s (Error code: %d, at byte %d)",
+               ErrorCodeToMessage(code), code, bytepos
+       );
+};
+
+
 void AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::OnData(UInt_t dataWord, bool /*parityError*/)
 {
   //function to arrange the decoded Raw Data
index 9d9fa53fe8090119aac45f493beec5ccd0cebb31..ec9798e760b14c5c778ff185ecc992bc7a4d1592 100644 (file)
@@ -106,22 +106,8 @@ private:
                        fBusPatchId = int(header->fBusPatchId);
                };
                
-               void OnNewBuffer(const void* buffer, UInt_t /*bufferSize*/) 
-               {
-                       assert( buffer != NULL );
-                       fBufferStart = buffer;
-                       fDataCount = 1;  // dataCount starts from 1 because the 0-th element of fPadData is used as null value.
-                       *fNofFiredDetElem = 0;
-                       fPrevDetElemId = 0 ;
-               };
-               
-               void OnError(ErrorCode code, const void* location)
-               {
-                       long bytepos = long(location) - long(fBufferStart) + sizeof(AliRawDataHeader);
-                       HLTError("There is a problem with decoding the raw data. %s (Error code: %d, at byte %d)",
-                               ErrorCodeToMessage(code), code, bytepos
-                       );
-               };
+               void OnNewBuffer(const void* buffer, UInt_t bufferSize);
+               void OnError(ErrorCode code, const void* location);
                
                void SetDCCut(AliHLTInt32_t dcCut) {fDCCut = dcCut;}
                void SetPadData(AliHLTMUONPad* padData) {fPadData = padData;}
@@ -182,11 +168,10 @@ private:
        AliHLTInt32_t fNofFiredDetElem,fMaxFiredPerDetElem[13];  // counter for detector elements that are fired
        const IdManuChannelToEntry* fIdToEntry;   // Mapping between Linenumber to IdManuChannel (The object is not owned by this component).
        
-       //bool ReadDDL(const AliHLTUInt32_t* rawData, AliHLTUInt32_t rawDataSize);
        bool DecodeDDL(const AliHLTUInt32_t* rawData, AliHLTUInt32_t rawDataSize);
        void FindCentralHits(AliHLTInt32_t minPadId, AliHLTInt32_t maxPadId);
        bool FindRecHits();
-       bool RecXRecY();
+       void RecXRecY();
        bool MergeRecHits();
        void Clear();
 
index 656e7a71f61c1a750f8dc4362ced8a5dcb0eb978..e4efaefe7a15918159cef2a1b09959f22814b619 100644 (file)
@@ -90,7 +90,7 @@ AliHLTMUONHitReconstructorComponent::~AliHLTMUONHitReconstructorComponent()
        }
        if (fLut != NULL)
        {
-               delete fLut;
+               delete [] fLut;
        }
 }
 
@@ -455,7 +455,7 @@ void AliHLTMUONHitReconstructorComponent::FreeMemory()
        }
        if (fLut != NULL)
        {
-               delete fLut;
+               delete [] fLut;
                fLut = NULL;
                fLutSize = 0;
        }