From g.hohl at aurenz.de Wed Jan 11 14:24:28 2012 From: g.hohl at aurenz.de (Hohl, Gerrit) Date: Wed, 11 Jan 2012 15:24:28 +0100 Subject: AW: AW: Problems using robots with authentication In-Reply-To: <8762hhtx18.fsf@gmail.com> References: <3B7A7BDFFD286F49A19A5B35D26E08FB8F1860@srvmail2.aurenz.local> <3B7A7BDFFD286F49A19A5B35D26E08FB8F1868@srvmail2.aurenz.local> <8762hhtx18.fsf@gmail.com> Message-ID: <3B7A7BDFFD286F49A19A5B35D26E08FB9517A5@srvmail2.aurenz.local> Hello Dimtry, sorry that I haven't replied to your mail earlier. And I didn't have the chance to try your suggestion until now. Will do that as soon as I have time for that. Anyway thanks for your reply. Regards, Gerrit -----Urspr?ngliche Nachricht----- Von: Dmitry Kurochkin [mailto:dmitry.kurochkin at measurement-factory.com] Gesendet: Donnerstag, 15. Dezember 2011 21:12 An: Hohl, Gerrit; users at web-polygraph.org Betreff: Re: AW: Problems using robots with authentication Hi Gerrit. On Thu, 15 Dec 2011 17:36:34 +0100, "Hohl, Gerrit" wrote: > Hello everyone, > > I read the article "Prerequisites" in the documentation: > http://www.web-polygraph.org/docs/reference/models/ssl.html#Sect:2 > > Polygraph SSL support is based on the OpenSSL library. A recent version of the library is required to compile Polygraph. We have tested with OpenSSL versions 0.9.6g and 0.9.7b. The presence of OpenSSL is determined at ./configure time. Please check that ./configure actually found SSL library and headers if you install Polygraph and want SSL support: > > ... > checking for CRYPTO_lock in -lcrypto... yes > checking for SSL_connect in -lssl... yes > checking for openssl/ssl.h... yes > checking for openssl/err.h... yes > checking for openssl/rand.h... yes > > Eh, I don't get these lines when I call the script. I assume that the script was modified, but the documentation not. > The exact messages may have change, but they are still there: $ ./configure | grep -i ssl checking for SSL_connect in -lssl... yes checking openssl/ssl.h usability... yes checking openssl/ssl.h presence... yes checking for openssl/ssl.h... yes checking openssl/err.h usability... yes checking openssl/err.h presence... yes checking for openssl/err.h... yes checking openssl/rand.h usability... yes checking openssl/rand.h presence... yes checking for openssl/rand.h... yes Assertion at NtlmAuth.cc:798 means that you built without OpenSSL support. You should install it and rebuild. On Debian-based systems you should install libssl-dev package. The assertion is always a bug. Web Polygraph should print a proper error here. There is an open bug #878881 [1] for this issue. > One remark: I only want NTLM authentication and not HTTPS benchmarking. > NTLM needs some crypto functions (MD5, at least). That is why OpenSSL is needed for it. Regards, Dmitry [1] https://bugs.launchpad.net/polygraph/+bug/878881 > Regards, > Gerrit > > -----Urspr?ngliche Nachricht----- > Von: users-bounces at web-polygraph.org > [mailto:users-bounces at web-polygraph.org] Im Auftrag von Hohl, Gerrit > Gesendet: Donnerstag, 15. Dezember 2011 17:08 > An: users at web-polygraph.org > Betreff: Problems using robots with authentication > > Hello everyone, > > I have the same problem that ufa faced at the end of October: > I use NTLM authentication and get the message > > NtlmAuth.cc:798: assertion failed: 'false' > Aborted > > from the polygraph-client program. After the first time I received that message I included the following line in my PGL file: > > Robot robot = { > [...] > pconn_use_lmt = const(2147483647); > [...] > }; > > But I still get the same message. I read something in Dmitry response about OpenSSL. The OpenSSL package ('openssl') is installed on that Ubuntu machine I'm currently using. But I'm not sure if polygraph was compiled with or without SSL. Is there a way to test it? Or what do I have to do to make sure that polygraph compiles with SSL support? > > Regards, > Gerrit > _______________________________________________ > Users mailing list > Users at web-polygraph.org > http://www.web-polygraph.org/mailman/listinfo/users > _______________________________________________ > Users mailing list > Users at web-polygraph.org > http://www.web-polygraph.org/mailman/listinfo/users From g.hohl at aurenz.de Wed Jan 11 14:43:38 2012 From: g.hohl at aurenz.de (Hohl, Gerrit) Date: Wed, 11 Jan 2012 15:43:38 +0100 Subject: Problems with benchmarking a proxy running under Windows 2008 R2 Message-ID: <3B7A7BDFFD286F49A19A5B35D26E08FB9517AF@srvmail2.aurenz.local> Hello everyone, I have a really odd problem bemachmarking a proxy which is running under Windows 2008 R2. The web-polygraph clients and server as well as the DNS is running on some Ubuntu 10.04.3 Server 64-bit machines. Each machine is a VM on our ESXi server. The proxy is installed on a Windows 2008 R2 system which is running a separated hardware. If we run the benchmark in that constelation we get a rate of about 60 hits/s. Not really satisfying. After that I installed our proxy on a SuSE Linux Enterprise 10 system - also running as a VM on the ESXi. The benchmark results of that constelation were quiet well and only limited by the ESXi hardware (the processors of the ESXi were at 100%). We decided to create also a VM with Windows 2008 R2 and installed again our proxy there (maybe the problem is between the ESXi and the separated hardware), but got the same odd results of 60 hits/s. As our test needs a lot of entries in the routing table and as we were not sure how well 2008 can handle a large number of entries, we setup a Ubuntu machine as router/gateway contaning all the routing entries. Basically it worked, but the numbers didn't change even a little bit. So I also turned off the 2008 network auto-tuning. Also no difference to the runs before - still 60 hits/s. I'm wondering if anyone of you had a similar experience. Or maybe someone of you knows that Windows 2008 R2 bottleneck and how to eliminate it? Regards, Gerrit -------------- next part -------------- An HTML attachment was scrubbed... URL: From morakhad at cisco.com Thu Jan 12 16:40:34 2012 From: morakhad at cisco.com (Mohammed Rakhada (morakhad)) Date: Thu, 12 Jan 2012 17:40:34 +0100 Subject: Compile errors for 4.5.0 on CentOS 5 Message-ID: <58E62AE37FBEDD419F31C57AD5A7835C45536D@XMB-AMS-210.cisco.com> Hello, I am trying to compile polygraph 4.5.0 on Centos 5.6 x86_64 but am getting errors. I was able to patch the BStream.h file as it was previously giving me the following error g++ -DHAVE_CONFIG_H -I../.. -I../../src -I../.. -I../../src -I/usr/include -g -O1 -Wall -Wwrite-strings -Woverloaded-virtual -MT PolyApp.o -MD -MP -MF .deps/PolyApp.Tpo -c -o PolyApp.o PolyApp.cc ../../src/base/BStream.h: In member function 'int64_t IBStream::geti64(int64_t&)': ../../src/base/BStream.h:72: error: 'be64toh' was not declared in this scope ../../src/base/BStream.h: In member function 'void OBStream::puti64(int64_t)': ../../src/base/BStream.h:106: error: 'htobe64' was not declared in this scope make[3]: *** [PolyApp.o] Error 1 make[3]: Leaving directory `/opt/home/compile/polygraph-4.5.0/src/app' make[2]: *** [all-recursive] Error 1 make[2]: Leaving directory `/opt/home/compile/polygraph-4.5.0/src' make[1]: *** [all-recursive] Error 1 make[1]: Leaving directory `/opt/home/compile/polygraph-4.5.0' I believe I traced this down to the BStream.h file not including the xstd/Endian.h library but after adding this the compile gets further but still doesn't complete and is now gives me the error below. So not sure if my "fix" is correct. g++ -DHAVE_CONFIG_H -I../.. -I../../src -I../.. -I../../src -I/usr/include -g -O1 -Wall -Wwrite-strings -Woverloaded-virtual -MT PolyApp.o -MD -MP -MF .deps/PolyApp.Tpo -c -o PolyApp.o PolyApp.cc ../../src/base/BStream.h: In member function 'int64_t IBStream::geti64(int64_t&)': ../../src/base/BStream.h:72: error: 'be64toh' was not declared in this scope ../../src/base/BStream.h: In member function 'void OBStream::puti64(int64_t)': ../../src/base/BStream.h:106: error: 'htobe64' was not declared in this scope make[3]: *** [PolyApp.o] Error 1 make[3]: Leaving directory `/opt/home/mrakhada/polygraph-4.5.0/src/app' make[2]: *** [all-recursive] Error 1 make[2]: Leaving directory `/opt/home/mrakhada/polygraph-4.5.0/src' make[1]: *** [all-recursive] Error 1 make[1]: Leaving directory `/opt/home/mrakhada/polygraph-4.5.0' Am I missing a library or can you provide a patch to allow it to compile on CentOS. I was able to successfully compile this on my desktop running Ubuntu. When running configure I do see this: checking for htobe64 and be64toh... no Regards, Mohammed Rakhada -------------- next part -------------- An HTML attachment was scrubbed... URL: From dmitry.kurochkin at measurement-factory.com Thu Jan 12 17:03:46 2012 From: dmitry.kurochkin at measurement-factory.com (Dmitry Kurochkin) Date: Thu, 12 Jan 2012 21:03:46 +0400 Subject: Compile errors for 4.5.0 on CentOS 5 In-Reply-To: <58E62AE37FBEDD419F31C57AD5A7835C45536D@XMB-AMS-210.cisco.com> References: <58E62AE37FBEDD419F31C57AD5A7835C45536D@XMB-AMS-210.cisco.com> Message-ID: <8739bkhmz1.fsf@gmail.com> Hi Mohammed. This is a known issue with v4.5.0. You have correctly identified the problem - xstd/Endian.h include is missing in base/BStream.h. The second error seems to be the same as the first one except for the paths. At the very least, the line numbers should have changed because of the added include line. Can you please double check that you are building the correct sources which have xstd/Endian.h include added to base/BStream.h? Regards, Dmitry From morakhad at cisco.com Thu Jan 12 17:40:06 2012 From: morakhad at cisco.com (Mohammed Rakhada (morakhad)) Date: Thu, 12 Jan 2012 18:40:06 +0100 Subject: Compile errors for 4.5.0 on CentOS 5 In-Reply-To: <8739bkhmz1.fsf@gmail.com> References: <58E62AE37FBEDD419F31C57AD5A7835C45536D@XMB-AMS-210.cisco.com> <8739bkhmz1.fsf@gmail.com> Message-ID: <58E62AE37FBEDD419F31C57AD5A7835C45536F@XMB-AMS-210.cisco.com> Hi Dmitry, It seems that I must have had something left over from a previous compile failure. I rm'd everything and then untar the source again and now it compiles. So thanks again for your help. For others having a similar problem this patch should help them. --- polygraph-4.5.0/src/base/BStream.h.orig 2012-01-12 17:19:55.000000000 +0000 +++ polygraph-4.5.0/src/base/BStream.h 2012-01-12 17:13:55.000000000 +0000 @@ -10,6 +10,7 @@ #include "xstd/h/netinet.h" /* for ntoh and hton */ // perhaps operators for these should be moved into a separate file? +#include "xstd/Endian.h" #include "xstd/Time.h" #include "xstd/Size.h" #include "xstd/NetDouble.h" Regards, Mohammed Rakhada -----Original Message----- From: Dmitry Kurochkin [mailto:dmitry.kurochkin at measurement-factory.com] Sent: 12 January 2012 17:04 To: Mohammed Rakhada (morakhad); users at web-polygraph.org Subject: Re: Compile errors for 4.5.0 on CentOS 5 Hi Mohammed. This is a known issue with v4.5.0. You have correctly identified the problem - xstd/Endian.h include is missing in base/BStream.h. The second error seems to be the same as the first one except for the paths. At the very least, the line numbers should have changed because of the added include line. Can you please double check that you are building the correct sources which have xstd/Endian.h include added to base/BStream.h? Regards, Dmitry From pmix at hendrie.id.au Tue Jan 17 06:45:31 2012 From: pmix at hendrie.id.au (Michael Hendrie) Date: Tue, 17 Jan 2012 17:15:31 +1030 Subject: Polymon Message-ID: Hi There, I'm using Web-Polygraph 4.0.10 and am starting to look at using polymon to monitor running tests. When I execute polygraph-polymon and connect to the socket created by polygraph-udp2tcpd I get no infomation about navigating around polymon, all I get is page is a title "Monitor Info" and the output below: dispatcher: 127.0.0.1:8050 listeners: 1 messages received: 2 mean message size: 112 selected hosts: 1 busy hosts: 1 experiments: 1 I have noticed that using the left and right arrow keys on the keyboard I can navigate around to certain screens but after a while (or may just be related to the up and down arrow keys) polygraph-polymon core dumps (backtrace below). Am I meant to be getting navigation info once connected? Is there any documented info on using polygraph-polymon?, the information given by --help doesn't really provide usage information apart from connecting to polygraph-udp2tcpd Any help would be greatly appreciated Michael (gdb) bt #0 0x8838decb in kill () from /lib/libc.so.6 #1 0x8838de68 in raise () from /lib/libc.so.6 #2 0x8838cb78 in abort () from /lib/libc.so.6 #3 0x08054695 in Abort (fname=0x805ee00 "polymon.cc", lineno=134628352, cond=0x805f15d "*TheLabels[TheFilter.lbl.pos]") at Assert.cc:22 #4 0x0804f74d in SelectHosts () at String.h:29 #5 0x0804fba9 in SwitchLblFilter (idx=0) at polymon.cc:1079 #6 0x0804fd19 in KbdMonitor::noteReadReady (this=0x8195180) at polymon.cc:447 #7 0x08058f67 in FileScanner::scan (this=0x8067180, minP=fsupMin, timeout=0x0) at FileScanner.cc:144 #8 0x0804e5da in main (argc=0, argv=0x8239000) at FileScanner.h:157 From dmitry.kurochkin at measurement-factory.com Thu Jan 19 22:34:27 2012 From: dmitry.kurochkin at measurement-factory.com (Dmitry Kurochkin) Date: Fri, 20 Jan 2012 02:34:27 +0400 Subject: Polymon In-Reply-To: References: Message-ID: <87r4yv48zw.fsf@gmail.com> 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 -------------- next part -------------- A non-text attachment was scrubbed... Name: polymon-fixes_v4.0.10.patch Type: text/x-diff Size: 24418 bytes Desc: not available URL: From pmix at hendrie.id.au Mon Jan 30 09:47:10 2012 From: pmix at hendrie.id.au (Michael Hendrie) Date: Mon, 30 Jan 2012 20:17:10 +1030 Subject: Polymon In-Reply-To: <87r4yv48zw.fsf@gmail.com> References: <87r4yv48zw.fsf@gmail.com> Message-ID: Somehow this reply ended up in my spam folder. Have just tested and the patch seems to resolve the segfault issue and provide some guidance on using polymon. Thanks for the help! On 20/01/2012, at 9:04 AM, Dmitry Kurochkin wrote: > 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 > 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 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 TheHosts; > +static PtrArray TheHosts; > static Array TheHostIdx; // address -> host map > static int TheBusyHostCnt = 0; > -static Array TheLabels; > +static PtrArray TheLabels; > static int TheUniqLblCnt = 0; > > -static Array TheWins; > +static PtrArray 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 */