Re: Polymon
Dmitry Kurochkin <dmitry.kurochkin-LbpN3Auhdh+Rtz+nHKFJDvXmoG9oyoYx@public.gmane.org> Fri, 20 Jan 2012 02:34:27 +0400
| Newsgroups | gmane.comp.web.web-polygraph.user |
|---|---|
| Message-ID | <[email protected]> |
Hello Michael. I am afraid the polymon is not very well documented. I was able to reproduce the segfault you reported. The attached patch should fix it and few other problems. Also the patch adds a basic help screen (press 'h') which would hopefully help you to get started. More info regarding polymon usage can be found in the mailing list archives [1]. Regards, Dmitry [1] http://www.web-polygraph.org/mail-archive/users/199912/0069.html _______________________________________________ Users mailing list Users-mN9fGWdlm5pku/f+YMZH/di2O/[email protected] http://www.web-polygraph.org/mailman/listinfo/users
polymon-fixes_v4.0.10.patch
(text/x-diff, 23.8 KB)
polymon-fixes_v4.0.10.patch - patch for Web Polygraph v4.0.10
Various polymon improvements: few segfault fixes and basic help screen.
diff --git a/src/monitor/polymon.cc b/src/monitor/polymon.cc
index 4b70415..d349b46 100644
--- src/monitor/polymon.cc
+++ src/monitor/polymon.cc
@@ -147,73 +147,88 @@ struct HostFilter {
// used in some "matrix" windows to remember screen content
class WinMatrix {
public:
WinMatrix(int aMaxY, int aMaxX);
double operator ()(int y, int x) const { return theImage[safePos(y,x)]; }
double &operator ()(int y, int x) { return theImage[safePos(y,x)]; }
protected:
int safePos(int y, int x) const;
protected:
Array<double> theImage;
int theMaxY;
int theMaxX;
};
// WINDOW wrapper with a title and event handlers
-class Window: public WINDOW {
+class Window {
public:
typedef void (Window::*EventHandler)(const Host &);
public:
Window(const char *aTitle);
virtual ~Window();
virtual void noteAdd(const Host &) {}
virtual void noteDel(const Host &) {}
virtual void noteUpd(const Host &) {}
+ private:
+ // disable copying
+ Window(const Window &);
+ Window &operator =(const Window &);
+
public:
- const char *theTitle;
+ WINDOW *const handle;
+ const char *title;
};
// general monitor information
class InfoWindow: public Window {
public:
InfoWindow(const char *aTitle);
virtual void noteAdd(const Host &);
virtual void noteDel(const Host &);
virtual void noteUpd(const Host &);
protected:
void update();
protected:
int theMsgCnt; // msgs seen so far
int theListnCnt; // derived from CopyCnt in the fwded msg
};
+// help window
+class HelpWindow: public Window {
+ public:
+ HelpWindow();
+
+ protected:
+ void update();
+};
+
// summary information about SmxWindows
class MsgSum;
class SumWindow: public Window {
public:
SumWindow(const char *aTitle);
virtual void noteAdd(const Host &);
virtual void noteDel(const Host &);
virtual void noteUpd(const Host &);
protected:
void update();
void displaySide(int &y, int x, const MsgSum &sum);
void displayLine(int y, int x, const char *label, const AggrStat &stats, const char *meas, double scale = 1);
};
// single measurement matrix window
class SmxWindow: public Window {
public:
SmxWindow(const char *aTitle);
@@ -267,41 +282,41 @@ class MsgSum {
public:
String theLabels;
AggrStat theReqRate;
AggrStat theRepRate;
AggrStat theBwidth;
AggrStat theRespTime;
AggrStat theDHR;
AggrStat theConnUse;
AggrStat theErrRatio;
AggrStat theXactTotCnt;
AggrStat theTotErrRatio;
AggrStat theSockInstCnt;
};
/* smx windows for all attributes */
struct RunLabelSmxWin: public SmxWindow {
RunLabelSmxWin(const char *aTitle): SmxWindow(aTitle) {}
virtual void displayMsg(int y, int x, const StatusFwdMsg &msg) {
- mvwprintw(this, y, x, (char*)"%7.6s", msg.theLabel);
+ mvwprintw(handle, y, x, (char*)"%7.6s", msg.theLabel);
}
};
struct RunTimeSmxWin: public SmxWindow {
RunTimeSmxWin(const char *aTitle): SmxWindow(aTitle) {}
virtual void displayMsg(int y, int x, const StatusFwdMsg &msg);
};
struct ReqRateSmxWin: public NumxWindow {
ReqRateSmxWin(const char *aTitle): NumxWindow(aTitle, "%7.1f") {}
virtual double msg2num(const StatusFwdMsg &msg) {
return (double)msg.theReqRate;
}
};
struct RepRateSmxWin: public NumxWindow {
RepRateSmxWin(const char *aTitle): NumxWindow(aTitle, "%7.1f") {}
virtual double msg2num(const StatusFwdMsg &msg) {
return (double)msg.theRepRate;
}
@@ -374,50 +389,53 @@ class MsgGapSmxWin: public SmxWindow {
public:
MsgGapSmxWin(const char *aTitle): SmxWindow(aTitle) {}
virtual void noteUpd(const Host &host);
protected:
virtual void displayMsg(int y, int x, const StatusFwdMsg &msg);
protected:
StatusFwdMsg theLastMsg;
};
/* globals */
static NetAddr TheDisp;
static FileScanner *TheScanner = 0;
static bool DoShutdown = false;
-static Array<Host*> TheHosts;
+static PtrArray<Host*> TheHosts;
static Array<Host*> TheHostIdx; // address -> host map
static int TheBusyHostCnt = 0;
-static Array<String*> TheLabels;
+static PtrArray<String*> TheLabels;
static int TheUniqLblCnt = 0;
-static Array<Window*> TheWins;
+static PtrArray<Window*> TheWins;
static int TheWinPos = 0; // current window
static Window *TheInfoWin = 0; // special
+static Window *TheHelpWin = 0; // help window
+static bool ShowingHelp = false; // true iff help window is shown
+
static HostFilter TheFilter;
static char TheFiltWarn[80] = "";
static int TheSelHostCnt = 0;
static const int TheXMargin = 5;
static const int TheYMargin = 4;
static const int TheXCellWidth = 7;
static const int TheYCellWidth = 2;
static void NoteMsg(const StatusFwdMsg &msg);
static void Broadcast(Window::EventHandler weh, const Host &host);
static void DeleteIdleHosts();
static bool AddFirstLabel(const Host *skip, const String &l);
static bool DelLastLabel(const Host *skip, const String &l);
static void SelectHost(Host *host);
static int SwitchWin(int idx);
static int SwitchLblFilter(int idx);
static int SwitchCatFilter(int idx);
static void BuildFiltWarn(ostream &os);
@@ -429,53 +447,67 @@ inline int Dbl2Int(double v) { return (int)rint(v); }
KbdMonitor::KbdMonitor(int aFD): theFD(aFD) {
theReserv = TheScanner->setFD(theFD, dirRead, this);
}
KbdMonitor::~KbdMonitor() {
if (theReserv)
TheScanner->clearRes(theReserv);
}
void KbdMonitor::noteReadReady(int) {
switch (getch()) {
case '0': SwitchWin(0); break;
case KEY_LEFT: SwitchWin(TheWinPos-1); break;
case KEY_RIGHT: SwitchWin(TheWinPos+1); break;
case KEY_DOWN: SwitchLblFilter(TheFilter.lbl.pos - 1); break;
case KEY_UP: SwitchLblFilter(TheFilter.lbl.pos + 1); break;
+ case 'H':
+ case 'h':
+ if (!ShowingHelp) {
+ ShowingHelp = true;
+ touchwin(TheHelpWin->handle);
+ wrefresh(TheHelpWin->handle);
+ return;
+ } else
+ SwitchWin(TheWinPos);
+ break;
+
case 'S': SwitchCatFilter(TheFilter.logCat.pos - 1); break;
case 's': SwitchCatFilter(TheFilter.logCat.pos + 1); break;
case 'R': SwitchLblFilter(0); SwitchCatFilter(0); DeleteIdleHosts(); // fall through
case 'r': clearok(curscr, true); SwitchWin(TheWinPos); break;
case 'q':
case 'Q': DoShutdown = true; break;
default: return;
}
- redrawwin(TheWins[TheWinPos]);
+ if (ShowingHelp)
+ ShowingHelp = false;
+
+ wrefresh(TheWins[TheWinPos]->handle);
}
/* MsgMonitor */
MsgMonitor::MsgMonitor(Socket aSock): theSock(aSock), theSize(0) {
theReserv = TheScanner->setFD(theSock.fd(), dirRead, this);
}
MsgMonitor::~MsgMonitor() {
if (theReserv)
TheScanner->clearRes(theReserv);
if (theSock)
theSock.close();
}
void MsgMonitor::noteReadReady(int) {
static const int msgsz = sizeof(StatusFwdMsg);
const int sz = theSock.read(theBuf + theSize, sizeof(theBuf) - theSize);
@@ -491,41 +523,41 @@ void MsgMonitor::noteReadReady(int) {
cerr << "dispatcher at " << TheDisp << " quit." << endl;
DoShutdown = true;
return;
}
theSize += sz;
while (theSize >= msgsz) {
StatusFwdMsg msg;
memcpy(&msg, theBuf, msgsz);
theSize -= msgsz;
memmove(theBuf, theBuf + msgsz, theSize);
// handle the message
msg.ntoh();
msg.theRcvTime = TheClock;
NoteMsg(msg);
}
Assert(theSize >= 0);
- wrefresh(TheWins[TheWinPos]);
+ wrefresh(TheWins[TheWinPos]->handle);
}
/* Ticker */
Ticker::Ticker(Time aPeriod): thePeriod(aPeriod) {
sleepFor(thePeriod);
}
Ticker::~Ticker() {
}
void Ticker::wakeUp(const Alarm &alarm) {
AlarmUser::wakeUp(alarm);
DeleteIdleHosts();
sleepFor(thePeriod);
}
@@ -560,216 +592,237 @@ bool Host::matches(const HostFilter &filter) const {
}
/* WinMatrix */
WinMatrix::WinMatrix(int aMaxY, int aMaxX):
theImage((aMaxY+1) * (aMaxX+1)), theMaxY(aMaxY), theMaxX(aMaxX) {
theImage.count(theImage.capacity());
theImage.memset(0);
}
int WinMatrix::safePos(int y, int x) const {
Assert(y <= theMaxY && x <= theMaxX);
const int p = y*(theMaxX+1) + x;
Assert(p < theImage.count());
return p;
}
/* Window */
-Window::Window(const char *aTitle): WINDOW(*newwin(0,0,0,0)), theTitle(aTitle) {
- leaveok(this, true); // do not bother about cursor pos
+Window::Window(const char *aTitle): handle(newwin(0,0,0,0)), title(aTitle) {
+ leaveok(handle, true); // do not bother about cursor pos
int maxx, maxy;
- getmaxyx(this, maxy, maxx);
+ (void)maxy; // silence g++ "set but not used" warning
+ getmaxyx(handle, maxy, maxx);
- werase(this);
+ werase(handle);
// print window title
- wattron(this, A_BOLD);
- wattron(this, A_UNDERLINE);
- mvwaddstr(this, 0, (maxx - strlen(theTitle))/2, (char*)theTitle);
- wattroff(this, A_UNDERLINE);
- wattroff(this, A_BOLD);
+ wattron(handle, A_BOLD);
+ wattron(handle, A_UNDERLINE);
+ mvwaddstr(handle, 0, (maxx - strlen(title))/2, (char*)title);
+ wattroff(handle, A_UNDERLINE);
+ wattroff(handle, A_BOLD);
}
Window::~Window() {
- delwin(this);
+ delwin(handle);
}
/* InfoWindow */
InfoWindow::InfoWindow(char const *aTitle): Window(aTitle),
theMsgCnt(0), theListnCnt(0) {
update();
}
void InfoWindow::update() {
const int x = 2;
int y = 3;
- mvwprintw(this, y++, x, (char*)"%20s %s:%d", "dispatcher:", TheDisp.addrA().cstr(), TheDisp.port());
- mvwprintw(this, y++, x, (char*)"%20s %7d", "listeners:", theListnCnt);
+ mvwprintw(handle, y++, x, (char*)"%20s %s:%d", "dispatcher:", TheDisp.addrA().cstr(), TheDisp.port());
+ mvwprintw(handle, y++, x, (char*)"%20s %7d", "listeners:", theListnCnt);
y++;
- mvwprintw(this, y++, x, (char*)"%20s %7d", "messages received:", theMsgCnt);
- mvwprintw(this, y++, x, (char*)"%20s %7d", "mean message size:", sizeof(StatusNotifMsg));
- mvwprintw(this, y++, x, (char*)"%20s %7d", "selected hosts:", TheSelHostCnt);
- mvwprintw(this, y++, x, (char*)"%20s %7d", "busy hosts:", TheBusyHostCnt);
- mvwprintw(this, y++, x, (char*)"%20s %7d", "experiments:", TheUniqLblCnt);
+ mvwprintw(handle, y++, x, (char*)"%20s %7d", "messages received:", theMsgCnt);
+ mvwprintw(handle, y++, x, (char*)"%20s %7d", "mean message size:", sizeof(StatusNotifMsg));
+ mvwprintw(handle, y++, x, (char*)"%20s %7d", "selected hosts:", TheSelHostCnt);
+ mvwprintw(handle, y++, x, (char*)"%20s %7d", "busy hosts:", TheBusyHostCnt);
+ mvwprintw(handle, y++, x, (char*)"%20s %7d", "experiments:", TheUniqLblCnt);
}
void InfoWindow::noteAdd(const Host &host) {
Window::noteAdd(host);
update();
}
void InfoWindow::noteDel(const Host &host) {
Window::noteDel(host);
update();
}
void InfoWindow::noteUpd(const Host &host) {
Window::noteUpd(host);
if (host.log().depth()) {
theMsgCnt++;
theListnCnt = host.log()[0].theCopyCnt;
}
update();
}
+/* HelpWindow */
+
+HelpWindow::HelpWindow(): Window("Help") {
+ update();
+}
+
+void HelpWindow::update() {
+ const int x = 2;
+ int y = 2;
+ mvwprintw(handle, y++, x, "0:\t\tMonitor Info.");
+ mvwprintw(handle, y++, x, "LEFT/RIGHT:\tNext/previous tab.");
+ mvwprintw(handle, y++, x, "UP/DOWN:\tChange label filters.");
+ mvwprintw(handle, y++, x, "h:\t\tShow/close this help tab.");
+ mvwprintw(handle, y++, x, "S/s:\t\tChange client/server-side filters.");
+ mvwprintw(handle, y++, x, "R:\t\tReset filters, remove idle hosts, and refresh screen.");
+ mvwprintw(handle, y++, x, "r:\t\tRefresh screen.");
+ mvwprintw(handle, y++, x, "Q/q:\t\tQuit.");
+}
+
+
/* SumWindow */
SumWindow::SumWindow(char const *aTitle): Window(aTitle) {
update();
}
void SumWindow::update() {
// collect summary info from hosts
MsgSum cltSum, srvSum;
for (int i = 0; i < TheHosts.count(); ++i) {
if (const Host *host = TheHosts[i]) {
if (host->log().depth()) {
const StatusFwdMsg &msg = host->log()[0];
if (host->isClient())
cltSum += msg;
else
srvSum += msg;
}
}
}
const int x = 2;
int y = 2;
- mvwprintw(this, y++, x, (char*)"%s (%d hosts)", "Client side:", cltSum.hostCount());
+ mvwprintw(handle, y++, x, (char*)"%s (%d hosts)", "Client side:", cltSum.hostCount());
displaySide(y, x+2, cltSum);
y += 1;
- mvwprintw(this, y++, x, (char*)"%s (%d hosts)", "Server side:", srvSum.hostCount());
+ mvwprintw(handle, y++, x, (char*)"%s (%d hosts)", "Server side:", srvSum.hostCount());
displaySide(y, x+2, srvSum);
y += 1;
- mvwprintw(this, y++, x+2, (char*)"%20s %7s %8s %9s %9s %s",
+ mvwprintw(handle, y++, x+2, (char*)"%20s %7s %8s %9s %9s %s",
"measurement:", "min", "mean", "max", "sum", "unit");
}
void SumWindow::displaySide(int &y, int x, const MsgSum &sum) {
- //mvwprintw(this, y++, x, (char*)"%20s %s", "labels:",
+ //mvwprintw(handle, y++, x, (char*)"%20s %s", "labels:",
// (const char*)sum.theLabels);
displayLine(y++, x, "load:", sum.theReqRate, "req/sec");
displayLine(y++, x, "throughput:", sum.theRepRate, "rep/sec");
//displayLine(y++, x, "bandwidth:", sum.theBwidth, "Mbit/sec", 1024.*1024/8);
displayLine(y++, x, "response time:", sum.theRespTime, "msec");
displayLine(y++, x, "DHR:", sum.theDHR, "%");
//displayLine(y++, x, "connection use:", sum.theConnUse, "xact/conn");
displayLine(y++, x, "errors total:", sum.theTotErrRatio, "%");
//displayLine(y++, x, "errors now:", sum.theErrRatio, "%");
displayLine(y++, x, "xactions total:", sum.theXactTotCnt, "x10^6", 1e6);
displayLine(y++, x, "open sockets now:", sum.theSockInstCnt, "");
}
void SumWindow::displayLine(int y, int x, const char *label, const AggrStat &stats, const char *meas, double scale) {
- mvwprintw(this, y, x, (char*)"%20s %7d %8d %9d %9d %s",
+ mvwprintw(handle, y, x, (char*)"%20s %7d %8d %9d %9d %s",
label,
Dbl2Int(stats.min()/scale),
Dbl2Int(stats.mean()/scale),
Dbl2Int(stats.max()/scale),
Dbl2Int(stats.sum()/scale),
meas);
}
void SumWindow::noteAdd(const Host &host) {
Window::noteAdd(host);
update();
}
void SumWindow::noteDel(const Host &host) {
Window::noteDel(host);
update();
}
void SumWindow::noteUpd(const Host &host) {
Window::noteUpd(host);
update();
}
/* SmxWindow */
SmxWindow::SmxWindow(char const *aTitle): Window(aTitle) {
- wattron(this, A_BOLD);
+ wattron(handle, A_BOLD);
// horizontal lables
for (int i = 0; i < 10; ++i)
- mvwprintw(this, 2, Id2X(i), (char*)"%7d", i+1);
+ mvwprintw(handle, 2, Id2X(i), (char*)"%7d", i+1);
// vertical labels
for (int i = 0; i < 100; i += 10)
- mvwprintw(this, Id2Y(i), 0, (char*)"%2d", i);
+ mvwprintw(handle, Id2Y(i), 0, (char*)"%2d", i);
- wattroff(this, A_BOLD);
+ wattroff(handle, A_BOLD);
}
void SmxWindow::noteAdd(const Host &host) {
Window::noteAdd(host);
displayMsg(Host2Y(host), Host2X(host), host.log()[0]);
}
void SmxWindow::noteDel(const Host &host) {
Window::noteDel(host);
eraseSlot(Host2Y(host), Host2X(host));
}
void SmxWindow::noteUpd(const Host &host) {
Window::noteUpd(host);
displayMsg(Host2Y(host), Host2X(host), host.log()[0]);
}
void SmxWindow::eraseSlot(int y, int x) {
- mvwprintw(this, y, x, (char*)"%7s ", "");
+ mvwprintw(handle, y, x, (char*)"%7s ", "");
}
int SmxWindow::Host2Y(const Host &host) {
return Id2Y((host.lna() & 255) - 1);
}
int SmxWindow::Host2X(const Host &host) {
return Id2X((host.lna() & 255) - 1);
}
int SmxWindow::Id2Y(int host_id) {
return TheYMargin + ((host_id % 100) / 10) * TheYCellWidth;
}
int SmxWindow::Id2X(int host_id) {
return TheXMargin + (host_id % 10) * TheXCellWidth;
}
/* NumxWindow */
@@ -781,98 +834,98 @@ NumxWindow::NumxWindow(const char *aTitle, const char *aFmt):
update();
}
void NumxWindow::noteAdd(const Host &host) {
theNumCnt++;
SmxWindow::noteAdd(host);
}
void NumxWindow::noteDel(const Host &host) {
theNumCnt--;
SmxWindow::noteDel(host);
}
void NumxWindow::noteUpd(const Host &host) {
SmxWindow::noteUpd(host);
}
void NumxWindow::displayMsg(int y, int x, const StatusFwdMsg &msg) {
const double n = msg2num(msg);
theNumSum -= theMatrix(y, x);
- mvwprintw(this, y, x, (char*)theFmt, n);
+ mvwprintw(handle, y, x, (char*)theFmt, n);
theMatrix(y, x) = n;
theNumSum += n;
update();
}
void NumxWindow::eraseSlot(int y, int x) {
theNumSum -= theMatrix(y, x);
SmxWindow::eraseSlot(y, x);
theMatrix(y, x) = 0;
update();
}
void NumxWindow::update() {
int maxx, maxy;
- getmaxyx(this, maxy, maxx);
+ getmaxyx(handle, maxy, maxx);
int y = maxy-1;
- wattron(this, A_BOLD);
- mvwaddstr(this, y, Id2X(2) + TheXCellWidth-4, (char*)"cnt:");
- mvwaddstr(this, y, Id2X(4) + TheXCellWidth-4, (char*)"avg:");
- mvwaddstr(this, y, Id2X(6) + TheXCellWidth-4, (char*)"sum:");
- wattroff(this, A_BOLD);
+ wattron(handle, A_BOLD);
+ mvwaddstr(handle, y, Id2X(2) + TheXCellWidth-4, (char*)"cnt:");
+ mvwaddstr(handle, y, Id2X(4) + TheXCellWidth-4, (char*)"avg:");
+ mvwaddstr(handle, y, Id2X(6) + TheXCellWidth-4, (char*)"sum:");
+ wattroff(handle, A_BOLD);
- mvwprintw(this, y, Id2X(3), (char*)"%7d", theNumCnt);
- mvwprintw(this, y, Id2X(5), (char*)theFmt, Ratio(theNumSum,theNumCnt));
- mvwprintw(this, y, Id2X(7), (char*)theFmt, theNumSum);
+ mvwprintw(handle, y, Id2X(3), (char*)"%7d", theNumCnt);
+ mvwprintw(handle, y, Id2X(5), (char*)theFmt, Ratio(theNumSum,theNumCnt));
+ mvwprintw(handle, y, Id2X(7), (char*)theFmt, theNumSum);
}
/* RunTimeSmxWin */
void RunTimeSmxWin::displayMsg(int y, int x, const StatusFwdMsg &msg) {
const int sec = (msg.theSndTime - msg.theStartTime).sec();
const int min = (sec/60) % 60;
const int hour = sec/3600;
if (hour > 0)
- mvwprintw(this, y, x, (char*)"%4d:%02d", hour, min);
+ mvwprintw(handle, y, x, (char*)"%4d:%02d", hour, min);
else
- mvwprintw(this, y, x, (char*)"%4d.%02d", min, sec%60);
+ mvwprintw(handle, y, x, (char*)"%4d.%02d", min, sec%60);
}
/* MsgGapSmxWin */
void MsgGapSmxWin::noteUpd(const Host &host) {
if (host.log().depth() > 1)
theLastMsg = host.log()[1];
SmxWindow::noteUpd(host);
}
void MsgGapSmxWin::displayMsg(int y, int x, const StatusFwdMsg &msg) {
if (theLastMsg.theRcvTime >= 0)
- mvwprintw(this, y, x, (char*)"%7d",
+ mvwprintw(handle, y, x, (char*)"%7d",
(msg.theRcvTime - theLastMsg.theRcvTime).sec());
else
- mvwprintw(this, y, x, (char*)"%7s", "?");
+ mvwprintw(handle, y, x, (char*)"%7s", "?");
}
MsgSum::MsgSum(): theLabels("") {
}
MsgSum &MsgSum::operator +=(const StatusFwdMsg &msg) {
/*if (msg.theLabel && !theLabels.str(msg.theLabel)) { // XXX: not sufficient
if (theLabels)
theLabels += ",";
theLabels += msg.theLabel;
}*/
theReqRate.record(Dbl2Int(msg.theReqRate));
theRepRate.record(Dbl2Int(msg.theRepRate));
theBwidth.record(Dbl2Int(msg.theBwidth));
theRespTime.record(msg.theRespTime.msec());
theDHR.record(Dbl2Int(msg.theDHR*100));
theConnUse.record(Dbl2Int(msg.theConnUse));
theErrRatio.record(Dbl2Int(msg.theErrRatio*100));
theXactTotCnt.record(msg.theXactTotCnt);
@@ -963,40 +1016,43 @@ void DeleteIdleHosts() {
if (Host *host = TheHosts[h]) {
if (host->busy()) {
// XXX pre-IPv6 code used 's_addr' as an int
const int idx = host->addr().addrN().octet(0) % TheHostIdx.count();
TheHostIdx[idx] = host;
if (host->selected())
TheSelHostCnt++;
} else {
TheBusyHostCnt--;
Broadcast(&Window::noteDel, *host);
DelLastLabel(host, host->runLabel());
delete host;
TheHosts[h] = 0;
}
}
}
}
static
bool AddFirstLabel(const Host *skip, const String &l) {
+ if (!l)
+ return false; // empty label
+
for (int h = 0; h < TheHosts.count(); ++h) {
if (TheHosts[h] == skip)
continue;
if (TheHosts[h] && l == TheHosts[h]->runLabel())
return false; // not first label
}
TheUniqLblCnt++;
for (int i = 1; i < TheLabels.count(); ++i) {
if (!*TheLabels[i]) {
*TheLabels[i] = l;
return true;
}
}
TheLabels.append(new String(l));
return false;
}
static
bool DelLastLabel(const Host *skip, const String &l) {
for (int h = 0; h < TheHosts.count(); ++h) {
@@ -1004,83 +1060,83 @@ bool DelLastLabel(const Host *skip, const String &l) {
continue;
if (TheHosts[h] && l == TheHosts[h]->runLabel())
return false; // not last label
}
TheUniqLblCnt--;
for (int i = 1; i < TheLabels.count(); ++i) {
if (*TheLabels[i] == l) {
*TheLabels[i] = 0;
if (i == TheLabels.count()-1)
delete TheLabels.pop();
return true;
}
}
Assert(0);
return false;
}
static
int SwitchWin(int idx) {
TheWinPos = (idx + TheWins.count()) % TheWins.count();
- touchwin(TheWins[TheWinPos]);
+ touchwin(TheWins[TheWinPos]->handle);
return TheWinPos;
}
static
void SelectHost(Host *host) {
const bool wasSel = host->selected();
const bool isSel = host->matches(TheFilter);
if (!wasSel && isSel) {
host->selected(isSel);
TheSelHostCnt++;
Broadcast(&Window::noteAdd, *host);
} else
if (wasSel && !isSel) {
TheSelHostCnt--;
Broadcast(&Window::noteDel, *host);
host->selected(isSel);
}
}
static
void SelectHosts() {
for (int h = 0; h < TheHosts.count(); ++h) {
if (Host *host = TheHosts[h])
SelectHost(host);
}
// update selection warnings
ofixedstream s(TheFiltWarn, sizeof(TheFiltWarn));
BuildFiltWarn(s);
for (int w = 0; w < TheWins.count(); ++w) {
if (strlen(TheFiltWarn)) {
- wattron(TheWins[w], A_BOLD);
- mvwaddstr(TheWins[w], 1, 0, (char*)"Filters:");
- wattroff(TheWins[w], A_BOLD);
- mvwprintw(TheWins[w], 1, 10, (char*)"%-20s", TheFiltWarn);
+ wattron(TheWins[w]->handle, A_BOLD);
+ mvwaddstr(TheWins[w]->handle, 1, 0, (char*)"Filters:");
+ wattroff(TheWins[w]->handle, A_BOLD);
+ mvwprintw(TheWins[w]->handle, 1, 10, (char*)"%-20s", TheFiltWarn);
} else {
- wattroff(TheWins[w], A_BOLD);
- mvwprintw(TheWins[w], 1, 0, (char*)"%-30s", "");
+ wattroff(TheWins[w]->handle, A_BOLD);
+ mvwprintw(TheWins[w]->handle, 1, 0, (char*)"%-30s", "");
}
}
- touchwin(TheWins[TheWinPos]);
+ touchwin(TheWins[TheWinPos]->handle);
}
static
int SwitchLblFilter(int idx) {
TheFilter.lbl.pos = (idx + TheLabels.count()) % TheLabels.count();
if (TheFilter.lbl.pos)
for (int i = 0; !*TheLabels[TheFilter.lbl.pos] && i < TheLabels.count(); ++i) {
TheFilter.lbl.pos++;
TheFilter.lbl.pos %= TheLabels.count();
}
SelectHosts();
return TheFilter.lbl.pos;
}
static
int SwitchCatFilter(int idx) {
TheFilter.logCat.pos = (idx + lgcEnd) % lgcEnd;
SelectHosts();
@@ -1138,52 +1194,55 @@ int main(int argc, char *argv[]) {
TheHostIdx.count(TheHostIdx.capacity());
TheLabels.append(new String);
TheWins.append(TheInfoWin = new InfoWindow("Monitor Info"));
TheWins.append(new SumWindow("Summary Information"));
TheWins.append(new RunLabelSmxWin("Experiment Label"));
TheWins.append(new RunTimeSmxWin("Run time [h:m.s]"));
TheWins.append(new ReqRateSmxWin("Load [requests/sec]"));
TheWins.append(new RepRateSmxWin("Throughput [replies/sec]"));
TheWins.append(new BwidthSmxWin("Network Bandwidth [Mbps,replies]"));
TheWins.append(new RespTimeSmxWin("Response Time [msec]"));
TheWins.append(new DHRSmxWin("DHR [%]"));
TheWins.append(new ConnUseSmxWin("Connection Use [xact/conn]"));
TheWins.append(new ErrTotRatioSmxWin("Errors Total [%]"));
TheWins.append(new ErrTotCntSmxWin("Errors Total Count x 1000"));
TheWins.append(new XactTotCntSmxWin("Total Xaction Count x 1000"));
TheWins.append(new ErrRatioSmxWin("Errors Now [%]"));
TheWins.append(new SockInstCntSmxWin("Open Sockets Now"));
TheWins.append(new MsgGapSmxWin("Message Gap [sec]"));
+ TheHelpWin = new HelpWindow;
+
signal(SIGPIPE, SIG_IGN);
Clock::Update();
TheScanner = new PG_PREFFERED_FILE_SCANNER;
TheScanner->configure();
MsgMonitor *msgSrv = new MsgMonitor(sock);
KbdMonitor *kbdSrv = new KbdMonitor(0); // XXX: how to get stdin fd?
Ticker *ticker = new Ticker(Time::Sec(60));
SwitchWin(0);
- redrawwin(TheWins[TheWinPos]);
+ wrefresh(TheWins[TheWinPos]->handle);
while (!DoShutdown) {
Clock::Update();
Time tout = TheAlarmClock.on() ?
TheAlarmClock.timeLeft() : Time();
TheScanner->scan(TheAlarmClock.on() ? 0 : &tout);
}
delete ticker;
delete msgSrv;
delete kbdSrv;
+ delete TheHelpWin;
delete TheScanner;
endwin();
return 0;
}
#endif /* HAVE_NCURSES_H */