CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_3/src/EventFilter/StorageManager/src/SMWebPageHelper.cc

Go to the documentation of this file.
00001 // $Id: SMWebPageHelper.cc,v 1.8 2012/04/23 08:37:24 mommsen Exp $
00003 
00004 #include <iomanip>
00005 #include <iostream>
00006 #include <sstream>
00007 #include <stdio.h>
00008 
00009 #include "boost/lexical_cast.hpp"
00010 
00011 #include "EventFilter/StorageManager/interface/AlarmHandler.h"
00012 #include "EventFilter/StorageManager/interface/EventConsumerMonitorCollection.h"
00013 #include "EventFilter/StorageManager/interface/FilesMonitorCollection.h"
00014 #include "EventFilter/StorageManager/interface/FragmentMonitorCollection.h"
00015 #include "EventFilter/StorageManager/interface/MonitoredQuantity.h"
00016 #include "EventFilter/StorageManager/interface/RegistrationCollection.h"
00017 #include "EventFilter/StorageManager/interface/ResourceMonitorCollection.h"
00018 #include "EventFilter/StorageManager/interface/RunMonitorCollection.h"
00019 #include "EventFilter/StorageManager/interface/StreamsMonitorCollection.h"
00020 #include "EventFilter/StorageManager/interface/SMWebPageHelper.h"
00021 #include "EventFilter/StorageManager/interface/XHTMLMonitor.h"
00022 #include "EventFilter/StorageManager/src/ConsumerWebPageHelper.icc"
00023 
00024 #include "toolbox/net/Utils.h"
00025 
00026 
00027 namespace stor
00028 {
00029 
00030   SMWebPageHelper::SMWebPageHelper
00031   (
00032     xdaq::ApplicationDescriptor* appDesc,
00033     SharedResourcesPtr sharedResources
00034   ) :
00035   WebPageHelper<SMWebPageHelper>(appDesc, "$Name: V08-10-00 $", this, &stor::SMWebPageHelper::addDOMforHyperLinks),
00036   sharedResources_(sharedResources),
00037   consumerWebPageHelper_(appDesc, "$Name: V08-10-00 $", this, &stor::SMWebPageHelper::addDOMforHyperLinks)
00038   {}
00039 
00040 
00041   void SMWebPageHelper::defaultWebPage(xgi::Output *out) const
00042   {
00043     XHTMLMonitor theMonitor;
00044     XHTMLMaker maker;
00045     
00046     StatisticsReporterPtr statReporter = sharedResources_->statisticsReporter_;
00047     
00048     // Create the body with the standard header
00049     XHTMLMaker::Node* body = createWebPageBody(maker, "Main",
00050       statReporter->getStateMachineMonitorCollection());
00051     
00052     // Run and event summary
00053     addDOMforRunMonitor(maker, body, statReporter->getRunMonitorCollection());
00054     
00055     // Resource usage
00056     addDOMforResourceUsage(maker, body, 
00057       statReporter->getResourceMonitorCollection(),
00058       statReporter->getThroughputMonitorCollection());
00059     
00060     // Summary
00061     addDOMforSummaryInformation(maker, body,
00062       statReporter->getDataSenderMonitorCollection(),
00063       statReporter->getStreamsMonitorCollection(),
00064       statReporter->getEventConsumerMonitorCollection(),
00065       statReporter->getDQMEventMonitorCollection(),
00066       sharedResources_->registrationCollection_);
00067     
00068     addDOMforHyperLinks(maker, body);
00069     
00070     // Dump the webpage to the output stream
00071     maker.out(*out);
00072   }
00073   
00074   
00075   void SMWebPageHelper::inputWebPage(xgi::Output *out) const
00076   {
00077     XHTMLMonitor theMonitor;
00078     XHTMLMaker maker;
00079 
00080     StatisticsReporterPtr statReporter = sharedResources_->statisticsReporter_;
00081     
00082     // Create the body with the standard header
00083     XHTMLMaker::Node* body = createWebPageBody(maker, "Input",
00084       statReporter->getStateMachineMonitorCollection());
00085     
00086     // Add the received data statistics table
00087     addDOMforFragmentMonitor(maker, body,
00088       statReporter->getFragmentMonitorCollection());
00089     
00090     addDOMforHyperLinks(maker, body);
00091     
00092     // Dump the webpage to the output stream
00093     maker.out(*out);
00094   }
00095   
00096   
00097   void SMWebPageHelper::storedDataWebPage(xgi::Output *out) const
00098   {
00099     XHTMLMonitor theMonitor;
00100     XHTMLMaker maker;
00101     
00102     StatisticsReporterPtr statReporter = sharedResources_->statisticsReporter_;
00103     
00104     // Create the body with the standard header
00105     XHTMLMaker::Node* body = createWebPageBody(maker, "Stored Data",
00106       statReporter->getStateMachineMonitorCollection());
00107     
00108     addDOMforStoredData(maker, body, statReporter->getStreamsMonitorCollection());
00109     
00110     maker.addNode("hr", body);
00111     
00112     addDOMforConfigString(maker, body, sharedResources_->configuration_->getDiskWritingParams());  
00113     
00114     addDOMforHyperLinks(maker, body);
00115     
00116     // Dump the webpage to the output stream
00117     maker.out(*out);
00118   }
00119   
00120   
00121   void SMWebPageHelper::filesWebPage(xgi::Output *out) const
00122   {
00123     XHTMLMonitor theMonitor;
00124     XHTMLMaker maker;
00125     
00126     StatisticsReporterPtr statReporter = sharedResources_->statisticsReporter_;
00127     
00128     // Create the body with the standard header
00129     XHTMLMaker::Node* body = createWebPageBody(maker, "Files",
00130       statReporter->getStateMachineMonitorCollection());
00131     
00132     addDOMforFiles(maker, body, statReporter->getFilesMonitorCollection());  
00133     
00134     addDOMforHyperLinks(maker, body);
00135     
00136     // Dump the webpage to the output stream
00137     maker.out(*out);
00138   }
00139   
00140   
00141   void SMWebPageHelper::consumerStatistics(xgi::Output *out) const
00142   {
00143     const StateMachineMonitorCollection& stateMachineMonitorCollection =
00144       sharedResources_->statisticsReporter_->getStateMachineMonitorCollection();
00145 
00146     std::string errorMsg;
00147     stateMachineMonitorCollection.statusMessage(errorMsg);
00148 
00149     consumerWebPageHelper_.consumerStatistics(out,
00150       stateMachineMonitorCollection.externallyVisibleState(),
00151       stateMachineMonitorCollection.innerStateName(),
00152       errorMsg,
00153       sharedResources_->statisticsReporter_,
00154       sharedResources_->registrationCollection_,
00155       sharedResources_->eventQueueCollection_,
00156       sharedResources_->dqmEventQueueCollection_
00157     );
00158   }
00159   
00160   
00161   void SMWebPageHelper::resourceBrokerOverview(xgi::Output *out) const
00162   {
00163     XHTMLMonitor theMonitor;
00164     XHTMLMaker maker;
00165     
00166     StatisticsReporterPtr statReporter = sharedResources_->statisticsReporter_;
00167     
00168     // Create the body with the standard header
00169     XHTMLMaker::Node* body = createWebPageBody(maker, "Resource Broker Overview",
00170       statReporter->getStateMachineMonitorCollection());
00171     
00172     addOutputModuleTables(maker, body,
00173       statReporter->getDataSenderMonitorCollection());  
00174     
00175     maker.addNode("hr", body);
00176     
00177     addResourceBrokerList(maker, body,
00178       statReporter->getDataSenderMonitorCollection());
00179     
00180     addDOMforHyperLinks(maker, body);
00181     
00182     // Dump the webpage to the output stream
00183     maker.out(*out);
00184   }
00185   
00186   
00187   void SMWebPageHelper::resourceBrokerDetail
00188   (
00189     xgi::Output *out,
00190     const long long& uniqueRBID
00191   ) const
00192   {
00193     XHTMLMonitor theMonitor;
00194     XHTMLMaker maker;
00195     
00196     StatisticsReporterPtr statReporter = sharedResources_->statisticsReporter_;
00197     
00198     // Create the body with the standard header
00199     std::ostringstream pageTitle;
00200     pageTitle << "Resource Broker " << uniqueRBID << " Detail";
00201     XHTMLMaker::Node* body = createWebPageBody(maker, pageTitle.str(),
00202       statReporter->getStateMachineMonitorCollection());
00203     
00204     addResourceBrokerDetails(maker, body, uniqueRBID,
00205       statReporter->getDataSenderMonitorCollection());  
00206     
00207     addOutputModuleStatistics(maker, body, uniqueRBID,
00208       statReporter->getDataSenderMonitorCollection());  
00209     
00210     addFilterUnitList(maker, body, uniqueRBID,
00211       statReporter->getDataSenderMonitorCollection());  
00212     
00213     addDOMforHyperLinks(maker, body);
00214     
00215     // Dump the webpage to the output stream
00216     maker.out(*out);
00217   }
00218   
00219   
00220   void SMWebPageHelper::dqmEventWebPage(xgi::Output* out) const
00221   {
00222     XHTMLMonitor theMonitor;
00223     XHTMLMaker maker;
00224     
00225     StatisticsReporterPtr statReporter = sharedResources_->statisticsReporter_;
00226     
00227     // Create the body with the standard header
00228     XHTMLMaker::Node* body = createWebPageBody(maker, "DQM Event Processor",
00229       statReporter->getStateMachineMonitorCollection());
00230     
00231     addDOMforProcessedDQMEvents(maker, body, statReporter->getDQMEventMonitorCollection());  
00232     addDOMforDQMEventStatistics(maker, body, statReporter->getDQMEventMonitorCollection());  
00233     
00234     addDOMforHyperLinks(maker, body);
00235     
00236     // Dump the webpage to the output stream
00237     maker.out(*out);
00238   }
00239   
00240   
00241   void SMWebPageHelper::throughputWebPage(xgi::Output *out) const
00242   {
00243     XHTMLMonitor theMonitor;
00244     XHTMLMaker maker;
00245     
00246     StatisticsReporterPtr statReporter = sharedResources_->statisticsReporter_;
00247     
00248     // Create the body with the standard header
00249     XHTMLMaker::Node* body = createWebPageBody(maker, "Throughput",
00250       statReporter->getStateMachineMonitorCollection());
00251     
00252     addDOMforThroughputStatistics(maker, body, statReporter->getThroughputMonitorCollection());  
00253     
00254     addDOMforHyperLinks(maker, body);
00255     
00256     // Dump the webpage to the output stream
00257     maker.out(*out);
00258   }
00259   
00260   
00261   XHTMLMaker::Node* SMWebPageHelper::createWebPageBody
00262   (
00263     XHTMLMaker& maker,
00264     const std::string& pageTitle,
00265     const StateMachineMonitorCollection& stateMachineMonitorCollection
00266   ) const
00267   {
00268     std::string errorMsg;
00269     stateMachineMonitorCollection.statusMessage(errorMsg);
00270     
00271     return WebPageHelper<SMWebPageHelper>::createWebPageBody(
00272       maker,
00273       pageTitle,
00274       stateMachineMonitorCollection.externallyVisibleState(),
00275       stateMachineMonitorCollection.innerStateName(),
00276       errorMsg
00277     );
00278   }
00279   
00280   
00281   void SMWebPageHelper::addDOMforHyperLinks
00282   (
00283     XHTMLMaker& maker,
00284     XHTMLMaker::Node *parent
00285   ) const
00286   {
00287     std::string url = appDescriptor_->getContextDescriptor()->getURL()
00288       + "/" + appDescriptor_->getURN();
00289     
00290     XHTMLMaker::AttrMap linkAttr;
00291     XHTMLMaker::Node *link;
00292     
00293     maker.addNode("hr", parent);
00294     
00295     linkAttr[ "href" ] = url;
00296     link = maker.addNode("a", parent, linkAttr);
00297     maker.addText(link, "Main web page");
00298     
00299     maker.addNode("hr", parent);
00300     
00301     linkAttr[ "href" ] = url + "/input";
00302     link = maker.addNode("a", parent, linkAttr);
00303     maker.addText(link, "I2O input web page");
00304     
00305     maker.addNode("hr", parent);
00306     
00307     linkAttr[ "href" ] = url + "/storedData";
00308     link = maker.addNode("a", parent, linkAttr);
00309     maker.addText(link, "Stored data web page");
00310     
00311     maker.addNode("hr", parent);
00312     
00313     linkAttr[ "href" ] = url + "/rbsenderlist";
00314     link = maker.addNode("a", parent, linkAttr);
00315     maker.addText(link, "RB Sender list web page");
00316     
00317     maker.addNode("hr", parent);
00318     
00319     linkAttr[ "href" ] = url + "/fileStatistics";
00320     link = maker.addNode("a", parent, linkAttr);
00321     maker.addText(link, "File Statistics web page");
00322     
00323     maker.addNode("hr", parent);
00324     
00325     linkAttr[ "href" ] = url + "/consumerStatistics";
00326     link = maker.addNode("a", parent, linkAttr);
00327     maker.addText(link, "Consumer Statistics");
00328     
00329     maker.addNode("hr", parent);
00330     
00331     linkAttr[ "href" ] = url + "/dqmEventStatistics";
00332     link = maker.addNode("a", parent, linkAttr);
00333     maker.addText(link, "DQM event processor statistics");
00334     
00335     maker.addNode("hr", parent);
00336     
00337     linkAttr[ "href" ] = url + "/throughputStatistics";
00338     link = maker.addNode("a", parent, linkAttr);
00339     maker.addText(link, "Throughput statistics");
00340     
00341     maker.addNode("hr", parent);
00342   }
00343   
00344   
00345   void SMWebPageHelper::addDOMforResourceUsage
00346   (
00347     XHTMLMaker& maker,
00348     XHTMLMaker::Node *parent,
00349     ResourceMonitorCollection const& rmc,
00350     ThroughputMonitorCollection const& tmc
00351   ) const
00352   {
00353     ResourceMonitorCollection::Stats rmcStats;
00354     rmc.getStats(rmcStats);
00355     
00356     ThroughputMonitorCollection::Stats tmcStats;
00357     tmc.getStats(tmcStats,10);
00358     
00359     XHTMLMaker::AttrMap halfWidthAttr;
00360     halfWidthAttr[ "width" ] = "50%";
00361     
00362     XHTMLMaker::Node* table = maker.addNode("table", parent, tableAttr_);
00363     
00364     XHTMLMaker::Node* tableRow = maker.addNode("tr", table, rowAttr_);
00365     
00366     XHTMLMaker::Node* tableDiv = maker.addNode("td", tableRow, halfWidthAttr);
00367     addTableForResourceUsages(maker, tableDiv, tmcStats, rmcStats);
00368     
00369     tableDiv = maker.addNode("td", tableRow, halfWidthAttr);
00370     addTableForDiskUsages(maker, tableDiv, rmcStats);
00371   }
00372   
00373   
00374   void SMWebPageHelper::addTableForResourceUsages
00375   (
00376     XHTMLMaker& maker,
00377     XHTMLMaker::Node *parent,
00378     ThroughputMonitorCollection::Stats const& tmcStats,
00379     ResourceMonitorCollection::Stats const& rmcStats
00380   ) const
00381   {
00382     XHTMLMaker::AttrMap colspanAttr;
00383     colspanAttr[ "colspan" ] = "2";
00384     
00385     XHTMLMaker::Node* table = maker.addNode("table", parent, tableAttr_);
00386     XHTMLMaker::Node* tableRow = maker.addNode("tr", table, rowAttr_);
00387     XHTMLMaker::Node* tableDiv = maker.addNode("th", tableRow, colspanAttr);
00388     maker.addText(tableDiv, "Resource Usage");
00389     
00390     addRowsForThroughputUsage(maker, table, tmcStats);
00391     addRowsForWorkers(maker, table, rmcStats);
00392     addRowsForSataBeast(maker, table, rmcStats);
00393   }
00394   
00395   
00396   void SMWebPageHelper::addRowsForThroughputUsage
00397   (
00398     XHTMLMaker& maker,
00399     XHTMLMaker::Node *table,
00400     ThroughputMonitorCollection::Stats const& stats
00401   ) const
00402   {
00403     XHTMLMaker::AttrMap tableLabelAttr = tableLabelAttr_;
00404     tableLabelAttr[ "width" ] = "54%";
00405     
00406     XHTMLMaker::AttrMap tableValueAttr = tableValueAttr_;
00407     tableValueAttr[ "width" ] = "46%";
00408     
00409     // Memory pool usage
00410     XHTMLMaker::Node* tableRow = maker.addNode("tr", table, rowAttr_);
00411     XHTMLMaker::Node* tableDiv = maker.addNode("td", tableRow);
00412     maker.addText(tableDiv, "Memory pool used (kB)");
00413     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
00414     maker.addDouble( tableDiv, stats.average.poolUsage / (double)0x400, 0 );
00415 
00416     // Input thread
00417     tableRow = maker.addNode("tr", table, rowAttr_);
00418     tableDiv = maker.addNode("td", tableRow);
00419     maker.addText(tableDiv, "Input thread busy (%)");
00420     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
00421     maker.addDouble( tableDiv, stats.average.fragmentProcessorBusy, 0 );
00422 
00423     // Disk writing thread
00424     tableRow = maker.addNode("tr", table, rowAttr_);
00425     tableDiv = maker.addNode("td", tableRow);
00426     maker.addText(tableDiv, "Disk writing thread busy (%)");
00427     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
00428     maker.addDouble( tableDiv, stats.average.diskWriterBusy, 0 );
00429 
00430     // DQM summing thread
00431     tableRow = maker.addNode("tr", table, rowAttr_);
00432     tableDiv = maker.addNode("td", tableRow);
00433     maker.addText(tableDiv, "DQM summing thread busy (%)");
00434     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
00435     maker.addDouble( tableDiv, stats.average.dqmEventProcessorBusy, 0 );
00436   }
00437   
00438   
00439   void SMWebPageHelper::addRowsForWorkers
00440   (
00441     XHTMLMaker& maker,
00442     XHTMLMaker::Node *table,
00443     ResourceMonitorCollection::Stats const& stats
00444   ) const
00445   {
00446     XHTMLMaker::AttrMap tableValueAttr = tableValueAttr_;
00447     tableValueAttr[ "width" ] = "46%";
00448     
00449     // # copy worker
00450     XHTMLMaker::Node* tableRow = maker.addNode("tr", table, rowAttr_);
00451     XHTMLMaker::Node* tableDiv = maker.addNode("td", tableRow);
00452     maker.addText(tableDiv, "# CopyWorker");
00453     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
00454     maker.addInt( tableDiv, stats.numberOfCopyWorkers );
00455     
00456     // # inject worker
00457     tableRow = maker.addNode("tr", table, rowAttr_);
00458     tableDiv = maker.addNode("td", tableRow);
00459     maker.addText(tableDiv, "# InjectWorker");
00460     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
00461     maker.addInt( tableDiv, stats.numberOfInjectWorkers );
00462   }
00463   
00464   
00465   void SMWebPageHelper::addRowsForSataBeast
00466   (
00467     XHTMLMaker& maker,
00468     XHTMLMaker::Node *table,
00469     ResourceMonitorCollection::Stats const& stats
00470   ) const
00471   {
00472     XHTMLMaker::AttrMap tableValueAttr = tableValueAttr_;
00473     tableValueAttr[ "width" ] = "46%";
00474     
00475     XHTMLMaker::Node *tableRow, *tableDiv;
00476     
00477     XHTMLMaker::AttrMap warningAttr = rowAttr_;
00478     
00479     if (stats.sataBeastStatus < 0 )
00480     {
00481       warningAttr[ "bgcolor" ] = alarmColors_.find(AlarmHandler::WARNING)->second;
00482       
00483       XHTMLMaker::AttrMap colspanAttr = tableLabelAttr_;
00484       colspanAttr[ "colspan" ] = "2";
00485       
00486       tableRow = maker.addNode("tr", table, warningAttr);
00487       tableDiv = maker.addNode("td", tableRow, colspanAttr);
00488       maker.addText(tableDiv, "No SATA disks found");
00489     }
00490     else
00491     {
00492       if ( stats.sataBeastStatus > 0 )
00493         warningAttr[ "bgcolor" ] = alarmColors_.find(AlarmHandler::ERROR)->second;
00494       tableRow = maker.addNode("tr", table, warningAttr);
00495       tableDiv = maker.addNode("td", tableRow);
00496       maker.addText(tableDiv, "SATA beast status");
00497       tableDiv = maker.addNode("td", tableRow, tableValueAttr);
00498       maker.addInt( tableDiv, stats.sataBeastStatus );
00499     }
00500   }
00501   
00502   
00503   void SMWebPageHelper::addTableForDiskUsages
00504   (
00505     XHTMLMaker& maker,
00506     XHTMLMaker::Node *parent,
00507     ResourceMonitorCollection::Stats const& stats
00508   ) const
00509   {
00510     XHTMLMaker::AttrMap colspanAttr;
00511     colspanAttr[ "colspan" ] = "2";
00512     
00513     XHTMLMaker::AttrMap tableLabelAttr = tableLabelAttr_;
00514     tableLabelAttr[ "width" ] = "54%";
00515     
00516     XHTMLMaker::AttrMap tableValueAttr = tableValueAttr_;
00517     tableValueAttr[ "width" ] = "46%";
00518     
00519     XHTMLMaker::AttrMap warningAttr = rowAttr_;
00520     
00521     XHTMLMaker::Node* table = maker.addNode("table", parent, tableAttr_);
00522     XHTMLMaker::Node* tableRow = maker.addNode("tr", table, rowAttr_);
00523     XHTMLMaker::Node* tableDiv = maker.addNode("th", tableRow, colspanAttr);
00524     maker.addText(tableDiv, "Disk Space Usage");
00525     
00526     
00527     for (ResourceMonitorCollection::DiskUsageStatsPtrList::const_iterator
00528            it = stats.diskUsageStatsList.begin(),
00529            itEnd = stats.diskUsageStatsList.end();
00530          it != itEnd;
00531          ++it)
00532     {
00533       warningAttr[ "bgcolor" ] = alarmColors_.find( (*it)->alarmState )->second;
00534       tableRow = maker.addNode("tr", table, warningAttr);
00535       tableDiv = maker.addNode("td", tableRow);
00536       maker.addText(tableDiv, (*it)->pathName);
00537       tableDiv = maker.addNode("td", tableRow, tableValueAttr);
00538       if ( (*it)->diskSize > 0 )
00539       {
00540         std::ostringstream tmpString;
00541         tmpString << std::fixed << std::setprecision(0) <<
00542           (*it)->relDiskUsage << "% (" <<
00543           (*it)->absDiskUsage << " of " << 
00544           (*it)->diskSize << " GB)";
00545         maker.addText(tableDiv, tmpString.str());
00546       }
00547       else
00548       {
00549         maker.addText(tableDiv, "not mounted");
00550       }
00551     }
00552   }
00553   
00554   
00555   void SMWebPageHelper::addDOMforSummaryInformation
00556   (
00557     XHTMLMaker& maker,
00558     XHTMLMaker::Node *parent,
00559     DataSenderMonitorCollection const& dsmc,
00560     StreamsMonitorCollection const& smc,
00561     EventConsumerMonitorCollection const& ecmc,
00562     DQMEventMonitorCollection const& dmc,
00563     RegistrationCollectionPtr registrationCollection
00564   ) const
00565   {
00566     DataSenderMonitorCollection::OutputModuleResultsList resultsList =
00567       dsmc.getTopLevelOutputModuleResults();
00568 
00569     StreamsMonitorCollection::StreamRecordList streamRecords;
00570     smc.getStreamRecords(streamRecords);
00571 
00572     XHTMLMaker::AttrMap colspanAttr;
00573     colspanAttr[ "colspan" ] = "6";
00574 
00575     XHTMLMaker::AttrMap bandwidthColspanAttr;
00576     bandwidthColspanAttr[ "colspan" ] = "3";
00577 
00578     XHTMLMaker::AttrMap tableValueWidthAttr;
00579     tableValueWidthAttr[ "width" ] = "15%";
00580     
00581     XHTMLMaker::AttrMap rowspanAttr = tableValueWidthAttr;
00582     rowspanAttr[ "rowspan" ] = "2";
00583     rowspanAttr[ "valign" ] = "top";
00584     
00585     XHTMLMaker::Node* table = maker.addNode("table", parent, tableAttr_);
00586     
00587     // Summary header
00588     XHTMLMaker::Node* tableRow = maker.addNode("tr", table, rowAttr_);
00589     XHTMLMaker::Node* tableDiv = maker.addNode("th", tableRow, colspanAttr);
00590     maker.addText(tableDiv, "Data Flow Summary");
00591     
00592     // Parameter/Value header
00593     tableRow = maker.addNode("tr", table, rowAttr_);
00594     tableDiv = maker.addNode("th", tableRow, rowspanAttr);
00595     maker.addText(tableDiv, "Output Module");
00596     tableDiv = maker.addNode("th", tableRow, rowspanAttr);
00597     maker.addText(tableDiv, "Event size (kB)");
00598     tableDiv = maker.addNode("th", tableRow, rowspanAttr);
00599     maker.addText(tableDiv, "Rate (Hz)");
00600     tableDiv = maker.addNode("th", tableRow, bandwidthColspanAttr);
00601     maker.addText(tableDiv, "Bandwidth (MB/s)");
00602 
00603     tableRow = maker.addNode("tr", table, rowAttr_);
00604     tableDiv = maker.addNode("th", tableRow, tableValueWidthAttr);
00605     maker.addText(tableDiv, "Input");
00606     tableDiv = maker.addNode("th", tableRow, tableValueWidthAttr);
00607     maker.addText(tableDiv, "To disk");
00608     tableDiv = maker.addNode("th", tableRow, tableValueWidthAttr);
00609     maker.addText(tableDiv, "To consumers");
00610 
00611     
00612     if (resultsList.empty())
00613     {
00614       XHTMLMaker::AttrMap messageAttr = colspanAttr;
00615       messageAttr[ "align" ] = "center";
00616       
00617       tableRow = maker.addNode("tr", table, rowAttr_);
00618       tableDiv = maker.addNode("td", tableRow, messageAttr);
00619       maker.addText(tableDiv, "No output modules are available yet.");
00620       return;
00621     }
00622     else
00623     {
00624       double totalInputBandwidth = 0;
00625       double totalDiskBandwidth = 0;
00626       double totalConsumerBandwidth = 0;
00627 
00628       for (
00629         DataSenderMonitorCollection::OutputModuleResultsList::const_iterator
00630           it = resultsList.begin(), itEnd = resultsList.end();
00631         it != itEnd; ++it
00632       )
00633       {
00634         const std::string outputModuleLabel = (*it)->name;
00635 
00636         const double inputBandwidth =
00637           (*it)->eventStats.getValueRate(MonitoredQuantity::RECENT)/(double)0x100000;
00638         totalInputBandwidth += inputBandwidth;
00639 
00640         StreamsMonitorCollection::StreamRecordList streamRecords;
00641         double diskBandwidth = 0;
00642         if ( smc.getStreamRecordsForOutputModuleLabel(outputModuleLabel, streamRecords) )
00643         {
00644           for (
00645             StreamsMonitorCollection::StreamRecordList::const_iterator
00646               it = streamRecords.begin(), itEnd = streamRecords.end();
00647             it != itEnd; ++it
00648           )
00649           {
00650             MonitoredQuantity::Stats streamBandwidthStats;
00651             (*it)->bandwidth.getStats(streamBandwidthStats);
00652             diskBandwidth += streamBandwidthStats.getValueRate(MonitoredQuantity::RECENT);
00653           }
00654           totalDiskBandwidth += diskBandwidth;
00655         }
00656         else
00657         {
00658           diskBandwidth = -1;
00659         }
00660 
00661         const double consumerBandwidth =
00662           getServedConsumerBandwidth(outputModuleLabel,
00663             registrationCollection, ecmc);
00664         totalConsumerBandwidth += consumerBandwidth;
00665 
00666         tableRow = maker.addNode("tr", table, rowAttr_);
00667         
00668         // Output module label
00669         tableDiv = maker.addNode("td", tableRow);
00670         maker.addText(tableDiv, outputModuleLabel);
00671         
00672         // event size
00673         tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00674         maker.addDouble( tableDiv,
00675           (*it)->eventStats.getValueAverage(MonitoredQuantity::RECENT)/(double)0x400, 1 );
00676         
00677         // rate
00678         tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00679         maker.addDouble( tableDiv,
00680           (*it)->eventStats.getSampleRate(MonitoredQuantity::RECENT), 1 );
00681         
00682         // input b/w
00683         tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00684         maker.addDouble( tableDiv, inputBandwidth, 1 );
00685         
00686         // b/w to disk
00687         tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00688         if ( diskBandwidth < 0 )
00689           maker.addText( tableDiv, "not written" );
00690         else
00691           maker.addDouble( tableDiv, diskBandwidth, 1 );
00692 
00693         // b/w to consumers
00694         tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00695         maker.addDouble( tableDiv, consumerBandwidth, 1 );
00696       }
00697       
00698       // DQM
00699       DQMEventMonitorCollection::DQMEventStats dqmStats;
00700       dmc.getStats(dqmStats);
00701       
00702       tableRow = maker.addNode("tr", table, rowAttr_);
00703       tableDiv = maker.addNode("td", tableRow);
00704       maker.addText(tableDiv, "DQM histograms");
00705       
00706       // DQM event size
00707       tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00708       maker.addDouble( tableDiv,
00709         dqmStats.dqmEventSizeStats.getValueAverage(MonitoredQuantity::RECENT)/(double)0x400, 1 );
00710       
00711       // DQM rate
00712       tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00713       maker.addDouble( tableDiv,
00714         dqmStats.numberOfTopLevelFoldersStats.getSampleRate(MonitoredQuantity::RECENT), 1 );
00715       
00716       // DQM input b/w
00717       tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00718       const double dqmInputBandwidth = dqmStats.dqmEventSizeStats.getValueRate(MonitoredQuantity::RECENT);
00719       totalInputBandwidth += dqmInputBandwidth;
00720       maker.addDouble( tableDiv, dqmInputBandwidth, 1 );
00721       
00722       // DQM b/w to disk
00723       tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00724       maker.addText( tableDiv, "not written" );
00725       // const double dqmDiskBandwidth = dqmStats.writtenDQMEventSizeStats.getValueRate(MonitoredQuantity::RECENT);
00726       // totalDiskBandwidth += dqmDiskBandwidth;
00727       // maker.addDouble( tableDiv, dqmDiskBandwidth, 1 );
00728       
00729       // DQM b/w to consumers
00730       tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00731       const double dqmConsumerBandwidth = dqmStats.servedDQMEventSizeStats.getValueRate(MonitoredQuantity::RECENT);
00732       totalConsumerBandwidth += dqmConsumerBandwidth;
00733       maker.addDouble( tableDiv, dqmConsumerBandwidth, 1 );
00734       
00735       
00736       // Totals
00737       tableRow = maker.addNode("tr", table, specialRowAttr_);
00738       tableDiv = maker.addNode("td", tableRow);
00739       maker.addText(tableDiv, "Total");
00740       tableDiv = maker.addNode("td", tableRow);
00741       tableDiv = maker.addNode("td", tableRow);
00742       tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00743       maker.addDouble( tableDiv, totalInputBandwidth, 1 );
00744       tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00745       maker.addDouble( tableDiv, totalDiskBandwidth, 1 );
00746       tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00747       maker.addDouble( tableDiv, totalConsumerBandwidth, 1 );
00748     }
00749   }
00750   
00751   
00752   double SMWebPageHelper::getServedConsumerBandwidth
00753   (
00754     const std::string& label,
00755     RegistrationCollectionPtr registrationCollection,
00756     const EventConsumerMonitorCollection& eventConsumerCollection
00757   ) const
00758   {
00759     double bandwidth = 0;
00760 
00761     RegistrationCollection::ConsumerRegistrations consumers;
00762     registrationCollection->getEventConsumers(consumers);
00763 
00764     for( RegistrationCollection::ConsumerRegistrations::const_iterator
00765            it = consumers.begin(), itEnd = consumers.end();
00766          it != itEnd; ++it )
00767     {
00768       if ( (*it)->outputModuleLabel() == label )
00769       {
00770         // Events served:
00771         MonitoredQuantity::Stats servedStats;
00772         if ( eventConsumerCollection.getServed( (*it)->queueId(), servedStats ) )
00773         {
00774           bandwidth += servedStats.getValueRate(MonitoredQuantity::RECENT);
00775         }
00776       }
00777     }
00778     
00779     return ( bandwidth/(double)0x100000 );
00780   }
00781   
00782   
00783   void SMWebPageHelper::addDOMforFragmentMonitor
00784   (
00785     XHTMLMaker& maker,
00786     XHTMLMaker::Node *parent,
00787     FragmentMonitorCollection const& fmc
00788   ) const
00789   {
00790     FragmentMonitorCollection::FragmentStats stats;
00791     fmc.getStats(stats);
00792     
00793     XHTMLMaker::AttrMap colspanAttr;
00794     colspanAttr[ "colspan" ] = "4";
00795     
00796     XHTMLMaker::Node* table = maker.addNode("table", parent, tableAttr_);
00797     
00798     // Received Data Statistics header
00799     XHTMLMaker::Node* tableRow = maker.addNode("tr", table, rowAttr_);
00800     XHTMLMaker::Node* tableDiv = maker.addNode("th", tableRow, colspanAttr);
00801     maker.addText(tableDiv, "Received I2O Frames");
00802     
00803     // Parameter/Value header
00804     tableRow = maker.addNode("tr", table, rowAttr_);
00805     tableDiv = maker.addNode("th", tableRow);
00806     maker.addText(tableDiv, "Parameter");
00807     tableDiv = maker.addNode("th", tableRow);
00808     maker.addText(tableDiv, "Total");
00809     tableDiv = maker.addNode("th", tableRow);
00810     maker.addText(tableDiv, "Events");
00811     tableDiv = maker.addNode("th", tableRow);
00812     maker.addText(tableDiv, "DQM histos");
00813     
00814     addFragmentStats(maker, table, stats,  MonitoredQuantity::FULL);
00815     
00816     addFragmentStats(maker, table, stats,  MonitoredQuantity::RECENT);
00817   }
00818   
00819   void SMWebPageHelper::addFragmentStats
00820   (
00821     XHTMLMaker& maker,
00822     XHTMLMaker::Node *table,
00823     FragmentMonitorCollection::FragmentStats const& stats,
00824     const MonitoredQuantity::DataSetType dataSet
00825   ) const
00826   {
00827     // Mean performance header
00828     XHTMLMaker::Node* tableRow = maker.addNode("tr", table, rowAttr_);
00829     XHTMLMaker::Node* tableDiv = maker.addNode("th", tableRow);
00830     if ( dataSet == MonitoredQuantity::FULL )
00831       maker.addText(tableDiv, "Performance for full run");
00832     else
00833       maker.addText(tableDiv, "Recent performance for last");
00834     
00835     addDurationToTableHead(maker, tableRow,
00836       stats.allFragmentSizeStats.getDuration(dataSet));
00837     addDurationToTableHead(maker, tableRow,
00838       stats.eventFragmentSizeStats.getDuration(dataSet));
00839     addDurationToTableHead(maker, tableRow,
00840       stats.dqmEventFragmentSizeStats.getDuration(dataSet));
00841     
00842     addRowForFramesReceived(maker, table, stats, dataSet);
00843     addRowForBandwidth(maker, table, stats, dataSet);
00844     addRowForRate(maker, table, stats, dataSet);
00845     addRowForLatency(maker, table, stats, dataSet);
00846     if ( dataSet == MonitoredQuantity::FULL )
00847     {
00848       addRowForTotalVolume(maker, table, stats, dataSet);
00849     }
00850     else
00851     {
00852       addRowForMaxBandwidth(maker, table, stats, dataSet);
00853       addRowForMinBandwidth(maker, table, stats, dataSet);
00854     }
00855   }
00856   
00857   
00858   void SMWebPageHelper::addRowForFramesReceived
00859   (
00860     XHTMLMaker& maker,
00861     XHTMLMaker::Node *table,
00862     FragmentMonitorCollection::FragmentStats const& stats,
00863     const MonitoredQuantity::DataSetType dataSet
00864   ) const
00865   {
00866     XHTMLMaker::Node* tableRow = maker.addNode("tr", table, rowAttr_);
00867     XHTMLMaker::Node* tableDiv = maker.addNode("td", tableRow);
00868     maker.addText(tableDiv, "Frames Received");
00869     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00870     maker.addInt( tableDiv, stats.allFragmentSizeStats.getSampleCount(dataSet) );
00871     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00872     maker.addInt( tableDiv, stats.eventFragmentSizeStats.getSampleCount(dataSet) );
00873     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00874     maker.addInt( tableDiv, stats.dqmEventFragmentSizeStats.getSampleCount(dataSet) );
00875   }
00876   
00877   
00878   void SMWebPageHelper::addRowForBandwidth
00879   (
00880     XHTMLMaker& maker,
00881     XHTMLMaker::Node *table,
00882     FragmentMonitorCollection::FragmentStats const& stats,
00883     const MonitoredQuantity::DataSetType dataSet
00884   ) const
00885   {
00886     XHTMLMaker::Node* tableRow = maker.addNode("tr", table, rowAttr_);
00887     XHTMLMaker::Node* tableDiv = maker.addNode("td", tableRow);
00888     maker.addText(tableDiv, "Bandwidth (MB/s)");
00889     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00890     maker.addDouble( tableDiv, stats.allFragmentSizeStats.getValueRate(dataSet) );
00891     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00892     maker.addDouble( tableDiv, stats.eventFragmentSizeStats.getValueRate(dataSet) );
00893     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00894     maker.addDouble( tableDiv, stats.dqmEventFragmentSizeStats.getValueRate(dataSet) );
00895   }
00896   
00897   
00898   void SMWebPageHelper::addRowForRate
00899   (
00900     XHTMLMaker& maker,
00901     XHTMLMaker::Node *table,
00902     FragmentMonitorCollection::FragmentStats const& stats,
00903     const MonitoredQuantity::DataSetType dataSet
00904   ) const
00905   {
00906     XHTMLMaker::Node* tableRow = maker.addNode("tr", table, rowAttr_);
00907     XHTMLMaker::Node* tableDiv = maker.addNode("td", tableRow);
00908     maker.addText(tableDiv, "Rate (frames/s)");
00909     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00910     maker.addDouble( tableDiv, stats.allFragmentSizeStats.getSampleRate(dataSet) );
00911     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00912     maker.addDouble( tableDiv, stats.eventFragmentSizeStats.getSampleRate(dataSet) );
00913     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00914     maker.addDouble( tableDiv, stats.dqmEventFragmentSizeStats.getSampleRate(dataSet) );
00915   }
00916   
00917   
00918   void SMWebPageHelper::addRowForLatency
00919   (
00920     XHTMLMaker& maker,
00921     XHTMLMaker::Node *table,
00922     FragmentMonitorCollection::FragmentStats const& stats,
00923     const MonitoredQuantity::DataSetType dataSet
00924   ) const
00925   {
00926     XHTMLMaker::Node* tableRow = maker.addNode("tr", table, rowAttr_);
00927     XHTMLMaker::Node* tableDiv = maker.addNode("td", tableRow);
00928     maker.addText(tableDiv, "Latency (us/frame)");
00929     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00930     maker.addDouble( tableDiv, stats.allFragmentSizeStats.getSampleLatency(dataSet) );
00931     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00932     maker.addDouble( tableDiv, stats.eventFragmentSizeStats.getSampleLatency(dataSet) );
00933     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00934     maker.addDouble( tableDiv, stats.dqmEventFragmentSizeStats.getSampleLatency(dataSet) );
00935   }
00936   
00937   
00938   void SMWebPageHelper::addRowForTotalVolume
00939   (
00940     XHTMLMaker& maker,
00941     XHTMLMaker::Node *table,
00942     FragmentMonitorCollection::FragmentStats const& stats,
00943     const MonitoredQuantity::DataSetType dataSet
00944   ) const
00945   {
00946     XHTMLMaker::Node* tableRow = maker.addNode("tr", table, rowAttr_);
00947     XHTMLMaker::Node* tableDiv = maker.addNode("td", tableRow);
00948     maker.addText(tableDiv, "Total volume received (MB)");
00949     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00950     maker.addDouble( tableDiv, stats.allFragmentSizeStats.getValueSum(dataSet), 3 );
00951     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00952     maker.addDouble( tableDiv, stats.eventFragmentSizeStats.getValueSum(dataSet), 3 );
00953     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00954     maker.addDouble( tableDiv, stats.dqmEventFragmentSizeStats.getValueSum(dataSet), 3 );
00955   }
00956   
00957   
00958   void SMWebPageHelper::addRowForMaxBandwidth
00959   (
00960     XHTMLMaker& maker,
00961     XHTMLMaker::Node *table,
00962     FragmentMonitorCollection::FragmentStats const& stats,
00963     const MonitoredQuantity::DataSetType dataSet
00964   ) const
00965   {
00966     XHTMLMaker::Node* tableRow = maker.addNode("tr", table, rowAttr_);
00967     XHTMLMaker::Node* tableDiv = maker.addNode("td", tableRow);
00968     maker.addText(tableDiv, "Maximum Bandwidth (MB/s)");
00969     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00970     maker.addDouble( tableDiv, stats.allFragmentBandwidthStats.getValueMax(dataSet) );
00971     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00972     maker.addDouble( tableDiv, stats.eventFragmentBandwidthStats.getValueMax(dataSet) );
00973     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00974     maker.addDouble( tableDiv, stats.dqmEventFragmentBandwidthStats.getValueMax(dataSet) );
00975   }
00976   
00977   
00978   void SMWebPageHelper::addRowForMinBandwidth
00979   (
00980     XHTMLMaker& maker,
00981     XHTMLMaker::Node *table,
00982     FragmentMonitorCollection::FragmentStats const& stats,
00983     const MonitoredQuantity::DataSetType dataSet
00984   ) const
00985   {
00986     XHTMLMaker::Node* tableRow = maker.addNode("tr", table, rowAttr_);
00987     XHTMLMaker::Node* tableDiv = maker.addNode("td", tableRow);
00988     maker.addText(tableDiv, "Minimum Bandwidth (MB/s)");
00989     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00990     maker.addDouble( tableDiv, stats.allFragmentBandwidthStats.getValueMin(dataSet) );
00991     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00992     maker.addDouble( tableDiv, stats.eventFragmentBandwidthStats.getValueMin(dataSet) );
00993     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00994     maker.addDouble( tableDiv, stats.dqmEventFragmentBandwidthStats.getValueMin(dataSet) );
00995   }
00996   
00997   
00998   void SMWebPageHelper::addDOMforRunMonitor
00999   (
01000     XHTMLMaker& maker,
01001     XHTMLMaker::Node *parent,
01002     RunMonitorCollection const& rmc
01003   ) const
01004   {
01005     MonitoredQuantity::Stats eventIDsReceivedStats;
01006     rmc.getEventIDsReceivedMQ().getStats(eventIDsReceivedStats);
01007     MonitoredQuantity::Stats errorEventIDsReceivedStats;
01008     rmc.getErrorEventIDsReceivedMQ().getStats(errorEventIDsReceivedStats);
01009     MonitoredQuantity::Stats unwantedEventIDsReceivedStats;
01010     rmc.getUnwantedEventIDsReceivedMQ().getStats(unwantedEventIDsReceivedStats);
01011     MonitoredQuantity::Stats runNumbersSeenStats;
01012     rmc.getRunNumbersSeenMQ().getStats(runNumbersSeenStats);
01013     MonitoredQuantity::Stats lumiSectionsSeenStats;
01014     rmc.getLumiSectionsSeenMQ().getStats(lumiSectionsSeenStats);
01015     MonitoredQuantity::Stats eolsSeenStats;
01016     rmc.getEoLSSeenMQ().getStats(eolsSeenStats);
01017     
01018     XHTMLMaker::AttrMap colspanAttr;
01019     colspanAttr[ "colspan" ] = "6";
01020     
01021     XHTMLMaker::AttrMap tableValueAttr = tableValueAttr_;
01022     tableValueAttr[ "width" ] = "16%";
01023     
01024     XHTMLMaker::Node* table = maker.addNode("table", parent, tableAttr_);
01025     
01026     XHTMLMaker::Node* tableRow = maker.addNode("tr", table, rowAttr_);
01027     XHTMLMaker::Node* tableDiv = maker.addNode("th", tableRow, colspanAttr);
01028     maker.addText(tableDiv, "Storage Manager Statistics");
01029     
01030     // Run number and lumi section
01031     tableRow = maker.addNode("tr", table, rowAttr_);
01032     tableDiv = maker.addNode("td", tableRow);
01033     maker.addText(tableDiv, "Run number");
01034     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
01035     maker.addDouble( tableDiv, runNumbersSeenStats.getLastSampleValue(), 0 );
01036     tableDiv = maker.addNode("td", tableRow);
01037     maker.addText(tableDiv, "Current lumi section");
01038     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
01039     maker.addDouble( tableDiv, lumiSectionsSeenStats.getLastSampleValue(), 0 );
01040     tableDiv = maker.addNode("td", tableRow);
01041     maker.addText(tableDiv, "Last EoLS");
01042     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
01043     maker.addDouble( tableDiv, eolsSeenStats.getLastSampleValue(), 0 );
01044     
01045     // Total events received
01046     tableRow = maker.addNode("tr", table, specialRowAttr_);
01047     tableDiv = maker.addNode("td", tableRow);
01048     maker.addText(tableDiv, "Events received (non-unique)");
01049     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
01050     maker.addInt( tableDiv, eventIDsReceivedStats.getSampleCount() );
01051     tableDiv = maker.addNode("td", tableRow);
01052     maker.addText(tableDiv, "Error events received");
01053     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
01054     maker.addInt( tableDiv, errorEventIDsReceivedStats.getSampleCount() );
01055     tableDiv = maker.addNode("td", tableRow);
01056     maker.addText(tableDiv, "Unwanted events received");
01057     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
01058     maker.addInt( tableDiv, unwantedEventIDsReceivedStats.getSampleCount() );
01059     
01060     // Last event IDs
01061     tableRow = maker.addNode("tr", table, rowAttr_);
01062     tableDiv = maker.addNode("td", tableRow);
01063     maker.addText(tableDiv, "Last event ID");
01064     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
01065     maker.addDouble( tableDiv, eventIDsReceivedStats.getLastSampleValue(), 0 );
01066     tableDiv = maker.addNode("td", tableRow);
01067     maker.addText(tableDiv, "Last error event ID");
01068     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
01069     maker.addDouble( tableDiv, errorEventIDsReceivedStats.getLastSampleValue(), 0 );
01070     tableDiv = maker.addNode("td", tableRow);
01071     maker.addText(tableDiv, "Last unwanted event ID");
01072     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
01073     maker.addDouble( tableDiv, unwantedEventIDsReceivedStats.getLastSampleValue(), 0 );
01074   }
01075   
01076   
01077   void SMWebPageHelper::addDOMforStoredData
01078   (
01079     XHTMLMaker& maker,
01080     XHTMLMaker::Node *parent,
01081     StreamsMonitorCollection const& smc
01082   ) const
01083   {
01084     MonitoredQuantity::Stats allStreamsVolumeStats;
01085     smc.getAllStreamsVolumeMQ().getStats(allStreamsVolumeStats);
01086     
01087     XHTMLMaker::AttrMap tableValueWidthAttr;
01088     tableValueWidthAttr[ "width" ] = "11%";
01089     
01090     XHTMLMaker::AttrMap rowspanAttr = tableValueWidthAttr;
01091     rowspanAttr[ "rowspan" ] = "2";
01092     rowspanAttr[ "valign" ] = "top";
01093     
01094     XHTMLMaker::AttrMap colspanAttr;
01095     colspanAttr[ "colspan" ] = "9";
01096     
01097     XHTMLMaker::AttrMap bandwidthColspanAttr;
01098     bandwidthColspanAttr[ "colspan" ] = "4";
01099     
01100     XHTMLMaker::Node* table = maker.addNode("table", parent, tableAttr_);
01101     
01102     XHTMLMaker::Node* tableRow = maker.addNode("tr", table, rowAttr_);
01103     XHTMLMaker::Node* tableDiv = maker.addNode("th", tableRow, colspanAttr);
01104     maker.addText(tableDiv, "Stored Data Statistics");
01105     
01106     // Header
01107     tableRow = maker.addNode("tr", table, specialRowAttr_);
01108     tableDiv = maker.addNode("th", tableRow, rowspanAttr);
01109     maker.addText(tableDiv, "Stream");
01110     tableDiv = maker.addNode("th", tableRow, rowspanAttr);
01111     maker.addText(tableDiv, "Fraction to disk");
01112     tableDiv = maker.addNode("th", tableRow, rowspanAttr);
01113     maker.addText(tableDiv, "Files");
01114     tableDiv = maker.addNode("th", tableRow, rowspanAttr);
01115     maker.addText(tableDiv, "Events");
01116     tableDiv = maker.addNode("th", tableRow, rowspanAttr);
01117     maker.addText(tableDiv, "Events/s");
01118     tableDiv = maker.addNode("th", tableRow, rowspanAttr);
01119     maker.addText(tableDiv, "Volume (MB)");
01120     tableDiv = maker.addNode("th", tableRow, bandwidthColspanAttr);
01121     maker.addText(tableDiv, "Bandwidth (MB/s)");
01122     
01123     tableRow = maker.addNode("tr", table, specialRowAttr_);
01124     tableDiv = maker.addNode("th", tableRow, tableValueWidthAttr);
01125     maker.addText(tableDiv, "average");
01126     tableDiv = maker.addNode("th", tableRow, tableValueWidthAttr);
01127     maker.addText(tableDiv, "min");
01128     tableDiv = maker.addNode("th", tableRow, tableValueWidthAttr);
01129     maker.addText(tableDiv, "max");
01130     
01131     if (! smc.streamRecordsExist())
01132     {
01133       tableRow = maker.addNode("tr", table, rowAttr_);
01134       tableDiv = maker.addNode("td", tableRow, colspanAttr);
01135       maker.addText(tableDiv, "no streams available yet");
01136       return;
01137     }
01138     // Mean performance
01139     tableRow = maker.addNode("tr", table, rowAttr_);
01140     tableDiv = maker.addNode("th", tableRow, colspanAttr);
01141     {
01142       std::ostringstream tmpString;
01143       tmpString << "Mean performance for " <<
01144         allStreamsVolumeStats.getDuration().total_seconds() << " s";
01145       maker.addText(tableDiv, tmpString.str());
01146     }
01147     listStreamRecordsStats(maker, table, smc, MonitoredQuantity::FULL);
01148     
01149     
01150     // Recent performance
01151     tableRow = maker.addNode("tr", table, rowAttr_);
01152     tableDiv = maker.addNode("th", tableRow, colspanAttr);
01153     {
01154       std::ostringstream tmpString;
01155       tmpString << "Recent performance for the last " <<
01156         allStreamsVolumeStats.getDuration(MonitoredQuantity::RECENT).total_seconds() << " s";
01157       maker.addText(tableDiv, tmpString.str());
01158     }
01159     listStreamRecordsStats(maker, table, smc, MonitoredQuantity::RECENT);
01160   }
01161   
01162   
01163   void SMWebPageHelper::addDOMforConfigString
01164   (
01165     XHTMLMaker& maker,
01166     XHTMLMaker::Node *parent,
01167     DiskWritingParams const& dwParams
01168   ) const
01169   {
01170     XHTMLMaker::Node* table = maker.addNode("table", parent);
01171     XHTMLMaker::Node* tableRow = maker.addNode("tr", table, specialRowAttr_);
01172     XHTMLMaker::Node* tableDiv = maker.addNode("th", tableRow);
01173     maker.addText(tableDiv, "SM Configuration");
01174     tableRow = maker.addNode("tr", table, rowAttr_);
01175     tableDiv = maker.addNode("td", tableRow);
01176     XHTMLMaker::AttrMap textareaAttr;
01177     textareaAttr[ "rows" ] = "10";
01178     textareaAttr[ "cols" ] = "100";
01179     textareaAttr[ "scroll" ] = "yes";
01180     textareaAttr[ "readonly" ];
01181     textareaAttr[ "title" ] = "SM config";
01182     XHTMLMaker::Node* textarea = maker.addNode("textarea", tableDiv, textareaAttr);
01183     maker.addText(textarea, dwParams.streamConfiguration_);
01184   }  
01185   
01186   
01187   void SMWebPageHelper::listStreamRecordsStats
01188   (
01189     XHTMLMaker& maker,
01190     XHTMLMaker::Node *table,
01191     StreamsMonitorCollection const& smc,
01192     const MonitoredQuantity::DataSetType dataSet
01193   ) const
01194   {
01195     StreamsMonitorCollection::StreamRecordList streamRecords;
01196     smc.getStreamRecords(streamRecords);
01197     MonitoredQuantity::Stats allStreamsFileCountStats;
01198     smc.getAllStreamsFileCountMQ().getStats(allStreamsFileCountStats);
01199     MonitoredQuantity::Stats allStreamsVolumeStats;
01200     smc.getAllStreamsVolumeMQ().getStats(allStreamsVolumeStats);
01201     MonitoredQuantity::Stats allStreamsBandwidthStats;
01202     smc.getAllStreamsBandwidthMQ().getStats(allStreamsBandwidthStats);
01203     
01204     XHTMLMaker::Node *tableRow, *tableDiv;
01205     
01206     XHTMLMaker::AttrMap tableValueAttr = tableValueAttr_;
01207     tableValueAttr[ "width" ] = "11%";
01208     
01209     
01210     for (
01211       StreamsMonitorCollection::StreamRecordList::const_iterator 
01212         it = streamRecords.begin(), itEnd = streamRecords.end();
01213       it != itEnd;
01214       ++it
01215     )
01216     {
01217       MonitoredQuantity::Stats streamFileCountStats;
01218       (*it)->fileCount.getStats(streamFileCountStats);
01219       MonitoredQuantity::Stats streamVolumeStats;
01220       (*it)->volume.getStats(streamVolumeStats);
01221       MonitoredQuantity::Stats streamBandwidthStats;
01222       (*it)->bandwidth.getStats(streamBandwidthStats);
01223       
01224       
01225       tableRow = maker.addNode("tr", table, rowAttr_);
01226       tableDiv = maker.addNode("td", tableRow);
01227       maker.addText(tableDiv, (*it)->streamName);
01228       tableDiv = maker.addNode("td", tableRow);
01229       maker.addDouble(tableDiv, (*it)->fractionToDisk, 2);
01230       tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01231       maker.addInt( tableDiv, streamFileCountStats.getSampleCount(dataSet) );
01232       tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01233       maker.addInt( tableDiv, streamVolumeStats.getSampleCount(dataSet) );
01234       tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01235       maker.addDouble( tableDiv, streamVolumeStats.getSampleRate(dataSet), 1 );
01236       tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01237       maker.addDouble( tableDiv, streamVolumeStats.getValueSum(dataSet), 1 );
01238       tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01239       maker.addDouble( tableDiv, streamBandwidthStats.getValueRate(dataSet) );
01240       tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01241       maker.addDouble( tableDiv, streamBandwidthStats.getValueMin(dataSet) );
01242       tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01243       maker.addDouble( tableDiv, streamBandwidthStats.getValueMax(dataSet) );
01244     }
01245     
01246     tableRow = maker.addNode("tr", table, specialRowAttr_);
01247     tableDiv = maker.addNode("td", tableRow);
01248     maker.addText(tableDiv, "Total");
01249     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01250     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01251     maker.addInt( tableDiv, allStreamsFileCountStats.getSampleCount(dataSet) );
01252     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01253     maker.addInt( tableDiv, allStreamsVolumeStats.getSampleCount(dataSet) );
01254     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01255     maker.addDouble( tableDiv, allStreamsVolumeStats.getSampleRate(dataSet), 1 );
01256     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01257     maker.addDouble( tableDiv, allStreamsVolumeStats.getValueSum(dataSet), 1 );
01258     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01259     maker.addDouble( tableDiv, allStreamsBandwidthStats.getValueRate(dataSet) );
01260     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01261     maker.addDouble( tableDiv, allStreamsBandwidthStats.getValueMin(dataSet) );
01262     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01263     maker.addDouble( tableDiv, allStreamsBandwidthStats.getValueMax(dataSet) );
01264   }
01265   
01266   
01267   void SMWebPageHelper::addDOMforFiles
01268   (
01269     XHTMLMaker& maker,
01270     XHTMLMaker::Node *parent,
01271     FilesMonitorCollection const& fmc
01272   ) const
01273   {
01274     FilesMonitorCollection::FileRecordList fileRecords;
01275     fmc.getFileRecords(fileRecords);
01276     
01277     XHTMLMaker::AttrMap colspanAttr;
01278     colspanAttr[ "colspan" ] = "6";
01279     
01280     XHTMLMaker::AttrMap tableLabelAttr = tableLabelAttr_;
01281     tableLabelAttr[ "align" ] = "center";
01282     
01283     XHTMLMaker::AttrMap tableValueWidthAttr;
01284     tableValueWidthAttr[ "width" ] = "11%";
01285     
01286     XHTMLMaker::AttrMap tableCounterWidthAttr;
01287     tableCounterWidthAttr[ "width" ] = "5%";
01288     
01289     XHTMLMaker::Node* table = maker.addNode("table", parent, tableAttr_);
01290     
01291     XHTMLMaker::Node* tableRow = maker.addNode("tr", table, rowAttr_);
01292     XHTMLMaker::Node* tableDiv = maker.addNode("th", tableRow, colspanAttr);
01293     maker.addText(tableDiv, "File Statistics (most recent first)");
01294     
01295     // Header
01296     tableRow = maker.addNode("tr", table, specialRowAttr_);
01297     tableDiv = maker.addNode("th", tableRow, tableCounterWidthAttr);
01298     maker.addText(tableDiv, "#");
01299     tableDiv = maker.addNode("th", tableRow);
01300     maker.addText(tableDiv, "Pathname");
01301     tableDiv = maker.addNode("th", tableRow, tableValueWidthAttr);
01302     maker.addText(tableDiv, "Events");
01303     tableDiv = maker.addNode("th", tableRow, tableValueWidthAttr);
01304     maker.addText(tableDiv, "Size (Bytes)");
01305     tableDiv = maker.addNode("th", tableRow, tableValueWidthAttr);
01306     maker.addText(tableDiv, "Closing reason");
01307     tableDiv = maker.addNode("th", tableRow, tableValueWidthAttr);
01308     maker.addText(tableDiv, "Adler32");
01309     
01310     // File list
01311     if (fileRecords.empty())
01312     {
01313       tableRow = maker.addNode("tr", table, rowAttr_);
01314       tableDiv = maker.addNode("td", tableRow, colspanAttr);
01315       maker.addText(tableDiv, "no files available yet");
01316       return;
01317     }
01318     
01319     for (
01320       FilesMonitorCollection::FileRecordList::const_reverse_iterator 
01321         it = fileRecords.rbegin(), itEnd = fileRecords.rend();
01322       it != itEnd;
01323       ++it
01324     )
01325     {
01326       tableRow = maker.addNode("tr", table, rowAttr_);
01327       tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01328       maker.addInt( tableDiv, (*it)->entryCounter );
01329       tableDiv = maker.addNode("td", tableRow);
01330       maker.addText(tableDiv, (*it)->completeFileName());
01331       tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01332       maker.addInt( tableDiv, (*it)->eventCount );
01333       tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01334       maker.addInt( tableDiv, (*it)->fileSize );
01335       tableDiv = maker.addNode("td", tableRow, tableLabelAttr);
01336       maker.addText(tableDiv, (*it)->closingReason());
01337       tableDiv = maker.addNode("td", tableRow, tableLabelAttr);
01338       maker.addHex(tableDiv, (*it)->adler32);
01339     }
01340   }
01341   
01342   
01343   void SMWebPageHelper::addDOMforThroughputStatistics
01344   (
01345     XHTMLMaker& maker,
01346     XHTMLMaker::Node *parent,
01347     ThroughputMonitorCollection const& tmc
01348   ) const
01349   {
01350     XHTMLMaker::AttrMap colspanAttr;
01351     colspanAttr[ "colspan" ] = "21";
01352     
01353     XHTMLMaker::Node* table = maker.addNode("table", parent, tableAttr_);
01354     
01355     XHTMLMaker::Node* tableRow = maker.addNode("tr", table, rowAttr_);
01356     XHTMLMaker::Node* tableDiv = maker.addNode("th", tableRow, colspanAttr);
01357     maker.addText(tableDiv, "Throughput Statistics");
01358     
01359     // Header
01360     tableRow = maker.addNode("tr", table, specialRowAttr_);
01361     tableDiv = maker.addNode("th", tableRow);
01362     maker.addText(tableDiv, "Time (UTC)");
01363     tableDiv = maker.addNode("th", tableRow);
01364     maker.addText(tableDiv, "Memory pool usage (bytes)");
01365     tableDiv = maker.addNode("th", tableRow);
01366     maker.addText(tableDiv, "Instantaneous Number of Fragments in Fragment Queue");
01367     tableDiv = maker.addNode("th", tableRow);
01368     maker.addText(tableDiv, "Memory used in Fragment Queue (MB)");
01369     tableDiv = maker.addNode("th", tableRow);
01370     maker.addText(tableDiv, "Number of Fragments Popped from Fragment Queue (Hz)");
01371     tableDiv = maker.addNode("th", tableRow);
01372     maker.addText(tableDiv, "Data Rate Popped from Fragment Queue (MB/sec)");
01373     tableDiv = maker.addNode("th", tableRow);
01374     maker.addText(tableDiv, "Fragment Processor Thread Busy Percentage");
01375     tableDiv = maker.addNode("th", tableRow);
01376     maker.addText(tableDiv, "Instantaneous Number of Events in Fragment Store");
01377     tableDiv = maker.addNode("th", tableRow);
01378     maker.addText(tableDiv, "Memory used in Fragment Store (MB)");
01379     tableDiv = maker.addNode("th", tableRow);
01380     maker.addText(tableDiv, "Instantaneous Number of Events in Stream Queue");
01381     tableDiv = maker.addNode("th", tableRow);
01382     maker.addText(tableDiv, "Memory used in Stream Queue (MB)");
01383     tableDiv = maker.addNode("th", tableRow);
01384     maker.addText(tableDiv, "Number of Events Popped from Stream Queue (Hz)");
01385     tableDiv = maker.addNode("th", tableRow);
01386     maker.addText(tableDiv, "Data Rate Popped from Stream Queue (MB/sec)");
01387     tableDiv = maker.addNode("th", tableRow);
01388     maker.addText(tableDiv, "Disk Writer Thread Busy Percentage");
01389     tableDiv = maker.addNode("th", tableRow);
01390     maker.addText(tableDiv, "Number of Events Written to Disk (Hz)");
01391     tableDiv = maker.addNode("th", tableRow);
01392     maker.addText(tableDiv, "Data  Rate to Disk (MB/sec)");
01393     tableDiv = maker.addNode("th", tableRow);
01394     maker.addText(tableDiv, "Instantaneous Number of DQMEvents in DQMEvent Queue");
01395     tableDiv = maker.addNode("th", tableRow);
01396     maker.addText(tableDiv, "Memory used in DQMEvent Queue (MB)");
01397     tableDiv = maker.addNode("th", tableRow);
01398     maker.addText(tableDiv, "Number of DQMEvents Popped from DQMEvent Queue (Hz)");
01399     tableDiv = maker.addNode("th", tableRow);
01400     maker.addText(tableDiv, "Data Rate Popped from DQMEvent Queue (MB/sec)");
01401     tableDiv = maker.addNode("th", tableRow);
01402     maker.addText(tableDiv, "DQMEvent Processor Thread Busy Percentage");
01403     
01404     ThroughputMonitorCollection::Stats stats;
01405     tmc.getStats(stats);
01406     
01407     addRowForThroughputStatistics(maker, table, stats.average, true);
01408     
01409     for (ThroughputMonitorCollection::Stats::Snapshots::const_iterator
01410            it = stats.snapshots.begin(),
01411            itEnd = stats.snapshots.end();
01412          it != itEnd;
01413          ++it)
01414     {
01415       addRowForThroughputStatistics(maker, table, (*it));
01416     }
01417     
01418     addRowForThroughputStatistics(maker, table, stats.average, true);
01419   }
01420   
01421   
01422   void SMWebPageHelper::addRowForThroughputStatistics
01423   (
01424     XHTMLMaker& maker,
01425     XHTMLMaker::Node* table,
01426     const ThroughputMonitorCollection::Stats::Snapshot& snapshot,
01427     const bool isAverage
01428   ) const
01429   {
01430     XHTMLMaker::Node* tableRow = maker.addNode("tr", table, rowAttr_);
01431     XHTMLMaker::Node* tableDiv;
01432     XHTMLMaker::AttrMap tableValueAttr = tableValueAttr_;
01433     
01434     if (isAverage)
01435     {
01436       tableValueAttr[ "style" ] = "background-color: yellow;";
01437       tableDiv = maker.addNode("td", tableRow, tableValueAttr);
01438       std::ostringstream avg;
01439       avg << "<" << snapshot.duration.total_seconds() << "s>";
01440       maker.addText(tableDiv, avg.str());
01441     }
01442     else
01443     {
01444       tableDiv = maker.addNode("td", tableRow, tableLabelAttr_);
01445       maker.addText( tableDiv, utils::timeStampUTC(snapshot.absoluteTime) );
01446     }
01447     
01448     // memory pool usage
01449     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
01450     maker.addDouble( tableDiv, snapshot.poolUsage, 0 );
01451     
01452     // number of fragments in fragment queue
01453     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
01454     maker.addDouble( tableDiv, snapshot.entriesInFragmentQueue, 0 );
01455     
01456     // memory used in fragment queue
01457     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
01458     maker.addDouble( tableDiv, snapshot.memoryUsedInFragmentQueue, 1 );
01459     
01460     // number of fragments popped from fragment queue
01461     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
01462     maker.addDouble( tableDiv, snapshot.fragmentQueueRate, 0 );
01463     
01464     // data rate popped from fragment queue
01465     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
01466     maker.addDouble( tableDiv, snapshot.fragmentQueueBandwidth, 1 );
01467     
01468     // fragment processor thread busy percentage
01469     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
01470     maker.addDouble( tableDiv, snapshot.fragmentProcessorBusy, 1 );
01471     
01472     // number of events in fragment store
01473     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
01474     maker.addDouble( tableDiv, snapshot.fragmentStoreSize, 0 );
01475     
01476     // memory used in fragment store
01477     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
01478     maker.addDouble( tableDiv, snapshot.fragmentStoreMemoryUsed, 1 );
01479     
01480     // number of events in stream queue
01481     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
01482     maker.addDouble( tableDiv, snapshot.entriesInStreamQueue, 0 );
01483     
01484     // memory used in stream queue
01485     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
01486     maker.addDouble( tableDiv, snapshot.memoryUsedInStreamQueue, 1 );
01487     
01488     // number of events popped from stream queue
01489     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
01490     maker.addDouble( tableDiv, snapshot.streamQueueRate, 0 );
01491     
01492     // data rate popped from stream queue
01493     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
01494     maker.addDouble( tableDiv, snapshot.streamQueueBandwidth, 1 );
01495   
01496     // disk writer thread busy percentage
01497     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
01498     maker.addDouble( tableDiv, snapshot.diskWriterBusy, 1 );
01499   
01500     // number of events written to disk
01501     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
01502     maker.addDouble( tableDiv, snapshot.writtenEventsRate, 0 );
01503     
01504     // date rate written to disk
01505     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
01506     maker.addDouble( tableDiv, snapshot.writtenEventsBandwidth, 1 );
01507     
01508     // number of dqm events in DQMEvent queue
01509     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
01510     maker.addDouble( tableDiv, snapshot.entriesInDQMQueue, 0 );
01511     
01512     // memory used in DQMEvent queue
01513     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
01514     maker.addDouble( tableDiv, snapshot.memoryUsedInDQMQueue, 1 );
01515     
01516     // number of dqm events popped from DQMEvent queue
01517     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
01518     maker.addDouble( tableDiv, snapshot.dqmQueueRate, 0 );
01519     
01520     // data rate popped from DQMEvent queue
01521     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
01522     maker.addDouble( tableDiv, snapshot.dqmQueueBandwidth, 1 );
01523     
01524     // DQMEvent processor thread busy percentage
01525     tableDiv = maker.addNode("td", tableRow, tableValueAttr);
01526     maker.addDouble( tableDiv, snapshot.dqmEventProcessorBusy, 1 );
01527   }
01528   
01529   
01530   void SMWebPageHelper::addOutputModuleTables
01531   (
01532     XHTMLMaker& maker,
01533     XHTMLMaker::Node *parent,
01534     DataSenderMonitorCollection const& dsmc
01535   ) const
01536   {
01537     DataSenderMonitorCollection::OutputModuleResultsList resultsList =
01538       dsmc.getTopLevelOutputModuleResults();
01539     
01540     addOutputModuleSummary(maker, parent, resultsList);
01541     addOutputModuleStatistics(maker, parent, resultsList);
01542   }
01543   
01544   
01545   void SMWebPageHelper::addOutputModuleStatistics
01546   (
01547     XHTMLMaker& maker,
01548     XHTMLMaker::Node *parent,
01549     long long uniqueRBID,
01550     DataSenderMonitorCollection const& dsmc
01551   ) const
01552   {
01553     DataSenderMonitorCollection::OutputModuleResultsList resultsList =
01554       dsmc.getOutputModuleResultsForRB(uniqueRBID);
01555     
01556     addOutputModuleStatistics(maker, parent, resultsList);
01557   }
01558   
01559   
01560   void SMWebPageHelper::addOutputModuleStatistics
01561   (
01562     XHTMLMaker& maker,
01563     XHTMLMaker::Node *parent,
01564     DataSenderMonitorCollection::OutputModuleResultsList const& resultsList
01565   ) const
01566   {
01567     XHTMLMaker::AttrMap colspanAttr;
01568     colspanAttr[ "colspan" ] = "7";
01569     
01570     XHTMLMaker::Node* table = maker.addNode("table", parent, tableAttr_);
01571     
01572     XHTMLMaker::Node* tableRow = maker.addNode("tr", table, rowAttr_);
01573     XHTMLMaker::Node* tableDiv = maker.addNode("th", tableRow, colspanAttr);
01574     maker.addText(tableDiv, "Received Data Statistics (by output module)");
01575     
01576     // Header
01577     tableRow = maker.addNode("tr", table, specialRowAttr_);
01578     tableDiv = maker.addNode("th", tableRow);
01579     maker.addText(tableDiv, "Output Module");
01580     tableDiv = maker.addNode("th", tableRow);
01581     maker.addText(tableDiv, "Events");
01582     tableDiv = maker.addNode("th", tableRow);
01583     maker.addText(tableDiv, "Size (MB)");
01584     tableDiv = maker.addNode("th", tableRow);
01585     maker.addText(tableDiv, "Size/Evt (KB)");
01586     tableDiv = maker.addNode("th", tableRow);
01587     maker.addText(tableDiv, "RMS (KB)");
01588     tableDiv = maker.addNode("th", tableRow);
01589     maker.addText(tableDiv, "Min (KB)");
01590     tableDiv = maker.addNode("th", tableRow);
01591     maker.addText(tableDiv, "Max (KB)");
01592     
01593     if (resultsList.empty())
01594     {
01595       XHTMLMaker::AttrMap messageAttr = colspanAttr;
01596       messageAttr[ "align" ] = "center";
01597       
01598       tableRow = maker.addNode("tr", table, rowAttr_);
01599       tableDiv = maker.addNode("td", tableRow, messageAttr);
01600       maker.addText(tableDiv, "No output modules are available yet.");
01601       return;
01602     }
01603     else
01604     {
01605       for (unsigned int idx = 0; idx < resultsList.size(); ++idx)
01606       {
01607         std::string outputModuleLabel = resultsList[idx]->name;
01608         
01609         tableRow = maker.addNode("tr", table, rowAttr_);
01610         tableDiv = maker.addNode("td", tableRow);
01611         maker.addText(tableDiv, outputModuleLabel);
01612         tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01613         maker.addInt( tableDiv, resultsList[idx]->eventStats.getSampleCount() );
01614         tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01615         maker.addDouble( tableDiv,
01616           resultsList[idx]->eventStats.getValueSum()/(double)0x100000 );
01617         tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01618         maker.addDouble( tableDiv,
01619           resultsList[idx]->eventStats.getValueAverage()/(double)0x400 );
01620         tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01621         maker.addDouble( tableDiv,
01622           resultsList[idx]->eventStats.getValueRMS()/(double)0x400 );
01623         tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01624         maker.addDouble( tableDiv,
01625           resultsList[idx]->eventStats.getValueMin()/(double)0x400 );
01626         tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01627         maker.addDouble( tableDiv,
01628           resultsList[idx]->eventStats.getValueMax()/(double)0x400 );
01629       }
01630     }
01631   }
01632   
01633   
01634   void SMWebPageHelper::addOutputModuleSummary
01635   (
01636     XHTMLMaker& maker,
01637     XHTMLMaker::Node *parent,
01638     DataSenderMonitorCollection::OutputModuleResultsList const& resultsList
01639   ) const
01640   {
01641     XHTMLMaker::AttrMap colspanAttr;
01642     colspanAttr[ "colspan" ] = "3";
01643     
01644     XHTMLMaker::Node* table = maker.addNode("table", parent, tableAttr_);
01645     
01646     XHTMLMaker::Node* tableRow = maker.addNode("tr", table, rowAttr_);
01647     XHTMLMaker::Node* tableDiv = maker.addNode("th", tableRow, colspanAttr);
01648     maker.addText(tableDiv, "Output Module Summary");
01649     
01650     // Header
01651     tableRow = maker.addNode("tr", table, specialRowAttr_);
01652     tableDiv = maker.addNode("th", tableRow);
01653     maker.addText(tableDiv, "Name");
01654     tableDiv = maker.addNode("th", tableRow);
01655     maker.addText(tableDiv, "ID");
01656     tableDiv = maker.addNode("th", tableRow);
01657     maker.addText(tableDiv, "Header Size (bytes)");
01658     
01659     if (resultsList.empty())
01660     {
01661       XHTMLMaker::AttrMap messageAttr = colspanAttr;
01662       messageAttr[ "align" ] = "center";
01663       
01664       tableRow = maker.addNode("tr", table, rowAttr_);
01665       tableDiv = maker.addNode("td", tableRow, messageAttr);
01666       maker.addText(tableDiv, "No output modules are available yet.");
01667       return;
01668     }
01669     else
01670     {
01671       for (unsigned int idx = 0; idx < resultsList.size(); ++idx)
01672       {
01673         tableRow = maker.addNode("tr", table, rowAttr_);
01674         tableDiv = maker.addNode("td", tableRow);
01675         maker.addText(tableDiv, resultsList[idx]->name);
01676         tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01677         maker.addInt( tableDiv, resultsList[idx]->id );
01678         tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01679         maker.addInt( tableDiv, resultsList[idx]->initMsgSize );
01680       }
01681     }
01682   }
01683   
01684   
01685   void SMWebPageHelper::addResourceBrokerList
01686   (
01687     XHTMLMaker& maker,
01688     XHTMLMaker::Node *parent,
01689     DataSenderMonitorCollection const& dsmc
01690   ) const
01691   {
01692     DataSenderMonitorCollection::ResourceBrokerResultsList rbResultsList =
01693       dsmc.getAllResourceBrokerResults();
01694     std::sort(rbResultsList.begin(), rbResultsList.end(), compareRBResultPtrValues);
01695     
01696     XHTMLMaker::AttrMap colspanAttr;
01697     colspanAttr[ "colspan" ] = "15";
01698     
01699     XHTMLMaker::AttrMap tableSuspiciousValueAttr = tableValueAttr_;
01700     tableSuspiciousValueAttr[ "style" ] = "background-color: yellow;";
01701     
01702     XHTMLMaker::Node* table = maker.addNode("table", parent, tableAttr_);
01703     
01704     XHTMLMaker::Node* tableRow = maker.addNode("tr", table, rowAttr_);
01705     XHTMLMaker::Node* tableDiv = maker.addNode("th", tableRow, colspanAttr);
01706     maker.addText(tableDiv, "Data Sender Overview");
01707     
01708     // Header
01709     tableRow = maker.addNode("tr", table, specialRowAttr_);
01710     tableDiv = maker.addNode("th", tableRow);
01711     maker.addText(tableDiv, "Resource Broker URL");
01712     tableDiv = maker.addNode("th", tableRow);
01713     maker.addText(tableDiv, "RB instance");
01714     tableDiv = maker.addNode("th", tableRow);
01715     maker.addText(tableDiv, "RB TID");
01716     tableDiv = maker.addNode("th", tableRow);
01717     maker.addText(tableDiv, "# of EPs");
01718     tableDiv = maker.addNode("th", tableRow);
01719     maker.addText(tableDiv, "# of INIT messages");
01720     tableDiv = maker.addNode("th", tableRow);
01721     maker.addText(tableDiv, "# of events");
01722     tableDiv = maker.addNode("th", tableRow);
01723     maker.addText(tableDiv, "# of error events");
01724     tableDiv = maker.addNode("th", tableRow);
01725     maker.addText(tableDiv, "# of faulty events");
01726     tableDiv = maker.addNode("th", tableRow);
01727     maker.addText(tableDiv, "# of outstanding data discards");
01728     tableDiv = maker.addNode("th", tableRow);
01729     maker.addText(tableDiv, "# of DQM events");
01730     tableDiv = maker.addNode("th", tableRow);
01731     maker.addText(tableDiv, "# of faulty DQM events");
01732     tableDiv = maker.addNode("th", tableRow);
01733     maker.addText(tableDiv, "# of outstanding DQM discards");
01734     tableDiv = maker.addNode("th", tableRow);
01735     maker.addText(tableDiv, "# of ignored discards");
01736     tableDiv = maker.addNode("th", tableRow);
01737     maker.addText(tableDiv, "Recent event rate (Hz)");
01738     tableDiv = maker.addNode("th", tableRow);
01739     maker.addText(tableDiv, "Last event number received");
01740     
01741     if (rbResultsList.empty())
01742     {
01743       XHTMLMaker::AttrMap messageAttr = colspanAttr;
01744       messageAttr[ "align" ] = "center";
01745       
01746       tableRow = maker.addNode("tr", table, rowAttr_);
01747       tableDiv = maker.addNode("td", tableRow, messageAttr);
01748       maker.addText(tableDiv, "No data senders have registered yet.");
01749       return;
01750     }
01751     else
01752     {
01753       for (unsigned int idx = 0; idx < rbResultsList.size(); ++idx)
01754       {
01755         tableRow = maker.addNode("tr", table, rowAttr_);
01756         
01757         tableDiv = maker.addNode("td", tableRow);
01758         XHTMLMaker::AttrMap linkAttr;
01759         linkAttr[ "href" ] = baseURL() + "/rbsenderdetail?id=" +
01760           boost::lexical_cast<std::string>(rbResultsList[idx]->uniqueRBID);
01761         XHTMLMaker::Node* link = maker.addNode("a", tableDiv, linkAttr);
01762         maker.addText(link, rbResultsList[idx]->key.hltURL);
01763         
01764         tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01765         maker.addInt( tableDiv, rbResultsList[idx]->key.hltInstance );
01766         tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01767         maker.addInt( tableDiv, rbResultsList[idx]->key.hltTid );
01768         tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01769         maker.addInt( tableDiv, rbResultsList[idx]->filterUnitCount );
01770         tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01771         maker.addInt(tableDiv, rbResultsList[idx]->initMsgCount );
01772         tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01773         maker.addInt( tableDiv, rbResultsList[idx]->eventStats.getSampleCount() );
01774         tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01775         maker.addInt( tableDiv, rbResultsList[idx]->errorEventStats.getSampleCount() );
01776         
01777         if (rbResultsList[idx]->faultyEventStats.getSampleCount() != 0)
01778         {
01779           tableDiv = maker.addNode("td", tableRow, tableSuspiciousValueAttr);
01780         }
01781         else
01782         {
01783           tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01784         }
01785         maker.addInt( tableDiv, rbResultsList[idx]->faultyEventStats.getSampleCount() );
01786         
01787         if (rbResultsList[idx]->outstandingDataDiscardCount != 0)
01788         {
01789           tableDiv = maker.addNode("td", tableRow, tableSuspiciousValueAttr);
01790         }
01791         else
01792         {
01793           tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01794         }
01795         maker.addInt( tableDiv, rbResultsList[idx]->outstandingDataDiscardCount );
01796         
01797         tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01798         maker.addInt( tableDiv, rbResultsList[idx]->dqmEventStats.getSampleCount() );
01799         
01800         if (rbResultsList[idx]->faultyDQMEventStats.getSampleCount() != 0)
01801         {
01802           tableDiv = maker.addNode("td", tableRow, tableSuspiciousValueAttr);
01803         }
01804         else
01805         {
01806           tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01807         }
01808         maker.addInt( tableDiv, rbResultsList[idx]->faultyDQMEventStats.getSampleCount() );
01809         
01810         if (rbResultsList[idx]->outstandingDQMDiscardCount != 0)
01811         {
01812           tableDiv = maker.addNode("td", tableRow, tableSuspiciousValueAttr);
01813         }
01814         else
01815         {
01816           tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01817         }
01818         maker.addInt( tableDiv, rbResultsList[idx]->outstandingDQMDiscardCount );
01819         
01820         const int skippedDiscards = rbResultsList[idx]->skippedDiscardStats.getSampleCount();
01821         if (skippedDiscards != 0)
01822         {
01823           tableDiv = maker.addNode("td", tableRow, tableSuspiciousValueAttr);
01824         }
01825         else
01826         {
01827           tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01828         }
01829         maker.addInt( tableDiv, skippedDiscards );
01830         
01831         tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01832         maker.addDouble( tableDiv, rbResultsList[idx]->eventStats.
01833           getSampleRate(MonitoredQuantity::RECENT) );
01834         tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01835         maker.addInt( tableDiv, rbResultsList[idx]->lastEventNumber );
01836       }
01837     }
01838   }
01839   
01840 
01841   void SMWebPageHelper::addResourceBrokerDetails
01842   (
01843     XHTMLMaker& maker,
01844     XHTMLMaker::Node *parent,
01845     long long uniqueRBID,
01846     DataSenderMonitorCollection const& dsmc
01847   ) const
01848   {
01849     DataSenderMonitorCollection::RBResultPtr rbResultPtr =
01850       dsmc.getOneResourceBrokerResult(uniqueRBID);
01851     
01852     if (rbResultPtr.get() == 0)
01853     {
01854       maker.addText(parent, "The requested resource broker page is not currently available.");
01855       return;
01856     }
01857     
01858     int tmpDuration;
01859     std::string tmpText;
01860     
01861     XHTMLMaker::AttrMap colspanAttr;
01862     colspanAttr[ "colspan" ] = "2";
01863     
01864     XHTMLMaker::AttrMap tableAttr = tableAttr_;
01865     tableAttr[ "width" ] = "";
01866     
01867     XHTMLMaker::Node* table = maker.addNode("table", parent, tableAttr);
01868     
01869     XHTMLMaker::Node* tableRow = maker.addNode("tr", table, rowAttr_);
01870     XHTMLMaker::Node* tableDiv = maker.addNode("th", tableRow, colspanAttr);
01871     maker.addText(tableDiv, "Resource Broker Details");
01872     
01873     // Header
01874     tableRow = maker.addNode("tr", table, specialRowAttr_);
01875     tableDiv = maker.addNode("th", tableRow);
01876     maker.addText(tableDiv, "Parameter");
01877     tableDiv = maker.addNode("th", tableRow);
01878     maker.addText(tableDiv, "Value");
01879     
01880     tableRow = maker.addNode("tr", table, rowAttr_);
01881     tableDiv = maker.addNode("td", tableRow, tableLabelAttr_);
01882     maker.addText(tableDiv, "URL");
01883     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01884     XHTMLMaker::AttrMap linkAttr;
01885     linkAttr[ "href" ] = rbResultPtr->key.hltURL + "/urn:xdaq-application:lid=" +
01886       boost::lexical_cast<std::string>(rbResultPtr->key.hltLocalId);
01887     XHTMLMaker::Node* link = maker.addNode("a", tableDiv, linkAttr);
01888     maker.addText(link, rbResultPtr->key.hltURL);
01889     
01890     tableRow = maker.addNode("tr", table, rowAttr_);
01891     tableDiv = maker.addNode("td", tableRow, tableLabelAttr_);
01892     maker.addText(tableDiv, "Class Name");
01893     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01894     maker.addText(tableDiv, rbResultPtr->key.hltClassName);
01895     
01896     tableRow = maker.addNode("tr", table, rowAttr_);
01897     tableDiv = maker.addNode("td", tableRow, tableLabelAttr_);
01898     maker.addText(tableDiv, "Instance");
01899     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01900     maker.addInt( tableDiv, rbResultPtr->key.hltInstance );
01901     
01902     tableRow = maker.addNode("tr", table, rowAttr_);
01903     tableDiv = maker.addNode("td", tableRow, tableLabelAttr_);
01904     maker.addText(tableDiv, "Local ID");
01905     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01906     maker.addInt( tableDiv, rbResultPtr->key.hltLocalId );
01907     
01908     tableRow = maker.addNode("tr", table, rowAttr_);
01909     tableDiv = maker.addNode("td", tableRow, tableLabelAttr_);
01910     maker.addText(tableDiv, "Tid");
01911     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01912     maker.addInt( tableDiv, rbResultPtr->key.hltTid );
01913     
01914     tableRow = maker.addNode("tr", table, rowAttr_);
01915     tableDiv = maker.addNode("td", tableRow, tableLabelAttr_);
01916     maker.addText(tableDiv, "INIT Message Count");
01917     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01918     maker.addInt( tableDiv, rbResultPtr->initMsgCount );
01919     
01920     tableRow = maker.addNode("tr", table, rowAttr_);
01921     tableDiv = maker.addNode("td", tableRow, tableLabelAttr_);
01922     maker.addText(tableDiv, "Event Count");
01923     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01924     maker.addInt( tableDiv, rbResultPtr->eventStats.getSampleCount() );
01925     
01926     tableRow = maker.addNode("tr", table, rowAttr_);
01927     tableDiv = maker.addNode("td", tableRow, tableLabelAttr_);
01928     maker.addText(tableDiv, "Error Event Count");
01929     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01930     maker.addInt( tableDiv, rbResultPtr->errorEventStats.getSampleCount() );
01931     
01932     tableRow = maker.addNode("tr", table, rowAttr_);
01933     tableDiv = maker.addNode("td", tableRow, tableLabelAttr_);
01934     maker.addText(tableDiv, "Faulty Event Count");
01935     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01936     maker.addInt( tableDiv, rbResultPtr->faultyEventStats.getSampleCount() );
01937     
01938     tableRow = maker.addNode("tr", table, rowAttr_);
01939     tableDiv = maker.addNode("td", tableRow, tableLabelAttr_);
01940     maker.addText(tableDiv, "Data Discard Count");
01941     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01942     maker.addInt( tableDiv, rbResultPtr->dataDiscardStats.getSampleCount() );
01943     
01944     tableRow = maker.addNode("tr", table, rowAttr_);
01945     tableDiv = maker.addNode("td", tableRow, tableLabelAttr_);
01946     maker.addText(tableDiv, "DQM Event Count");
01947     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01948     maker.addInt( tableDiv, rbResultPtr->dqmEventStats.getSampleCount() );
01949     
01950     tableRow = maker.addNode("tr", table, rowAttr_);
01951     tableDiv = maker.addNode("td", tableRow, tableLabelAttr_);
01952     maker.addText(tableDiv, "Faulty DQM Event Count");
01953     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01954     maker.addInt( tableDiv, rbResultPtr->faultyDQMEventStats.getSampleCount() );
01955     
01956     tableRow = maker.addNode("tr", table, rowAttr_);
01957     tableDiv = maker.addNode("td", tableRow, tableLabelAttr_);
01958     maker.addText(tableDiv, "DQM Discard Count");
01959     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01960     maker.addInt( tableDiv, rbResultPtr->dqmDiscardStats.getSampleCount() );
01961     
01962     tableRow = maker.addNode("tr", table, rowAttr_);
01963     tableDiv = maker.addNode("td", tableRow, tableLabelAttr_);
01964     maker.addText(tableDiv, "Ignored Discards Count");
01965     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01966     maker.addInt( tableDiv, rbResultPtr->skippedDiscardStats.getSampleCount() );
01967     
01968     tableRow = maker.addNode("tr", table, rowAttr_);
01969     tableDiv = maker.addNode("td", tableRow, tableLabelAttr_);
01970     maker.addText(tableDiv, "Last Event Number Received");
01971     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01972     maker.addInt( tableDiv, rbResultPtr->lastEventNumber );
01973     
01974     tableRow = maker.addNode("tr", table, rowAttr_);
01975     tableDiv = maker.addNode("td", tableRow, tableLabelAttr_);
01976     maker.addText(tableDiv, "Last Run Number Received");
01977     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01978     maker.addInt( tableDiv, rbResultPtr->lastRunNumber );
01979     
01980     tableRow = maker.addNode("tr", table, rowAttr_);
01981     tableDiv = maker.addNode("td", tableRow, tableLabelAttr_);
01982     tmpDuration = rbResultPtr->eventStats.recentDuration.total_seconds();
01983     tmpText =  "Recent (" + boost::lexical_cast<std::string>(tmpDuration) +
01984       " sec) Event Rate (Hz)";
01985     maker.addText(tableDiv, tmpText);
01986     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01987     maker.addDouble( tableDiv, rbResultPtr->eventStats.recentSampleRate );
01988     
01989     tableRow = maker.addNode("tr", table, rowAttr_);
01990     tableDiv = maker.addNode("td", tableRow, tableLabelAttr_);
01991     tmpDuration = rbResultPtr->eventStats.fullDuration.total_seconds();
01992     tmpText =  "Full (" + boost::lexical_cast<std::string>(tmpDuration) +
01993       " sec) Event Rate (Hz)";
01994     maker.addText(tableDiv, tmpText);
01995     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
01996     maker.addDouble( tableDiv, rbResultPtr->eventStats.fullSampleRate );
01997   }
01998   
01999   
02000   void SMWebPageHelper::addFilterUnitList
02001   (
02002     XHTMLMaker& maker,
02003     XHTMLMaker::Node *parent,
02004     long long uniqueRBID,
02005     DataSenderMonitorCollection const& dsmc
02006   ) const
02007   {
02008     DataSenderMonitorCollection::FilterUnitResultsList fuResultsList =
02009       dsmc.getFilterUnitResultsForRB(uniqueRBID);
02010     
02011     XHTMLMaker::AttrMap colspanAttr;
02012     colspanAttr[ "colspan" ] = "13";
02013     
02014     XHTMLMaker::AttrMap tableSuspiciousValueAttr = tableValueAttr_;
02015     tableSuspiciousValueAttr[ "style" ] = "background-color: yellow;";
02016     
02017     XHTMLMaker::Node* table = maker.addNode("table", parent, tableAttr_);
02018     
02019     XHTMLMaker::Node* tableRow = maker.addNode("tr", table, rowAttr_);
02020     XHTMLMaker::Node* tableDiv = maker.addNode("th", tableRow, colspanAttr);
02021     maker.addText(tableDiv, "Filter Units");
02022     
02023     // Header
02024     tableRow = maker.addNode("tr", table, specialRowAttr_);
02025     tableDiv = maker.addNode("th", tableRow);
02026     maker.addText(tableDiv, "Process ID");
02027     tableDiv = maker.addNode("th", tableRow);
02028     maker.addText(tableDiv, "# of INIT messages");
02029     tableDiv = maker.addNode("th", tableRow);
02030     maker.addText(tableDiv, "# of events");
02031     tableDiv = maker.addNode("th", tableRow);
02032     maker.addText(tableDiv, "# of error events");
02033     tableDiv = maker.addNode("th", tableRow);
02034     maker.addText(tableDiv, "# of faulty events");
02035     tableDiv = maker.addNode("th", tableRow);
02036     maker.addText(tableDiv, "# of outstanding data discards");
02037     tableDiv = maker.addNode("th", tableRow);
02038     maker.addText(tableDiv, "# of DQM events");
02039     tableDiv = maker.addNode("th", tableRow);
02040     maker.addText(tableDiv, "# of faulty DQM events");
02041     tableDiv = maker.addNode("th", tableRow);
02042     maker.addText(tableDiv, "# of outstanding DQM discards");
02043     tableDiv = maker.addNode("th", tableRow);
02044     maker.addText(tableDiv, "# of ignored discards");
02045     tableDiv = maker.addNode("th", tableRow);
02046     maker.addText(tableDiv, "Recent event rate (Hz)");
02047     tableDiv = maker.addNode("th", tableRow);
02048     maker.addText(tableDiv, "Last event number received");
02049     tableDiv = maker.addNode("th", tableRow);
02050     maker.addText(tableDiv, "Last run number received");
02051     
02052     if (fuResultsList.empty())
02053     {
02054       XHTMLMaker::AttrMap messageAttr = colspanAttr;
02055       messageAttr[ "align" ] = "center";
02056       
02057       tableRow = maker.addNode("tr", table, rowAttr_);
02058       tableDiv = maker.addNode("td", tableRow, messageAttr);
02059       maker.addText(tableDiv, "No filter units have registered yet.");
02060       return;
02061     }
02062     else
02063     {
02064       for (unsigned int idx = 0; idx < fuResultsList.size(); ++idx)
02065       {
02066         tableRow = maker.addNode("tr", table, rowAttr_);
02067         
02068         tableDiv = maker.addNode("td", tableRow);
02069         maker.addInt( tableDiv, fuResultsList[idx]->key.fuProcessId );
02070         tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
02071         maker.addInt( tableDiv, fuResultsList[idx]->initMsgCount );
02072         tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
02073         maker.addInt( tableDiv, fuResultsList[idx]->shortIntervalEventStats.getSampleCount() );
02074         tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
02075         maker.addInt( tableDiv, fuResultsList[idx]->errorEventStats.getSampleCount() );
02076         
02077         if (fuResultsList[idx]->faultyEventStats.getSampleCount() != 0)
02078         {
02079           tableDiv = maker.addNode("td", tableRow, tableSuspiciousValueAttr);
02080         }
02081         else
02082         {
02083           tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
02084         }
02085         maker.addInt( tableDiv, fuResultsList[idx]->faultyEventStats.getSampleCount() );
02086         
02087         if (fuResultsList[idx]->outstandingDataDiscardCount != 0)
02088         {
02089           tableDiv = maker.addNode("td", tableRow, tableSuspiciousValueAttr);
02090         }
02091         else
02092         {
02093           tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
02094         }
02095         maker.addInt( tableDiv, fuResultsList[idx]->outstandingDataDiscardCount );
02096         
02097         tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
02098         maker.addInt( tableDiv, fuResultsList[idx]->dqmEventStats.getSampleCount() );
02099         
02100         if (fuResultsList[idx]->faultyDQMEventStats.getSampleCount() != 0)
02101         {
02102           tableDiv = maker.addNode("td", tableRow, tableSuspiciousValueAttr);
02103         }
02104         else
02105         {
02106           tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
02107         }
02108         maker.addInt( tableDiv, fuResultsList[idx]->faultyDQMEventStats.getSampleCount() );
02109         
02110         if (fuResultsList[idx]->outstandingDQMDiscardCount != 0)
02111         {
02112           tableDiv = maker.addNode("td", tableRow, tableSuspiciousValueAttr);
02113         }
02114         else
02115         {
02116           tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
02117         }
02118         maker.addInt( tableDiv, fuResultsList[idx]->outstandingDQMDiscardCount );
02119         
02120         const int skippedDiscards = fuResultsList[idx]->skippedDiscardStats.getSampleCount();
02121         if (skippedDiscards != 0)
02122         {
02123           tableDiv = maker.addNode("td", tableRow, tableSuspiciousValueAttr);
02124         }
02125         else
02126         {
02127           tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
02128         }
02129         maker.addInt( tableDiv, skippedDiscards );
02130         
02131         tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
02132         maker.addDouble( tableDiv, fuResultsList[idx]->shortIntervalEventStats.
02133           getSampleRate(MonitoredQuantity::RECENT) );
02134         tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
02135         maker.addInt( tableDiv, fuResultsList[idx]->lastEventNumber );
02136         tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
02137         maker.addInt( tableDiv, fuResultsList[idx]->lastRunNumber );
02138       }
02139     }
02140   }
02141  
02142 } // namespace stor
02143  
02144