X-Git-Url: http://git.uio.no/git/?a=blobdiff_plain;f=MUON%2FAliMUONTrackerDDLDecoder.h;h=d23a26308ab989154851d1273eb34a1ccadf68bb;hb=257f0eee1768a2fce3261c00d1abba5bec687da0;hp=9dfcb8248fe0368604b639e6bdc9d2780e04ed22;hpb=1788245f8ea552746bbbf0cdd6a848dc6abc1eac;p=u%2Fmrichter%2FAliRoot.git diff --git a/MUON/AliMUONTrackerDDLDecoder.h b/MUON/AliMUONTrackerDDLDecoder.h index 9dfcb8248fe..d23a26308ab 100644 --- a/MUON/AliMUONTrackerDDLDecoder.h +++ b/MUON/AliMUONTrackerDDLDecoder.h @@ -37,6 +37,7 @@ /// must be checked before any proposed modification is made to this file. /// +#include #include "AliMUONTrackerDDLDecoderEventHandler.h" /// \ingroup raw @@ -181,6 +182,9 @@ public: /// This method decodes the DDL payload contained in the buffer. bool Decode(const void* buffer, UInt_t bufferSize); + /// First try fix data corruption and then decode the DDL payload. + bool Decode(void* buffer, UInt_t bufferSize); + /// Returns the block marker key. static UInt_t BlockDataKeyWord() { return fgkBlockDataKey; } @@ -318,6 +322,43 @@ bool AliMUONTrackerDDLDecoder::Decode(const void* buffer, UInt_t b } +template +bool AliMUONTrackerDDLDecoder::Decode(void* buffer, UInt_t bufferSize) +{ + /// This decoding method performs a special checks to see if the DDL + /// corruption is fixable and then fixes the buffer by modifying it directly. + /// The fixes only apply if the fTryRecover flag is enabled. + /// \note buffer might be modified. + + assert( buffer != NULL ); + if (fTryRecover) + { + /////////////////////////////////////////////////////// + // Trick to recover B off data Runs : 119041, 119047, 119055, 119057 + // A. Baldisseri May 2010 + // Check if 16 32-bit words from a buspatch have been inserted + // incorrectly immediately at the beginning of the DDL payload. + UChar_t* bufferChar = reinterpret_cast(buffer); + UInt_t* bufferInt = reinterpret_cast(buffer); + if (bufferSize > 18*4 // is the buffer large enough to check the header. + and bufferInt[0] != fgkBlockDataKey and bufferInt[16] == fgkBlockDataKey // was the header incorrectly moved. + and bufferSize > bufferInt[17]*4 + sizeof(AliMUONBlockHeaderStruct) // is the buffer large enough for the second block header. + and bufferInt[bufferInt[17]] == fgkBlockDataKey // Check that the second header is in the correct location. + and bufferInt[17] == bufferInt[18] + 8 // Make sure that both lengths are correct. + and (bufferInt[17] + bufferInt[bufferInt[17]+1]+2)*4 == bufferSize // Check that both blocks will have the correct size if we make the fix. + ) + { + UChar_t tmpbuf[16*4]; + memcpy(tmpbuf, bufferChar, 16*4); + size_t sizeToMove = bufferInt[17]*4-16*4; + memmove(bufferChar, bufferChar+16*4, sizeToMove); + memcpy(bufferChar + sizeToMove, tmpbuf, 16*4); + } + } + return Decode(reinterpret_cast(buffer), bufferSize); +} + + template void AliMUONTrackerDDLDecoder::DecodeBuffer( const UChar_t* start, const UChar_t* end @@ -347,8 +388,8 @@ void AliMUONTrackerDDLDecoder::DecodeBuffer( const UInt_t* trailerWords = reinterpret_cast(end) - 2; if (fAutoDetectTrailer) { - if (trailerWords >= bufferStart and *trailerWords == fgkEndOfDDL - and *(trailerWords+1) == fgkEndOfDDL + if (trailerWords >= bufferStart and trailerWords < bufferEnd + and *trailerWords == fgkEndOfDDL and *(trailerWords+1) == fgkEndOfDDL ) { // Found the trailer so reposition the end of blocks marker. @@ -358,8 +399,8 @@ void AliMUONTrackerDDLDecoder::DecodeBuffer( } else if (fCheckForTrailer) { - if (trailerWords >= bufferStart and *trailerWords == fgkEndOfDDL - and *(trailerWords+1) == fgkEndOfDDL + if (trailerWords >= bufferStart and trailerWords < bufferEnd + and *trailerWords == fgkEndOfDDL and *(trailerWords+1) == fgkEndOfDDL ) { // Found the trailer so reposition the end of blocks marker. @@ -367,9 +408,9 @@ void AliMUONTrackerDDLDecoder::DecodeBuffer( } else { - if (trailerWords+1 >= bufferStart and *(trailerWords+1) == fgkEndOfDDL) + if (trailerWords+1 >= bufferStart and trailerWords+1 < bufferEnd and *(trailerWords+1) == fgkEndOfDDL) fHandler.OnError(EventHandler::kTooFewDDLTrailerWords, trailerWords+1); - else if (trailerWords >= bufferStart and *(trailerWords) == fgkEndOfDDL) + else if (trailerWords >= bufferStart and trailerWords < bufferEnd and *(trailerWords) == fgkEndOfDDL) fHandler.OnError(EventHandler::kTooFewDDLTrailerWords, trailerWords); else fHandler.OnError(EventHandler::kNoDDLTrailerWords, end); @@ -391,10 +432,10 @@ void AliMUONTrackerDDLDecoder::DecodeBuffer( { trailerWords = bufferEnd; // There should only be a max of 2 trailer words. - if (*(trailerWords-1) == fgkEndOfDDL) - trailerWords--; - else if (*(trailerWords-1) == fgkEndOfDDL) - trailerWords--; + if (trailerWords-2 >= bufferStart and trailerWords-2 < bufferEnd and *(trailerWords-2) == fgkEndOfDDL) + trailerWords -= 2; + else if (trailerWords-1 >= bufferStart and trailerWords-1 < bufferEnd and *(trailerWords-1) == fgkEndOfDDL) + trailerWords -= 1; endOfBlocks = reinterpret_cast(trailerWords); } } @@ -411,8 +452,12 @@ void AliMUONTrackerDDLDecoder::DecodeBuffer( const AliMUONBlockHeaderStruct* blockHeader = reinterpret_cast(blockStart); current += sizeof(AliMUONBlockHeaderStruct); - if (current > endOfBlocks) + if (current > endOfBlocks or current < start) { + // If we overflowed the pointer and already had an error then + // we are clearly lost so just stop decoding before we segfault. + if (current < start and fHadError) return; + // We first check if we actually hit the end of DDL markers // If we did then either we did not/could not recover from // a corrupt trailer or we did not detect a correct trailer @@ -465,7 +510,9 @@ void AliMUONTrackerDDLDecoder::DecodeBuffer( // If any of the above fail then we know there is a problem with // the block header. It must be corrupted somehow. if (blockHeader->fDataKey != fgkBlockDataKey - or dataEnd > endOfBlocks or blockEnd > endOfBlocks or dataEnd != blockEnd) + or dataEnd > endOfBlocks or dataEnd < start + or blockEnd > endOfBlocks or blockEnd < start + or dataEnd != blockEnd) { // So let us see what exactly is wrong and report this. if (blockCount == fMaxBlocks) @@ -479,9 +526,9 @@ void AliMUONTrackerDDLDecoder::DecodeBuffer( } if (blockHeader->fDataKey != fgkBlockDataKey) fHandler.OnError(EventHandler::kBadBlockKey, &blockHeader->fDataKey); - if (blockEnd > endOfBlocks) + if (blockEnd > endOfBlocks or blockEnd < start) fHandler.OnError(EventHandler::kBadBlockLength, &blockHeader->fLength); - if (dataEnd > endOfBlocks) + if (dataEnd > endOfBlocks or dataEnd < start) fHandler.OnError(EventHandler::kBadBlockTotalLength, &blockHeader->fTotalLength); if (dataEnd != blockEnd) fHandler.OnError(EventHandler::kBlockLengthMismatch, blockHeader); @@ -567,8 +614,12 @@ bool AliMUONTrackerDDLDecoder::DecodeBlockData( const AliMUONDSPHeaderStruct* dspHeader = reinterpret_cast(dspStart); current += sizeof(AliMUONDSPHeaderStruct); - if (current > end) + if (current > end or current < start) { + // If we overflowed the pointer and already had an error then + // we are clearly lost so just stop decoding before we segfault. + if (current < start and fHadError) return false; + // So we only got part of a DSP header at the very end of // the block structure buffer. Nothing to do but report the // error and exit. Set fHadError in case of further decoding. @@ -592,14 +643,16 @@ bool AliMUONTrackerDDLDecoder::DecodeBlockData( // If any of the above fail then we know there is a problem with // the DSP header. It must be corrupted somehow. if (dspHeader->fDataKey != fgkDSPDataKey - or dataEnd > end or dspEnd > end or dataEnd != dspEnd) + or dataEnd > end or dataEnd < start + or dspEnd > end or dspEnd < start + or dataEnd != dspEnd) { // So let us see what exactly is wrong and report this. if (dspHeader->fDataKey != fgkDSPDataKey) fHandler.OnError(EventHandler::kBadDSPKey, &dspHeader->fDataKey); - if (dspEnd > end) + if (dspEnd > end or dspEnd < start) fHandler.OnError(EventHandler::kBadDSPLength, &dspHeader->fLength); - if (dataEnd > end) + if (dataEnd > end or dataEnd < start) fHandler.OnError(EventHandler::kBadDSPTotalLength, &dspHeader->fTotalLength); if (dataEnd != dspEnd) fHandler.OnError(EventHandler::kDSPLengthMismatch, dspHeader); @@ -639,15 +692,29 @@ bool AliMUONTrackerDDLDecoder::DecodeBlockData( fHandler.OnNewDSP(dspHeader, dataStart); // Check the error word in the header. - if (dspHeader->fErrorWord == (0x000000B1 | blockHeader->fDSPId) - or dspHeader->fErrorWord == (0x00000091 | blockHeader->fDSPId) - ) + if (dspHeader->fErrorWord != 0x0) { - // An event with a glitch in the readout has been detected. - // It means that somewhere a 1 byte word has been randomly - // inserted and all the readout sequence is shifted until - // the next event. - fHandler.OnError(EventHandler::kGlitchFound, &dspHeader->fErrorWord); + if (dspHeader->fErrorWord == (0x000000B1 | blockHeader->fDSPId) + or dspHeader->fErrorWord == (0x00000091 | blockHeader->fDSPId) + ) + { + // An event with a glitch in the readout has been detected. + // It means that somewhere a 1 byte word has been randomly + // inserted and all the readout sequence is shifted until + // the next event. + fHandler.OnError(EventHandler::kGlitchFound, &dspHeader->fErrorWord); + } + else if ((dspHeader->fErrorWord & 0x0000FFF0) == 0x220) + { + // Detected a TOKEN_LOST error which can affect the dead time in the DAQ. + fHandler.OnError(EventHandler::kTokenLost, &dspHeader->fErrorWord); + } + else + { + // The DSP error code is non-zero but has an unknown code. + fHandler.OnError(EventHandler::kUnknownDspError, &dspHeader->fErrorWord); + } + fHadError = true; if (fExitOnError) { @@ -656,11 +723,15 @@ bool AliMUONTrackerDDLDecoder::DecodeBlockData( } // Try recover by finding the very next DSP and continue - // decoding from there. Note: to achieve all we have to do - // is continue to the next iteration, because the logic + // decoding from there. Note: to achieve this all we have to + // do is continue to the next iteration, because the logic // will land up calling the FindKey method within the // TryRecoverStruct method above. - if (fTryRecover) continue; + if (fTryRecover) + { + fHandler.OnEndOfDSP(dspHeader, dataStart); + continue; + } } // Check if we are padding. If we are, then the bus patch data is @@ -731,8 +802,12 @@ bool AliMUONTrackerDDLDecoder::DecodeDSPData( const AliMUONBusPatchHeaderStruct* busPatchHeader = reinterpret_cast(busPatchStart); current += sizeof(AliMUONBusPatchHeaderStruct); - if (current > end) + if (current > end or current < start) { + // If we overflowed the pointer and already had an error then + // we are clearly lost so just stop decoding before we segfault. + if (current < start and fHadError) return false; + // So we only got part of a bus patch header at the very // end of the DSP structure buffer. Nothing to do but // report the error and exit. Set fHadError in case of @@ -759,14 +834,16 @@ bool AliMUONTrackerDDLDecoder::DecodeDSPData( // If any of the above fail then we know there is a problem with // the bus patch header. It must be corrupted somehow. if (busPatchHeader->fDataKey != fgkBusPatchDataKey - or dataEnd > end or busPatchEnd > end or dataEnd != busPatchEnd) + or dataEnd > end or dataEnd < start + or busPatchEnd > end or busPatchEnd < start + or dataEnd != busPatchEnd) { // So let us see what exactly is wrong and report this. if (busPatchHeader->fDataKey != fgkBusPatchDataKey) fHandler.OnError(EventHandler::kBadBusPatchKey, &busPatchHeader->fDataKey); - if (busPatchEnd > end) + if (busPatchEnd > end or busPatchEnd < start) fHandler.OnError(EventHandler::kBadBusPatchLength, &busPatchHeader->fLength); - if (dataEnd > end) + if (dataEnd > end or dataEnd < start) fHandler.OnError(EventHandler::kBadBusPatchTotalLength, &busPatchHeader->fTotalLength); if (dataEnd != busPatchEnd) fHandler.OnError(EventHandler::kBusPatchLengthMismatch, busPatchHeader); @@ -970,7 +1047,7 @@ AliMUONTrackerDDLDecoder::TryRecoverStruct( const UInt_t* headerKey = reinterpret_cast(structStart); bool headerKeyOk = (expectedKey == *headerKey); - bool lengthsMatch = (totalLength == length + headerSize); + bool lengthsMatch = (totalLength*4 == length*4 + headerSize); bool lengthIsCorrect = false; bool totalLengthIsCorrect = false; @@ -989,7 +1066,7 @@ AliMUONTrackerDDLDecoder::TryRecoverStruct( { // Must check that we can read another 4 bytes before // checking the key at dataEnd. - if (dataEnd + sizeof(UInt_t) <= bufferEnd) + if (dataEnd + sizeof(UInt_t) <= bufferEnd and dataEnd + sizeof(UInt_t) > structStart) { if (*keyAtDataEnd == fgkBlockDataKey) lengthIsCorrect = true; @@ -1005,7 +1082,7 @@ AliMUONTrackerDDLDecoder::TryRecoverStruct( { // Must check that we can read another 4 bytes before // checking the key at structEnd. - if (structEnd + sizeof(UInt_t) <= bufferEnd) + if (structEnd + sizeof(UInt_t) <= bufferEnd and structEnd + sizeof(UInt_t) > structStart) { if (*keyAtStructEnd == fgkBlockDataKey) totalLengthIsCorrect = true; @@ -1024,7 +1101,7 @@ AliMUONTrackerDDLDecoder::TryRecoverStruct( { // Must check that we can read another 4 bytes before // checking the key at dataEnd. - if (dataEnd + sizeof(UInt_t) <= bufferEnd) + if (dataEnd + sizeof(UInt_t) <= bufferEnd and dataEnd + sizeof(UInt_t) > structStart) { if (*keyAtDataEnd == fgkBlockDataKey or *keyAtDataEnd == fgkDSPDataKey) @@ -1041,7 +1118,7 @@ AliMUONTrackerDDLDecoder::TryRecoverStruct( { // Must check that we can read another 4 bytes before // checking the key at structEnd. - if (structEnd + sizeof(UInt_t) <= bufferEnd) + if (structEnd + sizeof(UInt_t) <= bufferEnd and structEnd + sizeof(UInt_t) > structStart) { if (*keyAtStructEnd == fgkBlockDataKey or *keyAtStructEnd == fgkDSPDataKey) @@ -1060,7 +1137,7 @@ AliMUONTrackerDDLDecoder::TryRecoverStruct( { // Must check that we can read another 4 bytes before // checking the key at dataEnd. - if (dataEnd + sizeof(UInt_t) <= bufferEnd) + if (dataEnd + sizeof(UInt_t) <= bufferEnd and dataEnd + sizeof(UInt_t) > structStart) { if (*keyAtDataEnd == fgkDSPDataKey or *keyAtDataEnd == fgkBusPatchDataKey) @@ -1077,7 +1154,7 @@ AliMUONTrackerDDLDecoder::TryRecoverStruct( { // Must check that we can read another 4 bytes before // checking the key at structEnd. - if (structEnd + sizeof(UInt_t) <= bufferEnd) + if (structEnd + sizeof(UInt_t) <= bufferEnd and structEnd + sizeof(UInt_t) > structStart) { if (*keyAtStructEnd == fgkDSPDataKey or *keyAtStructEnd == fgkBusPatchDataKey) @@ -1132,7 +1209,8 @@ const UChar_t* AliMUONTrackerDDLDecoder::FindKey( /// should point to 'start + bufferSize', i.e. just past the last byte of the /// buffer. If the key was found then the pointer to that location is returned /// otherwise NULL is returned. - + + if (end + sizeof(UInt_t) < start) return NULL; // check for pointer overflow. const UChar_t* current = start; while (current + sizeof(UInt_t) <= end) {