Changeset 11360


Ignore:
Timestamp:
07/12/11 15:29:14 (13 years ago)
Author:
ogrimm
Message:
Updates to make Edd more responsive with high incoming event rate
Location:
fact
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • fact/Evidence/GUI.cc

    r11088 r11360  
    1 
    21/* ============================================================
    32
     
    2827
    2928  // Check if history service available
    30   if (Hist == NULL || Hist->GetFormat() == NULL) {
     29  if (strcmp(Service, "Edd/Rate_kBSec") == 0) Format = "F";
     30  else if (Hist == NULL || Hist->GetFormat() == NULL) {
    3131        QMessageBox::warning(NULL, "Edd Message", QString("Could not retrieve history for service ") + Service ,QMessageBox::Ok);
    3232  }
     
    4444  M->setStatusBar(new QStatusBar(M));
    4545  M->setAttribute(Qt::WA_DeleteOnClose);
     46  M->setWindowTitle("Edd History - " + QString(Service));
    4647 
    4748  QWidget *W;
     
    6364  QString Status;
    6465
    65   if (Index != -1) Name = Name + "(" + QString::number(Index) + ")";
     66  if (Index != -1) Name = Name + "[" + QString::number(Index) + "]";
    6667
    6768  if (Time == -1) Status = QString("%1:  unavailable").arg(Name);
     
    8990  setFrame(false);
    9091  setAttribute(Qt::WA_DeleteOnClose);
    91   setText("connecting...");
    92  
    93   // Connect to DIM handler
    94   if (connect(Handler, SIGNAL(YEP(QString, int, QByteArray, QString, QString)), SLOT(Update(QString, int, QByteArray, QString, QString)), Qt::QueuedConnection) == false) {
    95     printf("Failed connection for %s\n", Name.toAscii().data());
    96   }
    97 
     92  QPalette Pal = palette(); 
     93  Pal.setColor(QPalette::Base, Qt::lightGray);
     94  setPalette(Pal);
     95 
    9896  // Context menu
    9997  Menu = new QMenu(this);
     
    103101
    104102  // Subscribe to service
    105   Handler->Subscribe(Name);
     103  Handler->Subscribe(Name, this, Index);
    106104}
    107105
     
    109107EddLineDisplay::~EddLineDisplay() {
    110108
    111   Handler->Unsubscribe(ServiceName);
     109  Handler->Unsubscribe(ServiceName, this);
    112110}
    113111
    114112// Update widget
    115 void EddLineDisplay::Update(QString Name, int Time, QByteArray, QString Format, QString Text) {
    116 
    117   if (ServiceName != Name) return;
     113void EddLineDisplay::Update(const QString &, int Time, const QByteArray &, const QString &Format, const QString &Text, int) {
    118114
    119115  // Check if service available
    120116  QPalette Pal = palette(); 
    121   if (!SetStatus(this, Name, Time, Format, Index)) {
     117  if (!SetStatus(this, ServiceName, Time, Format, Index)) {
    122118    setText("n/a");
    123119    Pal.setColor(QPalette::Base, Qt::lightGray);
     
    128124
    129125  // Message service backgound colour determined by severity
    130   if (Name.endsWith("/Message")) {
     126  if (ServiceName.endsWith("/Message")) {
    131127    switch (Text.section(' ', 0, 0).toInt()) {
    132128      case 0:  Pal.setColor(QPalette::Base, Qt::white); break;
     
    136132      default: break;
    137133    }
    138         Text = Text.section(' ', 1);
    139   }
    140   else if (Format[0].toUpper() != 'C' && Format != "I:1;C") Text = Text.section(' ', Index, Index);
    141 
    142   if (!ShowAsTime) setText(Text);
     134        setText(Text.section(' ', 1));
     135  }
     136  else if (!ShowAsTime) setText(Text);
    143137  else setText(QDateTime::fromTime_t(Text.toInt()).toString());
    144138
     
    162156
    163157  // If not, open new plot
    164   EddLineDisplay::MenuOpenHistory();
     158  MenuOpenHistory();
    165159}
    166160
     
    335329  connect(this, SIGNAL(legendClicked (QwtPlotItem *)), SLOT(LegendClicked(QwtPlotItem *)));
    336330 
    337   // Connect to DIM handler
    338   if (connect(Handler, SIGNAL(YEP(QString, int, QByteArray, QString, QString)), SLOT(Update(QString, int, QByteArray, QString, QString)), Qt::QueuedConnection) == false) {
    339     printf("Failed connection for %s\n", Service.toAscii().data());
    340   }
    341 
    342331  // Additonal context menu items
    343332  QAction* Action = Menu->addAction("Paste service", this, SLOT(MenuPasteService()));
     
    380369
    381370  N.Name = Name;
    382   N.Signal = NewCurve(Name+"("+QString::number(Index)+")");
     371  N.Signal = NewCurve(Name+"["+QString::number(Index)+"]");
    383372  N.Index = Index;
    384373  List.append(N);
     
    404393  }
    405394  Handler->DropHistory(Name);
    406   Handler->Subscribe(Name);
     395  Handler->Subscribe(Name, this, Index);
    407396 
    408397  SingleShot->start(100);
     
    410399
    411400// Update widget (must happen in GUI thread)
    412 void EddPlot::Update(QString Name, int Time, QByteArray, QString Format, QString Text) {
    413 
    414   for (int ItemNo=0; ItemNo<List.size(); ItemNo++) if (List[ItemNo].Name == Name) {
     401void EddPlot::Update(const QString &Name, int Time, const QByteArray &, const QString &Format, const QString &Text, int Index) {
     402
     403  for (int ItemNo=0; ItemNo<List.size(); ItemNo++) if (List[ItemNo].Name==Name && List[ItemNo].Index==Index) {
    415404
    416405        // Append data if service available
    417406        if (SetStatus(this, Name, Time, Format)) {
    418           QString Txt = Text;
    419           Txt = Txt.section(' ', List[ItemNo].Index, List[ItemNo].Index);
    420       AddPoint(ItemNo, Time, atof(Txt.toAscii().data()));
     407          //QString Txt = Text;
     408          //Txt = Txt.section(' ', List[ItemNo].Index, List[ItemNo].Index);
     409      //AddPoint(ItemNo, Time, atof(Txt.toAscii().data()));
     410      AddPoint(ItemNo, Time, atof(Text.toAscii().data()));
    421411        }
    422412
     
    479469
    480470  setAxisScale(QwtPlot::xBottom, time(NULL)-60*60, time(NULL)+60);
    481   setAxisAutoScale(QwtPlot::yLeft);
     471  //setAxisAutoScale(QwtPlot::yLeft);
    482472  replot();
    483473}
     
    486476
    487477  setAxisScale(QwtPlot::xBottom, time(NULL)-24*3600, time(NULL)+3600);
    488   setAxisAutoScale(QwtPlot::yLeft);
     478  //setAxisAutoScale(QwtPlot::yLeft);
    489479  replot();
    490480}
     
    495485
    496486  for (int i=0; i<List.size(); i++) if (List[i].Signal == Curve) {
    497     Handler->Unsubscribe(List[i].Name);
     487    Handler->Unsubscribe(List[i].Name, this);
    498488    List.removeAt(i);
    499489  }
     
    926916  Accumulate = true;
    927917 
    928   // Connect to DIM handler
    929   if (connect(Handler, SIGNAL(YEP(QString, int, QByteArray, QString, QString)), SLOT(Update(QString, int, QByteArray, QString, QString)), Qt::QueuedConnection) == false) {
    930     printf("Failed connection for %s\n", Name.toAscii().data());
    931   }
    932 
    933918  if (!Pure) {
    934919        // Get history for this service
     
    947932
    948933  // DIM client
    949   Handler->Subscribe(Name);
     934  Handler->Subscribe(Name, this);
    950935}
    951936
     
    953938EddText::~EddText() {
    954939
    955   Handler->Unsubscribe(Name);
     940  Handler->Unsubscribe(Name, this);
    956941}
    957942
    958943
    959944// Update widget (must happen in GUI thread)
    960 void EddText::Update(QString Name, int Time, QByteArray, QString Format, QString Text) {
    961 
    962   if (this->Name != Name) return;
     945void EddText::Update(const QString &, int Time, const QByteArray &, const QString &Format, const QString &Text, int) {
     946
    963947  QPalette Pal = palette(); 
    964948
     
    992976EddDim::EddDim() {
    993977
    994   Mutex = new QMutex(QMutex::Recursive);
    995978  Volume = 0;
    996979  Period = 10;
     980  Mutex = new QMutex(QMutex::Recursive);
    997981
    998982  // Timer to calculate data rates
     
    1002986
    1003987  // Connect to DIM handler
    1004   if (connect(this, SIGNAL(INT(QString, int, QByteArray, QString, QString)), SLOT(Update(QString, int, QByteArray, QString, QString))) == false) {
     988  if (connect(this, SIGNAL(INT(QString, int, QByteArray, QString)), SLOT(Update(QString, int, QByteArray, QString))) == false) {
    1005989    printf("Failed connection in EddDim()\n");
    1006990  }
    1007 
    1008   // To ensure responsiveness of GUI, subscriptions handled only when no GUI events (timeout 0)
    1009   Timer = new QTimer(this);
    1010   connect(Timer, SIGNAL(timeout()), SLOT(MakeSubscriptions()));
    1011   Timer->start();
    1012991}
    1013992
     
    1017996  QList<QString> L = HistoryList.keys();
    1018997  for(int i=0; i<L.size(); i++) delete HistoryList[L[i]].HistClass;
    1019 
    1020998  delete Mutex;
    1021999}
    10221000
    1023 // Subscribe to DIM service (actual subscription handled in worker thread below)
    1024 void EddDim::Subscribe(QString Name) {
     1001// Subscribe to DIM service
     1002void EddDim::Subscribe(QString Name, class EddWidget *Instance, int Index) {
    10251003
    10261004  // Lock before accessing list
    10271005  QMutexLocker Locker(Mutex);
    1028   WaitingList.append(Name);
    1029 }
    1030 
    1031 // Subscriptions handled only when no GUI events waiting (launched by timer, see constructor)
    1032 void EddDim::MakeSubscriptions() {
    1033 
    1034   // Lock before accessing list
    1035   QMutexLocker Locker(Mutex);
    1036 
    1037   if (WaitingList.isEmpty()) return;
    1038 
    1039   QString Name = WaitingList.first();
    1040   WaitingList.removeFirst();
    1041 
    1042   // If already subscribed to service, increase usage count
     1006
     1007  // Check if already subscribed to service
    10431008  if (ServiceList.contains(Name)) {
    1044         ServiceList[Name].Count++;
    1045         //YEP(Name, ServiceList[Name].TimeStamp, ServiceList[Name].ByteArray, ServiceList[Name].Format, ServiceList[Name].Text);
     1009        ServiceList[Name].Subscribers[Instance] = Index;
     1010        if (Index>=0 && Index<ServiceList[Name].Items.size()) Instance->Update(Name, ServiceList[Name].TimeStamp, ServiceList[Name].ByteArray, ServiceList[Name].Format, ServiceList[Name].Items[Index]);
     1011        else Instance->Update(Name, ServiceList[Name].TimeStamp, ServiceList[Name].ByteArray, ServiceList[Name].Format, ServiceList[Name].Text);
     1012
    10461013        return;
    10471014  }
     
    10501017  ServiceList[Name].ByteArray = QByteArray();
    10511018  ServiceList[Name].TimeStamp = -1;
    1052   ServiceList[Name].Count = 1;
     1019  ServiceList[Name].Subscribers[Instance] = Index;
    10531020  ServiceList[Name].DIMService = new DimStampedInfo(Name.toAscii().data(), INT_MAX, NO_LINK, this);
    10541021}
    10551022
    10561023
    1057 // Unsubsribe from DIM service
    1058 void EddDim::Unsubscribe(QString Name) {
     1024// Unsubscribe from DIM service
     1025void EddDim::Unsubscribe(QString Name, class EddWidget *Instance) {
    10591026
    10601027  // Lock before accessing list
    10611028  QMutexLocker Locker(Mutex);
    10621029
    1063   if (ServiceList.contains(Name)) ServiceList[Name].Count--;
    1064 
    1065   if (ServiceList[Name].Count == 0) {
     1030  if (!ServiceList.contains(Name)) return;
     1031 
     1032  if (ServiceList[Name].Subscribers.contains(Instance)) {
     1033        ServiceList[Name].Subscribers.remove(Instance);
     1034  }
     1035
     1036  if (ServiceList[Name].Subscribers.isEmpty()) {
    10661037        delete ServiceList[Name].DIMService;
    10671038        ServiceList.remove(Name);
    10681039        return;
    10691040  }
     1041}
     1042
     1043// Ignore service in update
     1044void EddDim::Ignore(QString Name, bool Ignore) {
     1045
     1046  QMutexLocker Locker(&IgnoreMutex);
     1047
     1048  IgnoreMap[Name] = Ignore;
    10701049}
    10711050
     
    11181097  float Rate = Volume/1024.0/Period;
    11191098  Volume = 0;
    1120   YEP("Edd/Rate_kBSec", time(NULL), QByteArray::number(Rate), "F", QString::number(Rate));
    1121 }
    1122 
    1123 // Force reemit of all buffered DIM data (work around for widget update problem)
    1124 void EddDim::ForceEmit() {
     1099
     1100  // No unlock because Mutex is recursive 
     1101  Update("Edd/Rate_kBSec", time(NULL), QByteArray((char *) &Rate, sizeof(Rate)), "F");
     1102}
     1103
     1104
     1105// Store service information for usage by Subscribe(), update statistics and emit signal to widgets
     1106void EddDim::Update(QString Name, int Time, QByteArray Data, QString Format) {
    11251107
    11261108  // Lock before accessing list
    11271109  QMutexLocker Locker(Mutex);
    11281110
    1129   QMap<QString, struct Item>::const_iterator i = ServiceList.constBegin();
    1130 
    1131   while (i != ServiceList.constEnd()) {
    1132         YEP(i.key(), i.value().TimeStamp, i.value().ByteArray, i.value().Format, i.value().Text);
    1133      ++i;
    1134   }
    1135 }
    1136 
    1137 // Store service information for usage by Subscribe(), update statistics and emit signal to widgets
    1138 void EddDim::Update(QString Name, int Time, QByteArray Data, QString Format, QString Text) {
    1139 
    1140   // Lock before accessing list
    1141   QMutexLocker Locker(Mutex);
     1111  Volume += Data.size();
    11421112
    11431113  // Store service data
    11441114  if (ServiceList.contains(Name)) {
    1145           ServiceList[Name].TimeStamp = Time;
    1146           ServiceList[Name].ByteArray = Data;
    1147           ServiceList[Name].Format = Format;
    1148           ServiceList[Name].Text = Text;
    1149   }
    1150 
    1151   // Emit signal to all widgets
    1152   YEP(Name, Time, Data, Format, Text);
    1153 }
    1154 
    1155 // Handling of DIM service update
    1156 // No locking allowed. Signal triggers only EddDim::Update() when the main event loop is idle.
     1115        ServiceList[Name].TimeStamp = Time;
     1116        ServiceList[Name].ByteArray = Data;
     1117        ServiceList[Name].Format = Format;
     1118        ServiceList[Name].Text = QString::fromStdString(EvidenceServer::ToString(Format.toAscii().data(), Data.data(), Data.size()));
     1119        ServiceList[Name].Items = ServiceList[Name].Text.split(" ");
     1120
     1121        QMap<class EddWidget *, int>::const_iterator i = ServiceList[Name].Subscribers.constBegin();
     1122        while (i != ServiceList[Name].Subscribers.constEnd()) {
     1123          if (i.value() >=0 && i.value() < ServiceList[Name].Items.size()) i.key()->Update(Name, Time, Data, Format, ServiceList[Name].Items[i.value()], i.value());
     1124          else i.key()->Update(Name, Time, Data, Format, ServiceList[Name].Text, i.value());
     1125          i++;
     1126        }
     1127  } 
     1128}
     1129
     1130// Handling of DIM service update (Data asynchronouly send to EddDim::Update())
    11571131void EddDim::infoHandler() {
    11581132
     1133  QMutexLocker Locker(&IgnoreMutex);
     1134  bool Ignore = IgnoreMap[getInfo()->getName()];
     1135  Locker.unlock();
     1136
    11591137  if (!EvidenceServer::ServiceOK(getInfo())) INT(getInfo()->getName(), -1);
    1160   else {
    1161     // Signal to EddDim::Update()
    1162         INT(getInfo()->getName(), getInfo()->getTimestamp(), QByteArray((char *) getInfo()->getData(),
    1163                 getInfo()->getSize()), getInfo()->getFormat(), QString::fromStdString(EvidenceServer::ToString(getInfo()->getFormat(), getInfo()->getData(), getInfo()->getSize())));
    1164         // No mutex protection for Volume (otherwise must be in Update())
    1165         Volume += getInfo()->getSize();
    1166   }
     1138  else if (!Ignore) INT(getInfo()->getName(), getInfo()->getTimestamp(), QByteArray((char *) getInfo()->getData(), getInfo()->getSize()), getInfo()->getFormat());
    11671139}
    11681140
  • fact/Evidence/GUI.h

    r11088 r11360  
    3434bool SetStatus(QWidget *, QString, int, QString, int = -1);
    3535
     36// General Edd Widget: has Update() method called by DIM interface
     37class EddWidget {
     38
     39  public:
     40        virtual void Update(const QString &, int, const QByteArray &, const QString &, const QString &, int=-1) = 0;
     41};
     42
    3643// Base class for Edd plot
    3744// DeleteCurve() is pure virtual and needs to be implemented iin the application class
     
    97104                 
    98105// General indicator for DIM service
    99 class EddLineDisplay: public QLineEdit {
     106class EddLineDisplay: public QLineEdit, public EddWidget {
    100107    Q_OBJECT
    101108
     
    112119       
    113120  public:
    114     EddLineDisplay(QString, int=0, QWidget * = NULL);
     121    EddLineDisplay(QString, int=-1, QWidget * = NULL);
    115122    ~EddLineDisplay();
     123        void Update(const QString &, int, const QByteArray &, const QString &, const QString &, int = -1);
    116124
    117125        bool ShowAsTime;
    118126       
    119127  private slots:
    120         void Update(QString, int, QByteArray, QString, QString);
    121128    void contextMenuEvent(QContextMenuEvent *);   
    122129    void MenuOpenHistory();
     
    143150
    144151// Graph class for history display
    145 class EddPlot: public EddBasePlot {
     152class EddPlot: public EddBasePlot, public EddWidget {
    146153    Q_OBJECT
    147154
     
    190197    void AddService(QString, int = 0);
    191198        void DeleteCurve(QwtPlotCurve *);
    192 
    193   private slots:
    194         void Update(QString, int, QByteArray, QString, QString);
     199        void Update(const QString &, int, const QByteArray &, const QString &, const QString &, int = -1);
     200
     201  private slots:
    195202        void LegendClicked(QwtPlotItem *);
    196203    void MenuPasteService();
     
    201208
    202209// Text history and output class
    203 class EddText: public QTextEdit {
     210class EddText: public QTextEdit, public EddWidget {
    204211  Q_OBJECT
    205212
     
    211218    EddText(QString, bool = false, QWidget * = NULL);
    212219    ~EddText();
     220        void Update(const QString &, int, const QByteArray &, const QString &, const QString &, int = -1);
    213221
    214222        bool Accumulate;
    215 
    216   private slots:
    217         void Update(QString, int, QByteArray, QString, QString);
    218223};
    219224
     
    226231        struct Item {
    227232          DimStampedInfo *DIMService;
    228           int Count;
     233          QMap<class EddWidget *, int> Subscribers;
    229234          int TimeStamp;
    230235          QByteArray ByteArray;
    231236          QString Format;
    232237          QString Text;
     238          QStringList Items;
    233239        };
    234240    QMap<QString, struct Item> ServiceList;
    235     QMutex *Mutex;
    236         QList<QString> WaitingList;
     241        QMap<QString, bool> IgnoreMap;
     242    QMutex *Mutex, IgnoreMutex;
    237243
    238244        struct HistItem {
     
    249255
    250256  private slots:
    251         void Update(QString, int, QByteArray, QString, QString);
     257        void Update(QString, int, QByteArray, QString);
    252258        void UpdateStatistics();
    253         void MakeSubscriptions();
    254259
    255260  public:
     
    257262    ~EddDim();
    258263
    259         void Subscribe(QString);
    260         void Unsubscribe (QString);
     264        void Subscribe(QString, class EddWidget *, int = -1);
     265        void Unsubscribe (QString, class EddWidget *);
     266        void Ignore (QString, bool);
    261267        class EvidenceHistory *GetHistory(QString);
    262268        void DropHistory(QString);
    263         void ForceEmit();
    264269
    265270  signals:
    266     void YEP(QString, int, QByteArray = QByteArray(), QString = QString(), QString = QString());
    267     void INT(QString, int, QByteArray = QByteArray(), QString = QString(), QString = QString());
     271    void INT(QString, int, QByteArray = QByteArray(), QString = QString());
    268272};
    269273
  • fact/tools/Edd/Edd.cc

    r11189 r11360  
    111111 
    112112// Update event buffer
    113 void EventScope::Update(QString Name, int Time, QByteArray Data, QString Format, QString) {
    114  
    115   if (Name != this->Name) return;
     113void EventScope::Update(const QString &, int Time, const QByteArray &Data, const QString &Format, const QString &, int) {
    116114
    117115  // Check if service available
    118116  if (!SetStatus(this, Name, Time, Format)) return;
    119117  if (Data.size() < (int) sizeof(RunHeader)) return;
    120  
    121   // Disconnect while processing to avoid queing of events
    122   disconnect(Handler, SIGNAL(YEP(QString, int, QByteArray, QString, QString)), this, SLOT(Update(QString, int, QByteArray, QString, QString)));
     118
     119  // Ignore further data while processing this one
     120  Handler->Ignore(Name, true);
    123121 
    124122  // Clear temporary file and write event data to this file
     
    132130  // Open temporary raw data file
    133131  OpenRawFile(File.fileName());
    134  
    135   // Reconnect after processing
    136   connect(Handler, SIGNAL(YEP(QString, int, QByteArray, QString, QString)), SLOT(Update(QString, int, QByteArray, QString, QString)));
     132
     133
     134  // Process all pending events, then allow data again
     135  QApplication::processEvents();
     136  Handler->Ignore(Name, false);
    137137}
    138138
     
    191191 
    192192  // Display first event
    193   NewEventNum(0);
     193  NewEventNum(DAQPage->Channel->value());
    194194}
    195195
     
    316316void EventScope::SetActive(bool State) {
    317317
    318   if (State && !Active) {
    319         Handler->Subscribe(DRSBoard+"/EventData");
    320         connect(Handler, SIGNAL(YEP(QString, int, QByteArray, QString, QString)), SLOT(Update(QString, int, QByteArray, QString, QString)));
    321   }
    322   if (!State && Active) {
    323         Handler->Unsubscribe(DRSBoard+"/EventData");
    324         disconnect(Handler, SIGNAL(YEP(QString, int, QByteArray, QString, QString)), this, SLOT(Update(QString, int, QByteArray, QString, QString)));
    325   }
     318  if (State && !Active) Handler->Subscribe(DRSBoard+"/EventData", this, -1);
     319  if (!State && Active) Handler->Unsubscribe(DRSBoard+"/EventData", this);
     320
    326321  Active = State;
    327322}
     
    929924  connect(Timer, SIGNAL(timeout()), this, SLOT(CheckAlarm()));
    930925  Timer->start(5000);
    931 
    932   // Force update of all widgets constructed (in thread for GUI responsiveness)
    933   QtConcurrent::run(Handler, &EddDim::ForceEmit);
    934926
    935927   
  • fact/tools/Edd/Edd.h

    r11088 r11360  
    1111
    1212// Event oscilloscope
    13 class EventScope: public EddBasePlot, public PixelMap {
     13class EventScope: public EddBasePlot, public PixelMap, public EddWidget {
    1414  Q_OBJECT
    1515
     
    3434    EventScope(class TP_DAQ *, QWidget * = NULL);
    3535    ~EventScope();
    36        
     36
     37        void Update(const QString &, int, const QByteArray &, const QString &, const QString &, int=-1);
    3738        void UpdateFirst(int, int, int);
    3839        void AddTrace(int, int, int);
     
    4344
    4445  private slots:
    45         void Update(QString, int, QByteArray, QString, QString);
    4646        void PlotTraces();
    4747        void DeleteCurve(QwtPlotCurve *);
Note: See TracChangeset for help on using the changeset viewer.