void printVector(vector<StatsData *> &vals, HashMap<uint32_t, uint32_t> serverip_to_shortid, const string &header) { cout << format("\n%s:\n") % header; cout << "server operation #ops #dups mean "; if (enable_first_latency_stat) { cout << "; firstlat mean 50% 90% "; } if (enable_last_latency_stat) { cout << "; lastlat mean 50% 90%"; } cout << "\n"; sort(vals.begin(),vals.end(),sortByServerOp()); for (vector<StatsData *>::iterator i = vals.begin(); i != vals.end();++i) { StatsData *j = *i; int64_t noperations = j->nops(); if (j->serverip == 0) { cout << " * "; } else { cout << format("%03d ") % serverip_to_shortid[j->serverip]; } cout << format("%9s %9lld %6lld %4.2f ") % j->operation % noperations % j->duplicates->countll() % j->duplicates->mean(); printOneQuant(j->first_latency_ms); printOneQuant(j->last_latency_ms); cout << "\n"; } }
// TODO: use rotating hash map void handleResponse() { // row is a response, so address of server = sourceip TidData dummy(transaction_id.val(), sourceip.val(), destip.val()); TidData *t = pending1->lookup(dummy); if (t == NULL) { ++missing_request_count; } else { // we now have both request and response, so we can add latency to statistics // TODO: do the calculation in raw units and convert at the end. int64_t delay_first_raw = reqtime.valRaw() - t->first_reqtime_raw; int64_t delay_last_raw = reqtime.valRaw() - t->last_reqtime_raw; double delay_first_ms = reqtime.rawToDoubleSeconds(delay_first_raw) * 1.0e3; double delay_last_ms = reqtime.rawToDoubleSeconds(delay_last_raw) * 1.0e3; StatsData hdummy(sourceip.val(), operation.stringval()); StatsData *d = stats_table.lookup(hdummy); // add to statistics per request type and server if (d == NULL) { // create new entry hdummy.initStats(enable_first_latency_stat, enable_last_latency_stat); d = stats_table.add(hdummy); } d->add(delay_first_ms, delay_last_ms); // remove request from pending hashtable only if // we haven't seen a duplicate request. If we // have seen a duplicate request, then there might // be a duplicate reply coming if (t->duplicate_count > 0) { d->duplicates->add(t->duplicate_count); if (t->seen_reply) { ++duplicate_reply_count; } else { t->seen_reply = true; } } else { pending1->remove(*t); } } }
/*! \brief extract channel information from raw data ReadBuffData extracts channel information from the raw data arrays and places it into a structure called evt. A pointer to each of the evt objects is placed in the eventlist vector for later time sorting. \param [in] buf : the buffer to process \param [in] bufLen : the length of the buffer \param [in] eventList : the event list to add the extracted buffer to \return An unused integer */ int ReadBuffDataD(word_t *buf, unsigned long *bufLen, vector<ChanEvent*> &eventList) { // multiplier for high bits of 48-bit time static const double HIGH_MULT = pow(2., 32.); word_t modNum; unsigned long numEvents = 0; word_t *bufStart = buf; /* Determine the number of words in the buffer */ *bufLen = *buf++; /* Read the module number */ modNum = *buf++; ChanEvent *lastVirtualChannel = NULL; if(*bufLen > 0) { // check if the buffer has data if(*bufLen == 2) { // this is an empty channel return 0; } do { ChanEvent *currentEvt = new ChanEvent; // decoding event data... see pixie16app.c // buf points to the start of channel data word_t chanNum = (buf[0] & 0x0000000F); word_t slotNum = (buf[0] & 0x000000F0) >> 4; word_t crateNum = (buf[0] & 0x00000F00) >> 8; word_t headerLength = (buf[0] & 0x0001F000) >> 12; word_t eventLength = (buf[0] & 0x1FFE0000) >> 17; currentEvt->virtualChannel = ((buf[0] & 0x20000000) != 0); currentEvt->saturatedBit = ((buf[0] & 0x40000000) != 0); currentEvt->pileupBit = ((buf[0] & 0x80000000) != 0); // Rev. D header lengths not clearly defined in pixie16app_defs //! magic numbers here for now // make some sanity checks if(headerLength == stats.headerLength) { // this is a manual statistics block inserted by the poll program stats.DoStatisticsBlock(&buf[1], modNum); buf += eventLength; numEvents = readbuff::STATS; continue; } if(headerLength != 4 && headerLength != 8 && headerLength != 12 && headerLength != 16) { cout << " Unexpected header length: " << headerLength << endl; cout << " Buffer " << modNum << " of length " << *bufLen << endl; cout << " CHAN:SLOT:CRATE " << chanNum << ":" << slotNum << ":" << crateNum << endl; // advance to next event and continue // buf += EventLength; // continue; // skip the rest of this buffer return readbuff::ERROR; //return numEvents; } word_t lowTime = buf[1]; word_t highTime = buf[2] & 0x0000FFFF; word_t cfdTime = (buf[2] & 0xFFFF0000) >> 16; word_t energy = buf[3] & 0x0000FFFF; word_t traceLength = (buf[3] & 0xFFFF0000) >> 16; if(headerLength == 8 || headerLength == 16) { // skip the onboard partial sums for now // trailing, leading, gap, baseline } if(headerLength >= 12) { int offset = headerLength - 8; for(int i=0; i < currentEvt->numQdcs; i++) { currentEvt->qdcValue[i] = buf[offset + i]; } } // one last sanity check if(traceLength / 2 + headerLength != eventLength) { cout << " Bad event length (" << eventLength << ") does not correspond with length of header (" << headerLength << ") and length of trace (" << traceLength << ")" << endl; buf += eventLength; continue; } // handle multiple crates modNum += 100 * crateNum; currentEvt->chanNum = chanNum; currentEvt->modNum = modNum; if(currentEvt->virtualChannel) { DetectorLibrary* modChan = DetectorLibrary::get(); currentEvt->modNum += modChan->GetPhysicalModules(); if(modChan->at(modNum, chanNum).HasTag("construct_trace")) { lastVirtualChannel = currentEvt; } } currentEvt->energy = energy; //KM 2012-10-24 reinstating removal of saturated if(currentEvt->saturatedBit) currentEvt->energy = 16383; currentEvt->trigTime = lowTime; currentEvt->cfdTime = cfdTime; currentEvt->eventTimeHi = highTime; currentEvt->eventTimeLo = lowTime; currentEvt->time = highTime * HIGH_MULT + lowTime; buf += headerLength; /* Check if trace data follows the channel header */ if(traceLength > 0) { // sbuf points to the beginning of trace data halfword_t *sbuf = (halfword_t *)buf; currentEvt->trace.reserve(traceLength); if(currentEvt->saturatedBit) currentEvt->trace.SetValue("saturation", 1); if(lastVirtualChannel != NULL && lastVirtualChannel->trace.empty()) { lastVirtualChannel->trace.assign(traceLength, 0); } // Read the trace data (2-bytes per sample, i.e. 2 samples per word) for(unsigned int k = 0; k < traceLength; k ++) { currentEvt->trace.push_back(sbuf[k]); if(lastVirtualChannel != NULL) { lastVirtualChannel->trace[k] += sbuf[k]; } } buf += traceLength / 2; } eventList.push_back(currentEvt); numEvents++; } while(buf < bufStart + *bufLen); } else { // if buffer has data
/*! \brief extract channel information from raw data ReadBuffData extracts channel information from the raw data arrays and places it into a structure called evt. A pointer to each of the evt objects is placed in the eventlist vector for later time sorting. \param [in] buf : the buffer to process \param [in] bufLen : the length of the buffer \param [in] eventList : the event list to add the extracted buffer to \return An unused integer */ int ReadBuffDataF(word_t *buf, unsigned long *bufLen, vector<ChanEvent*> &eventList) { // multiplier for high bits of 48-bit time static const double HIGH_MULT = pow(2., 32.); word_t modNum; unsigned long numEvents = 0; word_t *bufStart = buf; /* Determine the number of words in the buffer */ *bufLen = *buf++; /* Read the module number */ modNum = *buf++; ChanEvent *lastVirtualChannel = NULL; if(*bufLen > 0) { // check if the buffer has data if(*bufLen == 2) { // this is an empty channel return 0; } do { ChanEvent *currentEvt = new ChanEvent; // decoding event data... see pixie16app.c // buf points to the start of channel data //Decode the first header word word_t chanNum = (buf[0] & 0x0000000F); word_t slotNum = (buf[0] & 0x000000F0) >> 4; word_t crateNum = (buf[0] & 0x00000F00) >> 8; word_t headerLength = (buf[0] & 0x0001F000) >> 12; word_t eventLength = (buf[0] & 0x7FFE0000) >> 17; currentEvt->pileupBit = (buf[0] & 0x80000000) != 0; // Sanity check if(headerLength == stats.headerLength) { // this is a manual statistics block inserted poll stats.DoStatisticsBlock(&buf[1], modNum); buf += eventLength; numEvents = readbuff::STATS; continue; } //Decode the second header word word_t lowTime = buf[1]; //Decode the third header word word_t highTime = buf[2] & 0x0000FFFF; word_t cfdTime = (buf[2] & 0x3FFF0000) >> 16; currentEvt->cfdTrigSource = ((buf[2] & 0x40000000) != 0); currentEvt->cfdForceTrig = ((buf[2] & 0x80000000) != 0); //Decode the foruth header word word_t energy = buf[3] & 0x0000FFFF; word_t traceLength = (buf[3] & 0x7FFF0000) >> 16; currentEvt->saturatedBit = ((buf[3] & 0x80000000) != 0); int offset = headerLength - 8; switch(headerLength) { case 4: case 6: case 8: case 10: break; case 12: case 14: case 16: case 18: for(int i=0; i < currentEvt->numQdcs; i++) currentEvt->qdcValue[i] = buf[offset + i]; break; default: cerr << " Unexpected header length: " << headerLength << endl; cerr << " Buffer " << modNum << " of length " << *bufLen << endl; cerr << " CHAN:SLOT:CRATE " << chanNum << ":" << slotNum << ":" << crateNum << endl; return readbuff::ERROR; break; } // one last sanity check if(traceLength / 2 + headerLength != eventLength) { cerr << " Bad event length (" << eventLength << ") does not correspond with length of header (" << headerLength << ") and length of trace (" << traceLength << ")" << endl; buf += eventLength; continue; } // handle multiple crates modNum += 100 * crateNum; currentEvt->chanNum = chanNum; currentEvt->modNum = modNum; if(currentEvt->virtualChannel) { DetectorLibrary* modChan = DetectorLibrary::get(); currentEvt->modNum += modChan->GetPhysicalModules(); if(modChan->at(modNum, chanNum).HasTag("construct_trace")) { lastVirtualChannel = currentEvt; } } currentEvt->energy = energy; if(currentEvt->saturatedBit) currentEvt->energy = 16383; currentEvt->trigTime = lowTime; currentEvt->cfdTime = cfdTime; currentEvt->eventTimeHi = highTime; currentEvt->eventTimeLo = lowTime; currentEvt->time = highTime * HIGH_MULT + lowTime; buf += headerLength; /* Check if trace data follows the channel header */ if(traceLength > 0) { // sbuf points to the beginning of trace data halfword_t *sbuf = (halfword_t *)buf; currentEvt->trace.reserve(traceLength); if(currentEvt->saturatedBit) currentEvt->trace.SetValue("saturation", 1); if(lastVirtualChannel != NULL && lastVirtualChannel->trace.empty()) { lastVirtualChannel->trace.assign(traceLength, 0); } // Read the trace data (2-bytes per sample, i.e. 2 samples per word) for(unsigned int k = 0; k < traceLength; k ++) { currentEvt->trace.push_back(sbuf[k]); if(lastVirtualChannel != NULL) { lastVirtualChannel->trace[k] += sbuf[k]; } } buf += traceLength / 2; } eventList.push_back(currentEvt); numEvents++; } while(buf < bufStart + *bufLen); } else { // if buffer has data