+
+void AliHLTComponent::SetDDLBit(AliHLTEventDDL &list, Int_t ddlId, Bool_t state ) const
+{
+ // see header file for function documentation
+
+ // -- Detector offset
+ Int_t ddlIdBase = TMath::FloorNint( (Double_t) ddlId / 256.0 );
+
+ // -- Word Base = 1. word of detector ( TPC has 8 words, TOF 3 )
+ Int_t wordBase = 0;
+
+ if ( ddlIdBase <= 3 )
+ wordBase = ddlIdBase;
+ else if ( ddlIdBase > 3 && ddlIdBase < 5 )
+ wordBase = ddlIdBase + 7;
+ else
+ wordBase = ddlIdBase + 9;
+
+ // -- Bit index in Word
+ Int_t bitIdx = ddlId % 32;
+
+ // -- Index of word
+ Int_t wordIdx = wordBase;
+
+ // -- if TPC (3) or TOD (5) add word idx
+ if ( ( ddlIdBase == 3 ) || ( ddlIdBase == 5 ) ) {
+ wordIdx += TMath::FloorNint( (Double_t) ( ddlId - ( ddlIdBase * 256 ) ) / 32.0 );
+ }
+
+ // -- Set -- 'OR' word with bit mask;
+ if ( state )
+ list.fList[wordIdx] |= ( 0x00000001 << bitIdx );
+ // -- Unset -- 'AND' word with bit mask;
+ else
+ list.fList[wordIdx] &= ( 0xFFFFFFFF ^ ( 0x00000001 << bitIdx ) );
+}
+
+Int_t AliHLTComponent::GetFirstUsedDDLWord(AliHLTEventDDL &list) const
+{
+ // see header file for function documentation
+
+ Int_t iResult = -1;
+
+ for ( Int_t wordNdx = 0 ; wordNdx < gkAliHLTDDLListSize ; wordNdx++ ) {
+
+ if ( list.fList[wordNdx] != 0 && iResult == -1 ) {
+ // check for special cases TPC and TOF
+ if ( wordNdx > 3 && wordNdx <= 10 ) {
+ wordNdx = 10;
+ iResult = 3;
+ }
+ else if ( wordNdx > 12 && wordNdx <= 14 ) {
+ wordNdx = 14;
+ iResult = 12;
+ }
+ else
+ iResult = wordNdx;
+ }
+ else if ( list.fList[wordNdx] != 0 && iResult >= 0 ) {
+ HLTError( "DDLIDs for minimum of TWO detectors ( %d, %d ) set, this function works only for ONE detector.", iResult, wordNdx );
+ iResult = -1;
+ break;
+ }
+ }
+
+ return iResult;
+}
+
+AliHLTUInt32_t AliHLTComponent::CalculateChecksum(const AliHLTUInt8_t* buffer, int size)
+{
+ // see header file for function documentation
+ AliHLTUInt32_t remainder = 0;
+ const AliHLTUInt8_t crcwidth=(8*sizeof(AliHLTUInt32_t));
+ const AliHLTUInt32_t topbit=1 << (crcwidth-1);
+ const AliHLTUInt32_t polynomial=0xD8; /* 11011 followed by 0's */
+
+ // code from
+ // http://www.netrino.com/Embedded-Systems/How-To/CRC-Calculation-C-Code
+
+ /*
+ * Perform modulo-2 division, a byte at a time.
+ */
+ for (int byte = 0; byte < size; ++byte)
+ {
+ /*
+ * Bring the next byte into the remainder.
+ */
+ remainder ^= (buffer[byte] << (crcwidth - 8));
+
+ /*
+ * Perform modulo-2 division, a bit at a time.
+ */
+ for (uint8_t bit = 8; bit > 0; --bit)
+ {
+ /*
+ * Try to divide the current data bit.
+ */
+ if (remainder & topbit)
+ {
+ remainder = (remainder << 1) ^ polynomial;
+ }
+ else
+ {
+ remainder = (remainder << 1);
+ }
+ }
+ }
+
+ /*
+ * The final remainder is the CRC result.
+ */
+ return (remainder);
+}
+
+int AliHLTComponent::ExtractComponentTableEntry(const AliHLTUInt8_t* pBuffer, AliHLTUInt32_t size,
+ string& retChainId, string& retCompId, string& retCompArgs,
+ vector<AliHLTUInt32_t>& parents)
+{
+ // see header file for function documentation
+ retChainId.clear();
+ retCompId.clear();
+ retCompArgs.clear();
+ parents.clear();
+ if (!pBuffer || size==0) return 0;
+
+ const AliHLTComponentTableEntry* pEntry=reinterpret_cast<const AliHLTComponentTableEntry*>(pBuffer);
+ if (size<8/* the initial size of the structure*/ ||
+ pEntry==NULL || pEntry->fStructSize<8) return -ENOMSG;
+ const AliHLTUInt32_t* pParents=reinterpret_cast<const AliHLTUInt32_t*>(pEntry->fBuffer);
+ const AliHLTUInt8_t* pEnd=pBuffer+size;
+
+ if (pParents+pEntry->fNofParents>=reinterpret_cast<const AliHLTUInt32_t*>(pEnd)) return -ENODEV;
+ for (unsigned int i=0; i<pEntry->fNofParents; i++, pParents++) {
+ parents.push_back(*pParents);
+ }
+
+ const char* pDescription=reinterpret_cast<const char*>(pParents);
+ if (pDescription+pEntry->fSizeDescription>=reinterpret_cast<const char*>(pEnd) ||
+ *(pDescription+pEntry->fSizeDescription)!=0) {
+ return -EBADF;
+ }
+
+ TString descriptor=reinterpret_cast<const char*>(pDescription);
+ TString chainId;
+ TString compId;
+ TString compArgs;
+ TObjArray* pTokens=descriptor.Tokenize("{");
+ if (pTokens) {
+ int n=0;
+ if (pTokens->GetEntries()>n) {
+ retChainId=((TObjString*)pTokens->At(n++))->GetString();
+ }
+ if (pTokens->GetEntries()>n) {
+ compId=((TObjString*)pTokens->At(n++))->GetString();
+ }
+ delete pTokens;
+ }
+ if (!compId.IsNull() && (pTokens=compId.Tokenize(":"))!=NULL) {
+ int n=0;
+ if (pTokens->GetEntries()>n) {
+ compId=((TObjString*)pTokens->At(n++))->GetString();
+ }
+ if (pTokens->GetEntries()>n) {
+ compArgs=((TObjString*)pTokens->At(n++))->GetString();
+ }
+ delete pTokens;
+ }
+ compId.ReplaceAll("}", "");
+ compArgs.ReplaceAll("}", "");
+
+ retCompId=compId;
+ retCompArgs=compArgs;
+
+ if (retChainId.size()==0) return -ENODATA;
+
+ return 1;
+}
+
+int AliHLTComponent::LoggingVarargs(AliHLTComponentLogSeverity severity,
+ const char* originClass, const char* originFunc,
+ const char* file, int line, ... ) const
+{
+ // see header file for function documentation
+ int iResult=0;
+
+ va_list args;
+ va_start(args, line);
+
+ // logging function needs to be const in order to be called from const member functions
+ // without problems. But at this point we face the problem with virtual members which
+ // are not necessarily const.
+ AliHLTComponent* nonconst=const_cast<AliHLTComponent*>(this);
+ AliHLTLogging::SetLogString("%s (%s, %p): ",
+ fChainId[0]!=0?fChainId.c_str():nonconst->GetComponentID(),
+ nonconst->GetComponentID(), this);
+ iResult=SendMessage(severity, originClass, originFunc, file, line, AliHLTLogging::BuildLogString(NULL, args, true /*append*/));
+ va_end(args);
+
+ return iResult;
+}
+
+int AliHLTComponent::ScanECSParam(const char* ecsParam)
+{
+ // see header file for function documentation
+
+ // format of the parameter string from ECS
+ // <command>;<parameterkey>=<parametervalue>;<parameterkey>=<parametervalue>;...
+ // search for a subset of the parameterkeys
+ int iResult=0;
+ TString string=ecsParam;
+ TObjArray* parameter=string.Tokenize(";");
+ if (parameter) {
+ for (int i=0; i<parameter->GetEntries(); i++) {
+ TString entry=((TObjString*)parameter->At(i))->GetString();
+ HLTDebug("scanning ECS entry: %s", entry.Data());
+ TObjArray* entryParams=entry.Tokenize("=");
+ if (entryParams) {
+ if (entryParams->GetEntries()>1) {
+ if ((((TObjString*)entryParams->At(0))->GetString()).CompareTo("CTP_TRIGGER_CLASS")==0) {
+ int result=InitCTPTriggerClasses((((TObjString*)entryParams->At(1))->GetString()).Data());
+ if (iResult>=0 && result<0) iResult=result;
+ } else {
+ // TODO: scan the other parameters
+ // e.g. consistency check of run number
+ }
+ }
+ delete entryParams;
+ }
+ }
+ delete parameter;
+ }
+
+ return iResult;
+}
+
+int AliHLTComponent::InitCTPTriggerClasses(const char* ctpString)
+{
+ // see header file for function documentation
+ if (!ctpString) return -EINVAL;
+
+ if (fpTriggerClasses) {
+ fpTriggerClasses->Delete();
+ } else {
+ fpTriggerClasses=new TObjArray(gkNCTPTriggerClasses);
+ }
+ if (!fpTriggerClasses) return -ENOMEM;
+
+ // general format of the CTP_TRIGGER_CLASS parameter
+ // <bit position>:<Trigger class identifier string>:<detector-id-nr>-<detector-id-nr>-...,<bit position>:<Trigger class identifier string>:<detector-id-nr>-<detector-id-nr>-...,...
+ // the detector ids are ignored for the moment
+ HLTDebug(": %s", ctpString);
+ TString string=ctpString;
+ TObjArray* classEntries=string.Tokenize(",");
+ if (classEntries) {
+ for (int i=0; i<classEntries->GetEntries(); i++) {
+ TString entry=((TObjString*)classEntries->At(i))->GetString();
+ TObjArray* entryParams=entry.Tokenize(":");
+ if (entryParams) {
+ if (entryParams->GetEntries()==3 &&
+ (((TObjString*)entryParams->At(0))->GetString()).IsDigit()) {
+ int index=(((TObjString*)entryParams->At(0))->GetString()).Atoi();
+ if (index<gkNCTPTriggerClasses) {
+ fpTriggerClasses->AddAt(new TNamed("TriggerClass", (((TObjString*)entryParams->At(1))->GetString()).Data()), index);
+ } else {
+ // the trigger bitfield is fixed to 50 bits (gkNCTPTriggerClasses)
+ HLTError("invalid trigger class entry %s, index width of trigger bitfield", entry.Data());
+ }
+ } else {
+ HLTError("invalid trigger class entry %s", entry.Data());
+ }
+ delete entryParams;
+ }
+ }
+ delete classEntries;
+ }
+ return 0;
+}
+
+bool AliHLTComponent::EvaluateCTPTriggerClass(const char* expression, AliHLTComponentTriggerData& trigData) const
+{
+ // see header file for function documentation
+ if (!fpTriggerClasses) {
+ HLTError("trigger classes not initialized");
+ return false;
+ }
+
+ if (trigData.fDataSize != sizeof(AliHLTEventTriggerData)) {
+ HLTError("invalid trigger data size: %d expected %d", trigData.fDataSize, sizeof(AliHLTEventTriggerData));
+ return false;
+ }
+
+ // trigger mask is 50 bit wide and is stored in word 5 and 6 of the CDH
+ AliHLTEventTriggerData* evtData=reinterpret_cast<AliHLTEventTriggerData*>(trigData.fData);
+ AliHLTUInt64_t triggerMask=evtData->fCommonHeader[6];
+ triggerMask<<=32;
+ triggerMask|=evtData->fCommonHeader[5];
+
+ // use a TFormula to interprete the expression
+ // all classname are replaced by '[n]' which means the n'th parameter in the formula
+ // the parameters are set to 0 or 1 depending on the bit in the trigger mask
+ //
+ // TODO: this will most likely fail for class names like 'base', 'baseA', 'baseB'
+ // the class names must be fully unique, none must be contained as substring in
+ // another class name. Probably not needed for the moment but needs to be extended.
+ vector<Double_t> par;
+ TString condition=expression;
+ for (int i=0; i<gkNCTPTriggerClasses; i++) {
+ if (fpTriggerClasses->At(i)) {
+ TString className=fpTriggerClasses->At(i)->GetTitle();
+ //HLTDebug("checking trigger class %s", className.Data());
+ if (condition.Contains(className)) {
+ TString replace; replace.Form("[%d]", par.size());
+ //HLTDebug("replacing %s with %s in \"%s\"", className.Data(), replace.Data(), condition.Data());
+ condition.ReplaceAll(className, replace);
+ if (triggerMask&((AliHLTUInt64_t)0x1<<i)) par.push_back(1.0);
+ else par.push_back(0.0);
+ }
+ }
+ }
+
+ TFormula form("trigger expression", condition);
+ if (form.Compile()!=0) {
+ HLTError("invalid expression %s", expression);
+ return false;
+ }
+ if (form.EvalPar(&par[0], &par[0])>0.5) return true;
+ return false;
+}