docs: describe the pmdaroot process interfaces
[pcp.git] / src / pmview / stackmod.cpp
blob448b9bbdede9869e4f2261f11325803b9eb59b8e
1 /*
2 * Copyright (c) 1997 Silicon Graphics, Inc. All Rights Reserved.
3 * Copyright (c) 2009 Aconex. All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
15 #include <Inventor/SoPath.h>
16 #include <Inventor/nodes/SoBaseColor.h>
17 #include <Inventor/nodes/SoTranslation.h>
18 #include <Inventor/nodes/SoScale.h>
19 #include <Inventor/nodes/SoSeparator.h>
20 #include <Inventor/nodes/SoSelection.h>
21 #include <Inventor/nodes/SoSwitch.h>
22 #include "stackmod.h"
23 #include "modlist.h"
24 #include "launch.h"
26 #include <iostream>
27 using namespace std;
30 // Use debug flag LIBPMDA to trace stack refreshes
33 const float StackMod::theDefFillColor[] = { 0.35, 0.35, 0.35 };
34 const char StackMod::theStackId = 's';
36 StackMod::~StackMod()
40 StackMod::StackMod(MetricList *metrics, SoNode *obj, StackMod::Height height)
41 : Modulate(metrics),
42 _blocks(),
43 _switch(0),
44 _height(height),
45 _text(),
46 _selectCount(0),
47 _infoValue(0),
48 _infoMetric(0),
49 _infoInst(0)
51 int numValues = _metrics->numValues();
52 int numMetrics = _metrics->numMetrics();
53 char buf[32];
54 float initScale = 0.0;
55 int m, i, v;
57 _root = new SoSeparator;
59 if (numValues > 0) {
60 m = numValues;
61 if (_height == fixed) {
62 m++;
63 _text.append(QChar('\n'));
66 _blocks.resize(m);
67 _infoValue = m+1;
69 initScale = 1.0 / (float)numValues;
71 #ifdef PCP_DEBUG
72 if (pmDebug & DBG_TRACE_APPL2)
73 cerr << "StackMod::StackMod: numValues = "
74 << numValues << ", num of blocks = " << m << endl
75 << *_metrics;
76 #endif
78 for (m = 0, v = 0; m < numMetrics; m++) {
79 const QmcMetric &metric = _metrics->metric(m);
80 for (i = 0; i < metric.numValues(); i++, v++) {
81 StackBlock block;
83 block._sep = new SoSeparator;
84 sprintf(buf, "%c%d", theStackId, v);
85 block._sep->setName((SbName)buf);
86 _root->addChild(block._sep);
88 block._color = new SoBaseColor;
89 block._color->rgb.setValue(_errorColor.getValue());
90 block._sep->addChild(block._color);
92 block._scale = new SoScale;
93 block._scale->scaleFactor.setValue(1.0, initScale, 1.0);
94 block._sep->addChild(block._scale);
96 block._sep->addChild(obj);
98 block._state = Modulate::start;
99 block._selected = false;
101 if (_height == fixed || v < numValues - 1) {
102 block._tran = new SoTranslation();
103 block._tran->translation.setValue(0.0, initScale, 0.0);
104 _root->addChild(block._tran);
106 else {
107 block._tran = NULL;
109 _blocks[v] = block;
113 if (_height == fixed) {
114 StackBlock block;
115 block._sep = new SoSeparator;
116 _root->addChild(block._sep);
117 sprintf(buf, "%c%d", theStackId, v);
118 block._sep->setName((SbName)buf);
120 _switch = new SoSwitch();
121 _switch->whichChild.setValue(SO_SWITCH_ALL);
122 block._sep->addChild(_switch);
124 block._color = new SoBaseColor;
125 block._color->rgb.setValue(theDefFillColor);
126 _switch->addChild(block._color);
128 block._tran = NULL;
129 block._scale = new SoScale;
130 block._scale->scaleFactor.setValue(1.0, 0.0, 1.0);
131 block._state = Modulate::start;
132 block._selected = false;
133 _switch->addChild(block._scale);
135 _switch->addChild(obj);
136 _blocks[v] = block;
139 add();
142 // Invalid object
143 else {
145 _sts = -1;
147 SoBaseColor *tmpColor = new SoBaseColor();
148 tmpColor->rgb.setValue(_errorColor.getValue());
149 _root->addChild(tmpColor);
151 _root->addChild(obj);
155 void
156 StackMod::refresh(bool fetchFlag)
158 int numValues = _metrics->numValues();
159 int numMetrics = _metrics->numMetrics();
160 int m, i, v;
161 double sum = 0.0;
163 static QVector<double> values;
165 #ifdef PCP_DEBUG
166 if (pmDebug & DBG_TRACE_LIBPMDA)
167 cerr << endl << "StackMod::refresh" << endl;
168 #endif
170 if (status() < 0)
171 return;
173 if (numValues > values.size())
174 values.resize(numValues);
176 for (m = 0, v = 0; m < numMetrics; m++) {
177 QmcMetric &metric = _metrics->metric(m);
178 if (fetchFlag)
179 metric.update();
180 for (i = 0; i < metric.numValues(); i++, v++) {
182 StackBlock &block = _blocks[v];
183 double &value = values[v];
185 #ifdef PCP_DEBUG
186 if (pmDebug & DBG_TRACE_LIBPMDA)
187 cerr << '[' << v << "] ";
188 #endif
190 if (metric.error(i) <= 0) {
191 if (block._state != Modulate::error) {
192 block._color->rgb.setValue(_errorColor.getValue());
193 block._state = Modulate::error;
195 value = Modulate::theMinScale;
196 sum += value;
198 #ifdef PCP_DEBUG
199 if (pmDebug & DBG_TRACE_LIBPMDA)
200 cerr << "Error, value set to " << value << endl;
201 #endif
204 else if (block._state == Modulate::error ||
205 block._state == Modulate::start) {
206 block._state = Modulate::normal;
207 if (numMetrics == 1)
208 block._color->rgb.setValue(_metrics->color(v).getValue());
209 else
210 block._color->rgb.setValue(_metrics->color(m).getValue());
211 value = metric.value(i) * theScale;
212 if (value < theMinScale)
213 value = theMinScale;
214 sum += value;
215 #ifdef PCP_DEBUG
216 if (pmDebug & DBG_TRACE_LIBPMDA)
217 cerr << "Error->Normal, value = " << value << endl;
218 #endif
221 else {
222 value = metric.value(i) * theScale;
223 if (value < theMinScale)
224 value = theMinScale;
225 sum += value;
226 #ifdef PCP_DEBUG
227 if (pmDebug & DBG_TRACE_LIBPMDA)
228 cerr << "Normal, value = " << value << endl;
229 #endif
235 #ifdef PCP_DEBUG
236 if (pmDebug & DBG_TRACE_LIBPMDA)
237 cerr << "sum = " << sum << endl;
238 #endif
240 if (sum > theNormError && _height != util) {
241 if (_blocks[0]._state != Modulate::saturated) {
242 for (v = 0; v < numValues; v++) {
243 StackBlock &block = _blocks[v];
244 if (block._state != Modulate::error) {
245 block._color->rgb.setValue(Modulate::_saturatedColor);
246 block._state = Modulate::saturated;
251 else {
252 for (m = 0, v = 0; m < numMetrics; m++) {
253 QmcMetric &metric = _metrics->metric(m);
254 for (i = 0; i < metric.numValues(); i++, v++) {
255 StackBlock &block = _blocks[v];
256 if (block._state == Modulate::saturated) {
257 block._state = Modulate::normal;
258 if (numMetrics == 1)
259 block._color->rgb.setValue(_metrics->color(v).getValue());
260 else
261 block._color->rgb.setValue(_metrics->color(m).getValue());
267 // Scale values to the range [0,1].
268 // Ensure that each block always has the minimum height to
269 // avoid planes clashing
271 if (sum > 1.0 || _height == util) {
272 double oldSum = sum;
273 double max = 1.0 - (theMinScale * (numValues - 1));
274 sum = 0.0;
275 for (v = 0; v < numValues; v++) {
276 double &value = values[v];
277 value /= oldSum;
278 sum += value;
279 if (sum > max) {
280 value -= sum - max;
281 sum -= sum - max;
283 if (value < theMinScale)
284 value = theMinScale;
285 max += theMinScale;
289 for (v = 0; v < numValues; v++) {
291 StackBlock &block = _blocks[v];
292 double &value = values[v];
294 #ifdef PCP_DEBUG
295 if (pmDebug & DBG_TRACE_LIBPMDA)
296 cerr << '[' << v << "] scale = " << value << endl;
297 #endif
299 block._scale->scaleFactor.setValue(1.0, value, 1.0);
301 if (v < numValues-1 || _height == fixed)
302 block._tran->translation.setValue(0.0, value, 0.0);
305 if (_height == fixed) {
306 sum = 1.0 - sum;
307 if (sum >= theMinScale) {
308 _switch->whichChild.setValue(SO_SWITCH_ALL);
309 _blocks[v]._scale->scaleFactor.setValue(1.0, sum, 1.0);
311 else {
312 _switch->whichChild.setValue(SO_SWITCH_NONE);
313 _blocks[v]._scale->scaleFactor.setValue(1.0, theMinScale, 1.0);
318 void
319 StackMod::dump(QTextStream &os) const
321 int m, i, v;
323 os << "StackMod: ";
325 if (status() < 0)
326 os << "Invalid metrics: " << pmErrStr(status()) << endl;
327 else {
328 os << endl;
329 for (m = 0, v = 0; m < _metrics->numMetrics(); m++) {
330 QmcMetric &metric = _metrics->metric(m);
331 for (i = 0; i < metric.numValues(); i++, v++) {
332 os << " [" << v << "]: ";
333 if (_blocks[v]._selected == true)
334 os << '*';
335 else
336 os << ' ';
337 dumpState(os, _blocks[v]._state);
338 os << ": ";
339 metric.dump(os, true, i);
345 void
346 StackMod::infoText(QString &str, bool selected) const
348 int m = _infoMetric;
349 int i = _infoInst;
350 int v = _infoValue;
351 bool found = false;
353 if (selected && _selectCount == 1) {
354 for (m = 0, v = 0; m < _metrics->numMetrics(); m++) {
355 const QmcMetric &metric = _metrics->metric(m);
356 for (i = 0; i < metric.numValues(); i++, v++)
357 if (_blocks[v]._selected) {
358 found = true;
359 break;
361 if (found)
362 break;
366 if (v >= _blocks.size()) {
367 #ifdef PCP_DEBUG
368 if (pmDebug & DBG_TRACE_APPL2)
369 cerr << "StackMod::infoText: infoText requested but nothing selected"
370 << endl;
371 #endif
372 str = "";
374 else if (_height == fixed && v == _blocks.size() - 1) {
375 str = _text;
377 else {
378 const QmcMetric &metric = _metrics->metric(m);
379 str = metric.spec(true, true, i);
380 str.append(QChar('\n'));
382 if (_blocks[v]._state == Modulate::error)
383 str.append(theErrorText);
384 else if (_blocks[v]._state == Modulate::start)
385 str.append(theStartText);
386 else {
387 QString value;
388 str.append(value.setNum(metric.realValue(i), 'g', 4));
389 str.append(QChar(' '));
390 if (metric.desc().units().length() > 0)
391 str.append(metric.desc().units());
392 str.append(" [");
393 str.append(value.setNum(metric.value(i) * 100.0, 'g', 4));
394 str.append("% of expected max]");
399 void
400 StackMod::launch(Launch &launch, bool all) const
402 int m, i, v;
403 bool launchAll = all;
405 if (status() < 0)
406 return;
408 // If the filler block is selected, launch all metrics
409 if (!launchAll && _height == fixed &&
410 _blocks.last()._selected == true) {
411 launchAll = true;
414 if (_height == StackMod::util)
415 launch.startGroup("util");
416 else
417 launch.startGroup("stack");
419 for (m = 0, v = 0; m < _metrics->numMetrics(); m++) {
420 QmcMetric &metric = _metrics->metric(m);
421 for (i = 0; i < metric.numValues(); i++, v++) {
422 if ((_selectCount > 0 && _blocks[v]._selected == true) ||
423 _selectCount == 0 || launchAll == true) {
425 launch.addMetric(_metrics->metric(m),
426 _metrics->color(m),
432 launch.endGroup();
435 void
436 StackMod::selectAll()
438 int i;
440 if (_selectCount == _blocks.size())
441 return;
443 theModList->selectAllId(_root, _blocks.size());
445 #ifdef PCP_DEBUG
446 if (pmDebug & DBG_TRACE_APPL2)
447 cerr << "StackMod::selectAll" << endl;
448 #endif
450 for (i = 0; i < _blocks.size(); i++) {
451 if (_blocks[i]._selected == false) {
452 _selectCount++;
453 theModList->selectSingle(_blocks[i]._sep);
454 _blocks[i]._selected = true;
460 StackMod::select(SoPath *path)
462 int metric, inst, value;
464 findBlock(path, metric, inst, value, false);
465 if (value < _blocks.size() && _blocks[value]._selected == false) {
466 _blocks[value]._selected = true;
467 _selectCount++;
469 #ifdef PCP_DEBUG
470 if (pmDebug & DBG_TRACE_APPL2)
471 cerr << "StackMod::select: value = " << value
472 << ", count = " << _selectCount << endl;
473 #endif
475 return _selectCount;
479 StackMod::remove(SoPath *path)
481 int metric, inst, value;
483 findBlock(path, metric, inst, value, false);
484 if (value < _blocks.size() && _blocks[value]._selected == true) {
485 _blocks[value]._selected = false;
486 _selectCount--;
488 #ifdef PCP_DEBUG
489 if (pmDebug & DBG_TRACE_APPL2)
490 cerr << "StackMod::remove: value = " << value
491 << ", count = " << _selectCount << endl;
492 #endif
496 #ifdef PCP_DEBUG
497 else if (pmDebug & DBG_TRACE_APPL2)
498 cerr << "StackMod::remove: did not remove " << value
499 << ", count = " << _selectCount << endl;
500 #endif
502 return _selectCount;
505 void
506 StackMod::selectInfo(SoPath *path)
508 findBlock(path, _infoMetric, _infoInst, _infoValue);
511 void
512 StackMod::removeInfo(SoPath *)
514 _infoValue = _blocks.size();
515 _infoMetric = _infoInst = 0;
518 void
519 StackMod::findBlock(SoPath *path, int &metric, int &inst,
520 int &value, bool idMetric)
522 SoNode *node;
523 char *str;
524 int m, i, v;
525 char c;
527 for (i = path->getLength() - 1; i >= 0; --i) {
528 node = path->getNode(i);
529 str = (char *)(node->getName().getString());
530 if (strlen(str) && str[0] == theStackId)
531 break;
534 if (i >= 0) {
536 #ifdef PCP_DEBUG
537 if (pmDebug & DBG_TRACE_APPL2)
538 cerr << "StackMod::findBlock: stack id = " << str << endl;
539 #endif
541 sscanf(str, "%c%d", &c, &value);
543 if (value == 0 || idMetric == false) {
544 metric = 0;
545 inst = 0;
547 else {
548 m = 0;
549 v = value;
550 while (m < _metrics->numMetrics()) {
551 i = _metrics->metric(m).numValues();
552 if (v < i) {
553 metric = m;
554 inst = v;
555 break;
557 else {
558 v -= i;
559 m++;
564 else {
565 value = _blocks.size();
566 metric = inst = 0;
569 #ifdef PCP_DEBUG
570 if (pmDebug & DBG_TRACE_APPL2) {
571 cerr << "StackMod::findBlock: metric = " << metric
572 << ", inst = " << inst << ", value = " << value << endl;
574 #endif
576 return;
579 void
580 StackMod::setFillColor(const SbColor &col)
582 if (_sts >= 0 && _height == fixed)
583 _blocks.last()._color->rgb.setValue(col.getValue());
586 void
587 StackMod::setFillColor(int packedcol)
589 SbColor col;
590 float dummy = 0;
592 col.setPackedValue(packedcol, dummy);
593 setFillColor(col);