/*========================================================================= Program: ParaView Module: $RCSfile$ Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "pqMemoryInspectorPanel.h" #include "pqRemoteCommandDialog.h" #include "ui_pqMemoryInspectorPanelForm.h" using Ui::pqMemoryInspectorPanelForm; // #define pqMemoryInspectorPanelDEBUG // print a process table to stderr during initialization // #define MIP_PROCESS_TABLE #include "pqActiveObjects.h" #include "pqServerManagerModel.h" #include "pqApplicationCore.h" #include "pqView.h" #include "pqRenderView.h" #include "vtkSMRenderViewProxy.h" #include "vtkProcessModule.h" #include "vtkPVSystemConfigInformation.h" #include "vtkPVMemoryUseInformation.h" #include "vtkPVEnableStackTraceSignalHandler.h" #include "vtkPVDisableStackTraceSignalHandler.h" #include "vtkSMSession.h" #include "vtkSMSessionClient.h" #include "vtkPVInformation.h" #include "vtkClientServerStream.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if QT_VERSION < 0x050000 #include #endif #include using std::map; using std::pair; #include using std::vector; #include using std::string; #include using std::ostringstream; using std::istringstream; #include using std::cerr; using std::endl; using std::left; using std::right; #include using std::setw; using std::setfill; #include using std::min; #define pqErrorMacro(estr)\ qDebug()\ << "Error in:" << endl\ << __FILE__ << ", line " << __LINE__ << endl\ << "" estr << endl; // User interface //============================================================================= class pqMemoryInspectorPanelUI : public Ui::pqMemoryInspectorPanelForm {}; // QProgress bar makes use of integer type. Each power of 10 // greater than 100 result in a decimal place of precision in // the UI. #define MIP_PROGBAR_MAX 1000 // keys for tree items enum { ITEM_KEY_PROCESS_TYPE=Qt::UserRole, ITEM_KEY_PVSERVER_TYPE, // vtkProcessModule::ProcessTypes ITEM_KEY_PID, // long long ITEM_KEY_HOST_NAME, // string, hostname ITEM_KEY_MPI_RANK, // int ITEM_KEY_HOST_OS, // descriptive string ITEM_KEY_HOST_CPU, // descriptive string ITEM_KEY_HOST_MEM, // descriptive string ITEM_KEY_SYSTEM_TYPE // int (0 unix like, 1 win) }; // data for tree items enum { ITEM_DATA_CLIENT_GROUP, ITEM_DATA_CLIENT_HOST, ITEM_DATA_CLIENT_RANK, ITEM_DATA_SERVER_GROUP, ITEM_DATA_SERVER_HOST, ITEM_DATA_SERVER_RANK, ITEM_DATA_UNIX_SYSTEM=0, ITEM_DATA_WIN_SYSTEM=1 }; namespace { #if QT_VERSION >= 0x050000 // **************************************************************************** QStyle *getMemoryUseWidgetStyle() { // this sets the style for the progress bar used to // display % memory usage. If we didn't do this the // display will look different on each OS. The ownership // of the style does not change hands when it's set to // the widget thus a single static instance is convenient. static QStyle* style = QStyleFactory::create("fusion"); return style; } #else // **************************************************************************** QPlastiqueStyle *getMemoryUseWidgetStyle() { // this sets the style for the progress bar used to // display % memory usage. If we didn't do this the // display will look different on each OS. The ownership // of the style does not change hands when it's set to // the widget thus a single static instance is convenient. static QPlastiqueStyle style; return &style; } #endif // **************************************************************************** float getSystemWarningThreshold() { # ifdef WIN32 return 0.90f; # else return 0.80f; # endif } // **************************************************************************** float getSystemCriticalThreshold() { # ifdef WIN32 return 0.95f; # else return 0.90f; # endif } // **************************************************************************** float getProcessWarningThreshold() { return 0.70f; } // **************************************************************************** float getProcessCriticalThreshold() { return 0.80f; } // **************************************************************************** void setMemoryUseWidgetColor( QPalette &palette, float fracUsed, float fracWarn, float fracCrit) { (void)fracWarn; if (fracUsed>fracCrit) { // danger -> red //palette.setColor(QPalette::Highlight,QColor(232,40,40)); // bright //palette.setColor(QPalette::Highlight,QColor(190,60,60)); // moderate //palette.setColor(QPalette::Highlight,QColor(147,57,57)); // moderate balanced palette.setColor(QPalette::Highlight,QColor(217,84,84)); // cdash red } /* else if (fracUsed>fracWarn) { //palette.setColor(QPalette::Highlight,QColor(219,219,80)); // moderate palette.setColor(QPalette::Highlight,QColor(252,168,84)); // cdash yellow } */ else { // ok -> green //palette.setColor(QPalette::Highlight,QColor(66,232,20)); // bright //palette.setColor(QPalette::Highlight,QColor(90,160,70)); // moderate //palette.setColor(QPalette::Highlight,QColor(125,176,74));// cdash yellow palette.setColor(QPalette::Highlight, Qt::darkGray); } } // **************************************************************************** void setWidgetContainerColor(QPalette &palette, int rank) { if (rank%2) { palette.setColor(QPalette::Base,QColor(250,250,250)); } else { palette.setColor(QPalette::Base,QColor(237,237,237)); } } // **************************************************************************** QString translateUnits(float memUse) { QString fmt("%1 %2"); float p210=pow(2.0,10.0); float p220=pow(2.0,20.0); float p230=pow(2.0,30.0); float p240=pow(2.0,40.0); float p250=pow(2.0,50.0); // were dealing with kiB memUse *= 1024; if (memUse void ClearVectorOfPointers(vector data) { size_t n=data.size(); for (size_t i=0; iRank=rank; } int GetRank(){ return this->Rank; } void SetPid(long long pid){ this->Pid=pid; } long long GetPid(){ return this->Pid; } void SetProcMemoryAvailable(long long capacity){ this->ProcMemoryAvailable=capacity; } long long GetProcMemoryAvailable(){ return this->ProcMemoryAvailable; } void SetProcMemoryUse(long long load){ this->ProcMemoryUse=load; } long long GetProcMemoryUse(){ return this->ProcMemoryUse; } void SetHostMemoryUse(long long load){ this->HostMemoryUse=load; } long long GetHostMemoryUse(){ return this->HostMemoryUse; } float GetProcMemoryUseFraction() { return (float)this->ProcMemoryUse/(float)this->ProcMemoryAvailable; } QFrame *GetMemoryUseWidget(){ return this->WidgetContainer; } void UpdateMemoryUseWidget(); void InitializeMemoryUseWidget(); void Print(ostream &os); private: void InitializeMemoryUseWidget(QProgressBar *&loadWidget); private: int Rank; long long Pid; long long ProcMemoryUse; long long HostMemoryUse; long long ProcMemoryAvailable; QProgressBar *MemoryUseWidget; QFrame *WidgetContainer; }; //----------------------------------------------------------------------------- RankData::RankData( int rank, long long pid, long long procMemoryUse, long long hostMemoryUse, long long procAvail) : Rank(rank), Pid(pid), ProcMemoryUse(procMemoryUse), HostMemoryUse(hostMemoryUse), ProcMemoryAvailable(procAvail) { this->InitializeMemoryUseWidget(); } //----------------------------------------------------------------------------- RankData::~RankData() { delete this->WidgetContainer; } //----------------------------------------------------------------------------- void RankData::UpdateMemoryUseWidget() { float used = (float)this->GetProcMemoryUse(); float fracUsed = min(1.0f,this->GetProcMemoryUseFraction()); float percUsed = fracUsed*100.0f; int progVal = (int)(fracUsed*MIP_PROGBAR_MAX); this->MemoryUseWidget->setValue(progVal); this->MemoryUseWidget->setFormat( QString("%1 %2%").arg(::translateUnits(used)).arg(percUsed, 0,'f',2)); QPalette palette(this->MemoryUseWidget->palette()); ::setMemoryUseWidgetColor( palette, fracUsed, ::getProcessWarningThreshold(), ::getProcessCriticalThreshold()); this->MemoryUseWidget->setPalette(palette); } //----------------------------------------------------------------------------- void RankData::InitializeMemoryUseWidget() { this->InitializeMemoryUseWidget(this->MemoryUseWidget); QLabel *rank=new QLabel; rank->setText(QString("%1").arg(this->Rank)); QFrame *vline=new QFrame; vline->setFrameStyle(QFrame::VLine|QFrame::Plain); QFrame *vline2=new QFrame; vline2->setFrameStyle(QFrame::VLine|QFrame::Plain); QLabel *pid=new QLabel; pid->setText(QString("%1").arg(this->Pid)); QHBoxLayout *w=new QHBoxLayout; w->addWidget(this->MemoryUseWidget); w->setContentsMargins(2,2,2,2); w->setSpacing(2); QHBoxLayout *l=new QHBoxLayout; l->addWidget(rank); l->addWidget(vline); l->addWidget(pid); l->addWidget(vline2); l->addLayout(w); l->setContentsMargins(1,0,1,0); l->setSpacing(0); this->WidgetContainer=new QFrame; this->WidgetContainer->setLayout(l); this->WidgetContainer->setFrameStyle(QFrame::Box|QFrame::Plain); this->WidgetContainer->setLineWidth(1); QFont font(this->WidgetContainer->font()); font.setPointSize(8); this->WidgetContainer->setFont(font); QPalette palette(rank->palette()); ::setWidgetContainerColor(palette, this->Rank); rank->setPalette(palette); rank->setAutoFillBackground(true); pid->setPalette(palette); pid->setAutoFillBackground(true); QFontMetrics fontMet(font); int rankWid=fontMet.width("555555"); rank->setMinimumWidth(rankWid); rank->setMaximumWidth(rankWid); int pidWid=fontMet.width("555555555"); pid->setMinimumWidth(pidWid); pid->setMaximumWidth(pidWid); this->UpdateMemoryUseWidget(); } //----------------------------------------------------------------------------- void RankData::InitializeMemoryUseWidget(QProgressBar *&loadWidget) { loadWidget=new QProgressBar; loadWidget->setStyle(::getMemoryUseWidgetStyle()); loadWidget->setMaximumHeight(15); loadWidget->setMinimum(0); loadWidget->setMaximum(MIP_PROGBAR_MAX); QFont font(loadWidget->font()); font.setPointSize(8); loadWidget->setFont(font); } //----------------------------------------------------------------------------- void RankData::Print(ostream &os) { os << "RankData(" << this << ")" << " Rank=" << this->Rank << " Pid=" << this->Pid << " ProcMemoryUse=" << this->ProcMemoryUse << " HostMemoryUse=" << this->HostMemoryUse << " ProcMemoryAvailable=" << this->ProcMemoryAvailable << " MemoryUseWidget=" << this->MemoryUseWidget << endl; } /// data associated with the host (a collection of ranks) //============================================================================= class HostData { public: HostData(); HostData(string groupName,string hostName,long long memTotal, long long memAvail); HostData(const HostData &other){ *this=other; } const HostData &operator=(const HostData &other); ~HostData(); RankData *AddRankData(int rank, long long pid, long long procMemAvail); RankData *GetRankData(int i); void ClearRankData(); string &GetGroupName(){ return this->GroupName; } string &GetHostName(){ return this->HostName; } long long GetHostMemoryTotal(){ return this->HostMemoryTotal; } long long GetHostMemoryAvailable(){ return this->HostMemoryAvailable; } long long GetTotalSystemMemoryUse(); long long GetProcessGroupMemoryUse(); void SetTreeItem(QTreeWidgetItem *item){ this->TreeItem=item; } QTreeWidgetItem *GetTreeItem(){ return this->TreeItem; } QWidget *GetMemoryUseWidget(){ return (QWidget*)this->WidgetContainer; } QProgressBar *GetTotalMemoryUseWidget(){ return this->TotalMemoryUseWidget; } QProgressBar *GetGroupMemoryUseWidget(){ return this->GroupMemoryUseWidget; } void InitializeMemoryUseWidget(); void InitializeMemoryUseWidget(QProgressBar *&loadWidget); void UpdateMemoryUseWidget(); void UpdateMemoryUseWidget( QProgressBar *loadWidget, long long used, float fracUsed, float warnFrac, float critFrac); void Print(ostream &os); private: string GroupName; string HostName; long long HostMemoryTotal; // memory installed long long HostMemoryAvailable; // memory available to us. QProgressBar *TotalMemoryUseWidget; // for displaying all process's use QProgressBar *GroupMemoryUseWidget; // for displaying only pv process's use QFrame *WidgetContainer; // widget containing both all and proccess group QTreeWidgetItem *TreeItem; // gui element vector Ranks; // references to ranks local to this host }; //----------------------------------------------------------------------------- HostData::HostData() : GroupName(""), HostName(""), HostMemoryTotal(0), HostMemoryAvailable(0) {} //----------------------------------------------------------------------------- HostData::HostData( string groupName, string hostName, long long hostMemTotal, long long hostMemAvail) : GroupName(groupName), HostName(hostName), HostMemoryTotal(hostMemTotal), HostMemoryAvailable(hostMemAvail) { this->InitializeMemoryUseWidget(); } //----------------------------------------------------------------------------- HostData::~HostData() { this->ClearRankData(); delete this->WidgetContainer; } //----------------------------------------------------------------------------- const HostData &HostData::operator=(const HostData &other) { if (this==&other) return *this; this->GroupName=other.GroupName; this->HostName=other.HostName; this->HostMemoryTotal=other.HostMemoryTotal; this->HostMemoryAvailable=other.HostMemoryAvailable; this->TotalMemoryUseWidget=other.TotalMemoryUseWidget; this->GroupMemoryUseWidget=other.GroupMemoryUseWidget; this->TreeItem=other.TreeItem; this->Ranks=other.Ranks; return *this; } //----------------------------------------------------------------------------- RankData *HostData::GetRankData(int i) { if ((size_t)iRanks.size()) { return this->Ranks[i]; } return NULL; } //----------------------------------------------------------------------------- void HostData::ClearRankData() { ::ClearVectorOfPointers(this->Ranks); } //----------------------------------------------------------------------------- RankData *HostData::AddRankData( int rank, long long pid, long long procMemAvail) { RankData *newRank=new RankData(rank,pid,0,0,procMemAvail); this->Ranks.push_back(newRank); return newRank; } //----------------------------------------------------------------------------- long long HostData::GetTotalSystemMemoryUse() { long long load=0; if (this->Ranks.size()) { load=this->Ranks[0]->GetHostMemoryUse(); } return load; } //----------------------------------------------------------------------------- long long HostData::GetProcessGroupMemoryUse() { long long load=0; size_t n=this->Ranks.size(); for (size_t i=0; iRanks[i]->GetProcMemoryUse(); } return load; } //----------------------------------------------------------------------------- void HostData::InitializeMemoryUseWidget() { this->InitializeMemoryUseWidget(this->TotalMemoryUseWidget); this->InitializeMemoryUseWidget(this->GroupMemoryUseWidget); QFormLayout *l=new QFormLayout; l->setRowWrapPolicy(QFormLayout::DontWrapRows); l->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow); l->setFormAlignment(Qt::AlignHCenter|Qt::AlignTop); l->setLabelAlignment(Qt::AlignRight); l->setContentsMargins(2,2,2,2); l->setSpacing(2); l->addRow("System Total",this->TotalMemoryUseWidget); l->addRow(this->GroupName.c_str(),this->GroupMemoryUseWidget); QLabel *label=new QLabel; label->setText(this->HostName.c_str()); QFrame *vline=new QFrame; vline->setFrameStyle(QFrame::VLine|QFrame::Plain); QHBoxLayout *h=new QHBoxLayout; h->addWidget(label); h->addWidget(vline); h->addLayout(l); h->setContentsMargins(1,0,1,0); h->setSpacing(0); this->WidgetContainer=new QFrame; this->WidgetContainer->setLayout(h); this->WidgetContainer->setFrameStyle(QFrame::Box|QFrame::Plain); QFont font(this->WidgetContainer->font()); font.setPointSize(8); this->WidgetContainer->setFont(font); this->UpdateMemoryUseWidget(); } //----------------------------------------------------------------------------- void HostData::InitializeMemoryUseWidget(QProgressBar *&loadWidget) { loadWidget=new QProgressBar; loadWidget->setStyle(::getMemoryUseWidgetStyle()); loadWidget->setMaximumHeight(15); loadWidget->setMinimum(0); loadWidget->setMaximum(MIP_PROGBAR_MAX); QFont font(loadWidget->font()); font.setPointSize(8); loadWidget->setFont(font); } //----------------------------------------------------------------------------- void HostData::UpdateMemoryUseWidget() { long long load; float frac; load=this->GetTotalSystemMemoryUse(); frac=min(1.0f,(float)load/(float)this->HostMemoryTotal); this->UpdateMemoryUseWidget( this->TotalMemoryUseWidget, load, frac, ::getSystemWarningThreshold(), ::getSystemCriticalThreshold()); load=this->GetProcessGroupMemoryUse(); frac=min(1.0f,(float)load/(float)this->HostMemoryAvailable); this->UpdateMemoryUseWidget( this->GroupMemoryUseWidget, load, frac, ::getProcessWarningThreshold(), ::getProcessCriticalThreshold()); } //----------------------------------------------------------------------------- void HostData::UpdateMemoryUseWidget( QProgressBar *loadWidget, long long used, float fracUsed, float warnFrac, float critFrac) { float percUsed = fracUsed*100.0f; int progVal = (int)(fracUsed*MIP_PROGBAR_MAX); loadWidget->setValue(progVal); loadWidget->setFormat( QString("%1 %2%").arg(::translateUnits(used)).arg(percUsed, 0,'f',2)); QPalette palette(loadWidget->palette()); ::setMemoryUseWidgetColor( palette, fracUsed, warnFrac, critFrac); loadWidget->setPalette(palette); } //----------------------------------------------------------------------------- void HostData::Print(ostream &os) { os << "HostData(" << this << ")" << " HostName=" << this->HostName << " HostMemoryTotal=" << this->HostMemoryTotal << " TotalMemoryUseWidget=" << this->TotalMemoryUseWidget << " GroupMemoryUseWidget=" << this->GroupMemoryUseWidget << " WidgetContainer=" << this->WidgetContainer << " TreeItem=" << this->TreeItem << " Ranks=" << endl; size_t nRanks=this->Ranks.size(); for (size_t i=0; iRanks[i]->Print(os); } os << endl; } //----------------------------------------------------------------------------- pqMemoryInspectorPanel::pqMemoryInspectorPanel( QWidget* pWidget, Qt::WindowFlags flags) : QWidget(pWidget,flags) { #if defined pqMemoryInspectorPanelDEBUG cerr << ":::::pqMemoryInspectorPanel::pqMemoryInspectorPanel" << endl; #endif this->ClientOnly=1; this->ClientHost=0; this->AutoUpdate=true; this->UpdateEnabled=0; // Construct Qt form. this->Ui=new pqMemoryInspectorPanelUI; this->Ui->setupUi(this); this->Ui->updateMemUse->setIcon(QPixmap(":/pqWidgets/Icons/pqRedo24.png")); // attempt initialization here before we begin to listen // for event's that could trigger and update. this->Initialize(); // listen for enable/disable auto update QObject::connect( this->Ui->autoUpdate, SIGNAL(toggled(bool)), this, SLOT(SetAutoUpdate(bool))); // listen for manual update request QObject::connect( this->Ui->updateMemUse, SIGNAL(released()), this, SLOT(Update())); // listen to context menu events QObject::connect( this->Ui->configView, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(ConfigViewContextMenu(const QPoint &))); this->Ui->configView->setContextMenuPolicy(Qt::CustomContextMenu); // connect to new views as they are created pqServerManagerModel* smm = pqApplicationCore::instance()->getServerManagerModel(); // listen for new views, we want to update after render is finished. QObject::connect( smm, SIGNAL(viewAdded(pqView*)), this, SLOT(ConnectToView(pqView*))); // listen to the active view for render completed events. pqView* view=pqActiveObjects::instance().activeView(); if (view) { this->ConnectToView(view); } // listen to servers connecting and disconnecting QObject::connect( smm, SIGNAL(serverAdded(pqServer*)), this, SLOT(ServerConnected())); QObject::connect( smm, SIGNAL(finishedRemovingServer()), this, SLOT(ServerDisconnected())); /* // TODO -- not sure if these are useful, maybe for responding // to python events? QObject::connect( smm, SIGNAL(dataUpdated(pqPipelineSource*)), this, SLOT(EnableUpdate())); QObject::connect( smm, SIGNAL(proxyAdded(pqProxy*)), this, SLOT(EnableUpdate())); QObject::connect( smm, SIGNAL(proxRemoved(pqProxy*)), this, SLOT(EnableUpdate())); */ QPalette pal=this->Ui->configView->palette(); pal.setColor(QPalette::Highlight, Qt::lightGray); this->Ui->configView->setPalette(pal); } //----------------------------------------------------------------------------- pqMemoryInspectorPanel::~pqMemoryInspectorPanel() { #if defined pqMemoryInspectorPanelDEBUG cerr << ":::::pqMemoryInspectorPanel::~pqMemoryInspectorPanel" << endl; #endif this->ClearClient(); this->ClearServers(); delete this->Ui; } //----------------------------------------------------------------------------- void pqMemoryInspectorPanel::ClearClient() { if (this->ClientHost) { delete this->ClientHost; } this->ClientHost=0; } //----------------------------------------------------------------------------- void pqMemoryInspectorPanel::ClearServer( map &hosts, vector &ranks) { map::iterator it=hosts.begin(); map::iterator end=hosts.end(); while (it!=end) { if ((*it).second) { delete (*it).second; (*it).second=NULL; } ++it; } hosts.clear(); ranks.clear(); } //----------------------------------------------------------------------------- void pqMemoryInspectorPanel::ClearServers() { this->ClientOnly=1; this->ClearServer(this->ServerHosts,this->ServerRanks); this->ClearServer(this->DataServerHosts,this->DataServerRanks); this->ClearServer(this->RenderServerHosts,this->RenderServerRanks); } //----------------------------------------------------------------------------- void pqMemoryInspectorPanel::ServerDisconnected() { #if defined pqMemoryInspectorPanelDEBUG cerr << ":::::pqMemoryInspectorPanel:;ServerDisconnected" << endl; #endif this->ClearClient(); this->ClearServers(); } //----------------------------------------------------------------------------- void pqMemoryInspectorPanel::ServerConnected() { #if defined pqMemoryInspectorPanelDEBUG cerr << ":::::pqMemoryInspectorPanel::ServerConnected" << endl; #endif this->Initialize(); } //----------------------------------------------------------------------------- void pqMemoryInspectorPanel::ConnectToView(pqView *view) { #if defined pqMemoryInspectorPanelDEBUG cerr << ":::::pqMemoryInspectorPanel::ConnectToView" << endl; #endif // rendering triggers the update QObject::connect( view, SIGNAL(endRender()), this, SLOT(RenderCompleted())); // update only after data is changed QObject::connect( view, SIGNAL(updateDataEvent()), this, SLOT(EnableUpdate())); } //----------------------------------------------------------------------------- void pqMemoryInspectorPanel::showEvent(QShowEvent *e) { #if defined pqMemoryInspectorPanelDEBUG cerr << ":::::pqMemoryInspectorPanel::showEvent" << endl; #endif (void)e; this->Update(); } //----------------------------------------------------------------------------- void pqMemoryInspectorPanel::EnableUpdate() { #if defined pqMemoryInspectorPanelDEBUG cerr << ":::::pqMemoryInspectorPanel::EnableUpdate" << endl; #endif this->UpdateEnabled=1; } //----------------------------------------------------------------------------- void pqMemoryInspectorPanel::RenderCompleted() { #if defined pqMemoryInspectorPanelDEBUG cerr << ":::::pqMemoryInspectorPanel::RenderCompleted" << endl; #endif if (!this->AutoUpdate || !this->isVisible() || !this->UpdateEnabled) { return; } this->Update(); return; /* // This code is for updating on endRender regardless of whether // or not data was updated.it works better than updating only // after data is udpated. however is disabled because it's slight // over kill if (!this->AutoUpdate || !this->isVisible()) { return; } // only going to respond to render view's events. other view's // events may be useful to track but need to consider case by // case and verify that we don't flood the server with update // requests. pqRenderView* view = qobject_cast(pqActiveObjects::instance().activeView()); if (view) { vtkSMRenderViewProxy *viewProxy = dynamic_cast(view->getProxy()); if (viewProxy) { if (!viewProxy->LastRenderWasInteractive() && !this->PendingUpdate) { // there are two still renders after the last // interactive render. QTimer::singleShot(2000, this, SLOT(Update())); this->PendingUpdate=1; } } } */ } //----------------------------------------------------------------------------- void pqMemoryInspectorPanel::InitializeServerGroup( long long clientPid, vtkPVSystemConfigInformation *configs, int validProcessType, QTreeWidgetItem *group, string groupName, map &hosts, vector &ranks, int &systemType) { size_t nConfigs=configs->GetSize(); for (size_t i=0; iGetPid(i); if (pid==clientPid) { // must be the builtin, do not duplicate. continue; } int processType=configs->GetProcessType(i); if (processType!=validProcessType) { // it's not the correct type. continue; } string os=configs->GetOSDescriptor(i); string cpu=configs->GetCPUDescriptor(i); string mem=configs->GetMemoryDescriptor(i); string hostName=configs->GetHostName(i); systemType=configs->GetSystemType(i); int rank=configs->GetRank(i); long long hostMemoryTotal=configs->GetHostMemoryTotal(i); long long hostMemoryAvailable=configs->GetHostMemoryAvailable(i); long long procMemoryAvailable=configs->GetProcMemoryAvailable(i); // it's useful to have hostname's rank's and pid's in // the terminal. if the client hangs you can attach // gdb and see where it's stuck without a lot of effort #ifdef MIP_PROCESS_TABLE cerr << setw(32) << hostName << setw(16) << pid << setw(8) << rank << endl << setw(1); #endif // host HostData *serverHost=NULL; pair ins(hostName,(HostData*)0); pair::iterator,bool> ret; ret=hosts.insert(ins); if (ret.second) { // new host serverHost=new HostData(groupName,hostName,hostMemoryTotal,hostMemoryAvailable); ret.first->second=serverHost; QTreeWidgetItem *serverHostItem=new QTreeWidgetItem(group); serverHostItem->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless); serverHostItem->setExpanded(true); serverHostItem->setData(0,ITEM_KEY_PROCESS_TYPE,QVariant(ITEM_DATA_SERVER_HOST)); serverHostItem->setData(0,ITEM_KEY_PVSERVER_TYPE,QVariant(processType)); serverHostItem->setData(0,ITEM_KEY_SYSTEM_TYPE,QVariant(systemType)); serverHostItem->setData(0,ITEM_KEY_HOST_NAME,QVariant(hostName.c_str())); serverHostItem->setData(0,ITEM_KEY_HOST_OS,QString(os.c_str())); serverHostItem->setData(0,ITEM_KEY_HOST_CPU,QString(cpu.c_str())); serverHostItem->setData(0,ITEM_KEY_HOST_MEM,QString(mem.c_str())); this->Ui->configView->setItemWidget(serverHostItem,0,serverHost->GetMemoryUseWidget()); serverHost->SetTreeItem(serverHostItem); } else { serverHost=ret.first->second; } // rank RankData *serverRank=serverHost->AddRankData(rank,pid,procMemoryAvailable); ranks.push_back(serverRank); QTreeWidgetItem *serverRankItem=new QTreeWidgetItem(serverHost->GetTreeItem()); serverRankItem->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless); serverRankItem->setExpanded(false); serverRankItem->setData(0,ITEM_KEY_PROCESS_TYPE,QVariant(ITEM_DATA_SERVER_RANK)); serverRankItem->setData(0,ITEM_KEY_PVSERVER_TYPE,QVariant(processType)); serverRankItem->setData(0,ITEM_KEY_HOST_NAME,QVariant(hostName.c_str())); serverRankItem->setData(0,ITEM_KEY_PID,QVariant(pid)); serverRankItem->setData(0,ITEM_KEY_SYSTEM_TYPE,QVariant(systemType)); this->Ui->configView->setItemWidget(serverRankItem,0,serverRank->GetMemoryUseWidget()); } // prune off the group if there were none added. if (group->childCount()==0) { int idx=this->Ui->configView->indexOfTopLevelItem(group); if (idx>=0) { this->Ui->configView->takeTopLevelItem(idx); } } } //----------------------------------------------------------------------------- int pqMemoryInspectorPanel::Initialize() { #if defined pqMemoryInspectorPanelDEBUG cerr << ":::::pqMemoryInspectorPanel::Initialize" << endl; #endif this->ClearClient(); this->ClearServers(); this->ClientSystemType=0; this->ServerSystemType=0; this->DataServerSystemType=0; this->RenderServerSystemType=0; this->StackTraceOnClient=0; this->StackTraceOnServer=0; this->StackTraceOnDataServer=0; this->StackTraceOnRenderServer=0; this->Ui->configView->clear(); pqServer* server = pqActiveObjects::instance().activeServer(); if (!server) { // this is not necessarilly an error as the panel may be created // before the server is connected. return 0; } // client QTreeWidgetItem *clientGroup=new QTreeWidgetItem(this->Ui->configView); clientGroup->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless); clientGroup->setExpanded(true); clientGroup->setData(0,ITEM_KEY_PROCESS_TYPE,QVariant(ITEM_DATA_CLIENT_GROUP)); QWidget *groupWidget=this->NewGroupWidget("client",":/pqWidgets/Icons/pqClient32.png"); this->Ui->configView->setItemWidget(clientGroup,0,groupWidget); vtkSMSession *session=NULL; vtkPVSystemConfigInformation *configs=NULL; configs=vtkPVSystemConfigInformation::New(); session=server->session(); session->GatherInformation(vtkPVSession::CLIENT,configs,0); size_t nConfigs=configs->GetSize(); if (nConfigs!=1) { pqErrorMacro("There should always be one client."); return 0; } long long clientPid=configs->GetPid(0); this->ClientHost = new HostData( "paraview", configs->GetHostName(0), configs->GetHostMemoryTotal(0), configs->GetHostMemoryAvailable(0)); this->ClientHost->AddRankData( 0, configs->GetPid(0), configs->GetProcMemoryAvailable(0)); this->ClientSystemType=configs->GetSystemType(0); QTreeWidgetItem *clientHostItem=new QTreeWidgetItem(clientGroup); clientHostItem->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless); clientHostItem->setExpanded(true); clientHostItem->setData(0,ITEM_KEY_PROCESS_TYPE,QVariant(ITEM_DATA_CLIENT_HOST)); clientHostItem->setData(0,ITEM_KEY_PVSERVER_TYPE,QVariant(configs->GetProcessType(0))); clientHostItem->setData(0,ITEM_KEY_SYSTEM_TYPE,QVariant(configs->GetSystemType(0))); clientHostItem->setData(0,ITEM_KEY_HOST_OS,QString(configs->GetOSDescriptor(0))); clientHostItem->setData(0,ITEM_KEY_HOST_CPU,QString(configs->GetCPUDescriptor(0))); clientHostItem->setData(0,ITEM_KEY_HOST_MEM,QString(configs->GetMemoryDescriptor(0))); clientHostItem->setData(0,ITEM_KEY_HOST_NAME,QVariant(configs->GetHostName(0))); clientHostItem->setData(0,ITEM_KEY_PID,QVariant(configs->GetPid(0))); this->Ui->configView->setItemWidget(clientHostItem,0,this->ClientHost->GetMemoryUseWidget()); configs->Delete(); #ifdef MIP_PROCESS_TABLE // print a process table to the terminal. cerr << endl << setw(32) << "Host" << setw(16) << "Pid" << setw(8) << "Rank" << endl << left << setw(56) << setfill('=') << "client" << endl << right<< setw(1) << setfill(' ') << setw(32) << configs->GetFullyQualifiedDomainName(0) << setw(16) << configs->GetPid(0) << setw(8) << "x" << endl << setfill(' ') << setw(1); #endif // collect info from the server(s) configs=vtkPVSystemConfigInformation::New(); vtkPVSystemConfigInformation *dsconfigs=vtkPVSystemConfigInformation::New(); session->GatherInformation(vtkPVSession::DATA_SERVER,dsconfigs,0); configs->AddInformation(dsconfigs); dsconfigs->Delete(); // don't attempt to communicate with a render server if it's // not connected which results in a duplicated gather as in that // case comm is routed to the data server. if (session->GetRenderClientMode()==vtkSMSession::RENDERING_SPLIT) { vtkPVSystemConfigInformation *rsconfigs=vtkPVSystemConfigInformation::New(); session->GatherInformation(vtkPVSession::RENDER_SERVER,rsconfigs,0); configs->AddInformation(rsconfigs); rsconfigs->Delete(); } nConfigs=configs->GetSize(); if (nConfigs>0) { configs->Sort(); // servers #ifdef MIP_PROCESS_TABLE cerr << left << setw(56) << setfill('=') << "server" << endl << right << setw(1) << setfill(' '); #endif QTreeWidgetItem *group=NULL; group = new QTreeWidgetItem(this->Ui->configView); group->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless); group->setExpanded(true); group->setData(0,ITEM_KEY_PROCESS_TYPE,QVariant(ITEM_DATA_SERVER_GROUP)); groupWidget=this->NewGroupWidget("server",":/pqWidgets/Icons/pqDataServer32.png"); this->Ui->configView->addTopLevelItem(group); this->Ui->configView->setItemWidget(group,0,groupWidget); this->InitializeServerGroup( clientPid, configs, vtkProcessModule::PROCESS_SERVER, group, "pvserver", this->ServerHosts, this->ServerRanks, this->ServerSystemType); // dataservers #ifdef MIP_PROCESS_TABLE cerr << left << setw(56) << setfill('=') << "data server" << endl << right << setw(1) << setfill(' '); #endif group = new QTreeWidgetItem(this->Ui->configView); group->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless); group->setExpanded(true); group->setData(0,ITEM_KEY_PROCESS_TYPE,QVariant(ITEM_DATA_SERVER_GROUP)); groupWidget=this->NewGroupWidget("data server",":/pqWidgets/Icons/pqDataServer32.png"); this->Ui->configView->addTopLevelItem(group); this->Ui->configView->setItemWidget(group,0,groupWidget); this->InitializeServerGroup( clientPid, configs, vtkProcessModule::PROCESS_DATA_SERVER, group, "pvdataserver", this->DataServerHosts, this->DataServerRanks, this->DataServerSystemType); // renderservers #ifdef MIP_PROCESS_TABLE cerr << left << setw(56) << setfill('=') << "render server" << endl << right << setw(1) << setfill(' '); #endif group = new QTreeWidgetItem(this->Ui->configView); group->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless); group->setExpanded(true); group->setData(0,ITEM_KEY_PROCESS_TYPE,QVariant(ITEM_DATA_SERVER_GROUP)); groupWidget=this->NewGroupWidget("render server",":/pqWidgets/Icons/pqDataServer32.png"); this->Ui->configView->addTopLevelItem(group); this->Ui->configView->setItemWidget(group,0,groupWidget); this->InitializeServerGroup( clientPid, configs, vtkProcessModule::PROCESS_RENDER_SERVER, group, "pvrenderserver", this->RenderServerHosts, this->RenderServerRanks, this->RenderServerSystemType); #ifdef MIP_PROCESS_TABLE cerr << setw(56) << setfill('=') << "=" << endl << setw(1) << setfill(' '); #endif } configs->Delete(); // this->ClientOnly=0; if ( (this->RenderServerHosts.size()==0) && (this->DataServerHosts.size()==0) && (this->ServerHosts.size()==0)) { this->ClientOnly=1; } else { // update host load to reflect all of its ranks. map::iterator it; map::iterator end; it=this->DataServerHosts.begin(); end=this->DataServerHosts.end(); while (it!=end) { it->second->UpdateMemoryUseWidget(); ++it; } it=this->RenderServerHosts.begin(); end=this->RenderServerHosts.end(); while (it!=end) { it->second->UpdateMemoryUseWidget(); ++it; } } // this->Ui->configView->resizeColumnToContents(0); this->Ui->configView->resizeColumnToContents(1); // fecth the remote memory usage this->Update(); // don't expand by default when there are a lot of // sever hosts if ( (this->RenderServerHosts.size()>1) || (this->DataServerHosts.size()>1) || (this->ServerHosts.size()>2) ) { this->ShowOnlyNodes(); } else { this->ShowAllRanks(); } return 1; } //----------------------------------------------------------------------------- void pqMemoryInspectorPanel::Update() { #if defined pqMemoryInspectorPanelDEBUG cerr << ":::::pqMemoryInspectorPanel::Update" << endl; #endif pqServer* server = pqActiveObjects::instance().activeServer(); if (!server) { return; } if (!this->Initialized() && !this->Initialize()) { return; } this->UpdateRanks(); this->UpdateHosts(); this->PendingUpdate=0; this->UpdateEnabled=0; } //----------------------------------------------------------------------------- void pqMemoryInspectorPanel::UpdateRanks() { #if defined pqMemoryInspectorPanelDEBUG cerr << ":::::pqMemoryInspectorPanel::UpdateRanks" << endl; #endif pqServer* server = pqActiveObjects::instance().activeServer(); if (!server) { pqErrorMacro("failed to get active server"); return; } // fectch latest numbers vtkSMSession *session=NULL; vtkPVMemoryUseInformation *infos=NULL; size_t nInfos=0; // client infos=vtkPVMemoryUseInformation::New(); session=server->session(); session->GatherInformation(vtkPVSession::CLIENT,infos,0); nInfos=infos->GetSize(); if (nInfos==0) { pqErrorMacro("failed to get client info"); return; } RankData *clientRank=this->ClientHost->GetRankData(0); clientRank->SetProcMemoryUse(infos->GetProcMemoryUse(0)); clientRank->SetHostMemoryUse(infos->GetHostMemoryUse(0)); clientRank->UpdateMemoryUseWidget(); infos->Delete(); if (this->ClientOnly) { return; } // servers infos=vtkPVMemoryUseInformation::New(); vtkPVMemoryUseInformation *dsinfos=vtkPVMemoryUseInformation::New(); session->GatherInformation(vtkPVSession::DATA_SERVER,dsinfos,0); infos->AddInformation(dsinfos); dsinfos->Delete(); // don't attempt to communicate with a render server if it's // not connected which results in a duplicated gather as in that // case comm is routed to the data server. if (session->GetRenderClientMode()==vtkSMSession::RENDERING_SPLIT) { vtkPVMemoryUseInformation *rsinfos=vtkPVMemoryUseInformation::New(); session->GatherInformation(vtkPVSession::RENDER_SERVER,rsinfos,0); infos->AddInformation(rsinfos); rsinfos->Delete(); } nInfos=infos->GetSize(); for (size_t i=0; iGetRank((int)i); long long procUse=infos->GetProcMemoryUse((int)i); long long hostUse=infos->GetHostMemoryUse((int)i); switch (infos->GetProcessType((int)i)) { case vtkProcessModule::PROCESS_SERVER: if (this->ServerRanks.size()) { this->ServerRanks[rank]->SetProcMemoryUse(procUse); this->ServerRanks[rank]->SetHostMemoryUse(hostUse); this->ServerRanks[rank]->UpdateMemoryUseWidget(); } break; case vtkProcessModule::PROCESS_DATA_SERVER: if (this->DataServerRanks.size()) { this->DataServerRanks[rank]->SetProcMemoryUse(procUse); this->DataServerRanks[rank]->SetHostMemoryUse(hostUse); this->DataServerRanks[rank]->UpdateMemoryUseWidget(); } break; case vtkProcessModule::PROCESS_RENDER_SERVER: if (this->RenderServerRanks.size()) { this->RenderServerRanks[rank]->SetProcMemoryUse(procUse); this->RenderServerRanks[rank]->SetHostMemoryUse(hostUse); this->RenderServerRanks[rank]->UpdateMemoryUseWidget(); } break; case vtkProcessModule::PROCESS_INVALID: case vtkProcessModule::PROCESS_CLIENT: default: continue; } } infos->Delete(); } //----------------------------------------------------------------------------- void pqMemoryInspectorPanel::UpdateHosts() { #if defined pqMemoryInspectorPanelDEBUG cerr << ":::::pqMemoryInspectorPanel::UpdateHosts" << endl; #endif this->ClientHost->UpdateMemoryUseWidget(); if (this->ClientOnly) { return; } this->UpdateHosts(this->ServerHosts); this->UpdateHosts(this->DataServerHosts); this->UpdateHosts(this->RenderServerHosts); } //----------------------------------------------------------------------------- void pqMemoryInspectorPanel::UpdateHosts(map &hosts) { // update host laod to reflect all of its ranks. map::iterator it=hosts.begin(); map::iterator end=hosts.end(); while (it!=end) { (*it).second->UpdateMemoryUseWidget(); ++it; } } //----------------------------------------------------------------------------- void pqMemoryInspectorPanel::EnableStackTraceOnClient(bool enable) { this->EnableStackTrace(enable,vtkPVSession::CLIENT); this->StackTraceOnClient=enable; } //----------------------------------------------------------------------------- void pqMemoryInspectorPanel::EnableStackTraceOnServer(bool enable) { this->EnableStackTrace(enable,vtkPVSession::DATA_SERVER); this->StackTraceOnServer=enable; } //----------------------------------------------------------------------------- void pqMemoryInspectorPanel::EnableStackTraceOnDataServer(bool enable) { this->EnableStackTrace(enable,vtkPVSession::DATA_SERVER); this->StackTraceOnDataServer=enable; } //----------------------------------------------------------------------------- void pqMemoryInspectorPanel::EnableStackTraceOnRenderServer(bool enable) { this->EnableStackTrace(enable,vtkPVSession::RENDER_SERVER); this->StackTraceOnRenderServer=enable; } //----------------------------------------------------------------------------- void pqMemoryInspectorPanel::EnableStackTrace(bool enable, int group) { pqServer* server = pqActiveObjects::instance().activeServer(); if (!server) { pqErrorMacro("Failed to get the server"); return; } if (enable) { vtkPVEnableStackTraceSignalHandler *esh = vtkPVEnableStackTraceSignalHandler::New(); server->session()->GatherInformation(group,esh,0); } else { vtkPVDisableStackTraceSignalHandler *dsh = vtkPVDisableStackTraceSignalHandler::New(); server->session()->GatherInformation(group,dsh,0); } } //----------------------------------------------------------------------------- void pqMemoryInspectorPanel::ExecuteRemoteCommand() { #if defined pqMemoryInspectorPanelDEBUG cerr << ":::::pqMemoryInspectorPanel::ExecCommand" << endl; #endif QTreeWidgetItem *item=this->Ui->configView->currentItem(); if (item) { bool ok; int type=item->data(0,ITEM_KEY_PROCESS_TYPE).toInt(&ok); if (!ok) return; // treate the client group like a rank. if (type==ITEM_DATA_CLIENT_GROUP) { item=item->child(0); if (item==NULL) return; type=item->data(0,ITEM_KEY_PROCESS_TYPE).toInt(); } // treate the client host like a rank. if (type==ITEM_DATA_CLIENT_HOST) { type=ITEM_DATA_CLIENT_RANK; } switch (type) { case ITEM_DATA_CLIENT_RANK: case ITEM_DATA_SERVER_RANK: { string host((const char *)item->data(0,ITEM_KEY_HOST_NAME).toString().toLatin1()); string pid((const char *)item->data(0,ITEM_KEY_PID).toString().toLatin1()); int serverSystemType=item->data(0,ITEM_KEY_SYSTEM_TYPE).toInt(); bool localServer=(this->ClientHost->GetHostName()==host); if (localServer) { serverSystemType=-1; } // select and configure a command pqRemoteCommandDialog dialog(this,0,this->ClientSystemType,serverSystemType); dialog.SetActiveHost(host); dialog.SetActivePid(pid); if (dialog.exec()==QDialog::Accepted) { string command=dialog.GetCommand(); string tmp; QString exe; QStringList args; istringstream is(command); is >> tmp; ::unescapeWhitespace(tmp,'^'); exe = tmp.c_str(); while (is.good()) { is >> tmp; ::unescapeWhitespace(tmp,'^'); args << tmp.c_str(); } QProcess *proc = new QProcess(this); QObject::connect( proc, SIGNAL(error(QProcess::ProcessError)), this, SLOT(RemoteCommandFailed(QProcess::ProcessError))); proc->setProcessChannelMode(QProcess::ForwardedChannels); proc->closeWriteChannel(); proc->startDetached(exe,args); } } break; default: QMessageBox ebx( QMessageBox::Information, "Error", "No process selected. Select a specific process first by " "clicking on its entry in the tree view widget."); ebx.exec(); break; } } else { QMessageBox ebx( QMessageBox::Information, "Error", "No process selected. Select a specific process first by " "clicking on its entry in the tree view widget."); ebx.exec(); } } //----------------------------------------------------------------------------- void pqMemoryInspectorPanel::RemoteCommandFailed( QProcess::ProcessError code) { switch (code) { case QProcess::FailedToStart: qCritical() << "The process failed to start. Either the invoked program is missing, " "or you may have insufficient permissions to invoke the program."; break; case QProcess::Crashed: qCritical() << "The process crashed some time after starting successfully."; break; default: qCritical() << "Process failed with error"; } } //----------------------------------------------------------------------------- void pqMemoryInspectorPanel::ShowOnlyNodes() { #if defined pqMemoryInspectorPanelDEBUG cerr << ":::::pqMemoryInspectorPanel::ShowOnlyNodes" << endl; #endif this->Ui->configView->collapseAll(); QTreeWidgetItem *item; QTreeWidgetItemIterator it(this->Ui->configView); while ((item=*it)!=(QTreeWidgetItem*)0) { bool ok; int type=item->data(0,ITEM_KEY_PROCESS_TYPE).toInt(&ok); if (!ok) return; switch (type) { case ITEM_DATA_CLIENT_GROUP: case ITEM_DATA_SERVER_GROUP: case ITEM_DATA_CLIENT_HOST: item->setExpanded(true); break; case ITEM_DATA_SERVER_HOST: item->setExpanded(false); break; case ITEM_DATA_CLIENT_RANK: case ITEM_DATA_SERVER_RANK: break; } ++it; } } //----------------------------------------------------------------------------- void pqMemoryInspectorPanel::ShowAllRanks() { #if defined pqMemoryInspectorPanelDEBUG cerr << ":::::pqMemoryInspectorPanel::ShowAllRanks" << endl; #endif this->Ui->configView->expandAll(); } //----------------------------------------------------------------------------- void pqMemoryInspectorPanel::ShowHostPropertiesDialog() { #if defined pqMemoryInspectorPanelDEBUG cerr << ":::::pqMemoryInspectorPanel::ShowHostPropertiesDialog" << endl; #endif QTreeWidgetItem *item=this->Ui->configView->currentItem(); if (!item) { return; } int type=item->data(0,ITEM_KEY_PROCESS_TYPE).toInt(); // treate the client group like a host. if (type==ITEM_DATA_CLIENT_GROUP) { item=item->child(0); if (item==NULL) return; type=item->data(0,ITEM_KEY_PROCESS_TYPE).toInt(); } if ( (type==ITEM_DATA_CLIENT_HOST) || (type==ITEM_DATA_SERVER_HOST) ) { QString host=item->data(0,ITEM_KEY_HOST_NAME).toString(); QString os=item->data(0,ITEM_KEY_HOST_OS).toString(); QString cpu=item->data(0,ITEM_KEY_HOST_CPU).toString(); QString mem=item->data(0,ITEM_KEY_HOST_MEM).toString(); QString descr; descr+="

"; descr+=(type==ITEM_DATA_CLIENT_HOST?"Client":"Server"); descr+=" System Properties


"; descr+=""; descr+=""; descr+=""; descr+="
Host:"; descr+=host; descr+="
OS:"; descr+=os; descr+="
CPU:"; descr+=cpu; descr+="
Memory:"; descr+=mem; descr+="

"; QMessageBox props(QMessageBox::Information,"",descr,QMessageBox::Ok,this); props.exec(); } } //----------------------------------------------------------------------------- void pqMemoryInspectorPanel::ConfigViewContextMenu(const QPoint &position) { #if defined pqMemoryInspectorPanelDEBUG cerr << ":::::pqMemoryInspectorPanel::ConfigContextMenu" << endl; #endif QMenu context; QTreeWidgetItem * item=this->Ui->configView->itemAt(position); if (item) { bool ok; int procType=item->data(0,ITEM_KEY_PROCESS_TYPE).toInt(&ok); if (!ok) { return; } switch(procType) { case ITEM_DATA_CLIENT_GROUP: { QTreeWidgetItem *child=item->child(0); if (child==NULL) return; context.addAction("properties...",this,SLOT(ShowHostPropertiesDialog())); int sysType=child->data(0,ITEM_KEY_SYSTEM_TYPE).toInt(&ok); if (!ok) return; if (sysType==ITEM_DATA_UNIX_SYSTEM) { int serverType=child->data(0,ITEM_KEY_PVSERVER_TYPE).toInt(&ok); if (!ok) return; this->AddEnableStackTraceMenuAction(serverType,context); context.addAction("remote command...",this,SLOT(ExecuteRemoteCommand())); } } break; case ITEM_DATA_SERVER_GROUP: { context.addAction("show only nodes",this,SLOT(ShowOnlyNodes())); context.addAction("show all ranks",this,SLOT(ShowAllRanks())); QTreeWidgetItem *child=item->child(0); if (child==NULL) return; int sysType=child->data(0,ITEM_KEY_SYSTEM_TYPE).toInt(&ok); if (!ok) return; int serverType=child->data(0,ITEM_KEY_PVSERVER_TYPE).toInt(&ok); if (!ok) return; if (sysType==ITEM_DATA_UNIX_SYSTEM) { this->AddEnableStackTraceMenuAction(serverType,context); } } break; case ITEM_DATA_CLIENT_HOST: case ITEM_DATA_CLIENT_RANK: { context.addAction("properties...",this,SLOT(ShowHostPropertiesDialog())); int sysType=item->data(0,ITEM_KEY_SYSTEM_TYPE).toInt(&ok); if (!ok) return; if (sysType==ITEM_DATA_UNIX_SYSTEM) { context.addAction("remote command...",this,SLOT(ExecuteRemoteCommand())); } } break; case ITEM_DATA_SERVER_HOST: { context.addAction("properties...",this,SLOT(ShowHostPropertiesDialog())); } break; case ITEM_DATA_SERVER_RANK: { context.addAction("show only nodes",this,SLOT(ShowOnlyNodes())); context.addAction("show all ranks",this,SLOT(ShowAllRanks())); int sysType=item->data(0,ITEM_KEY_SYSTEM_TYPE).toInt(&ok); if (!ok) return; if (sysType==ITEM_DATA_UNIX_SYSTEM) { context.addAction("remote command...",this,SLOT(ExecuteRemoteCommand())); } } break; } } context.exec(this->Ui->configView->mapToGlobal(position)); } //----------------------------------------------------------------------------- void pqMemoryInspectorPanel::AddEnableStackTraceMenuAction( int serverType, QMenu &context) { QAction *action=new QAction(this); action->setText("stack trace signal handler"); action->setCheckable(true); switch (serverType) { case vtkProcessModule::PROCESS_CLIENT: action->setChecked(this->StackTraceOnClient); connect(action, SIGNAL(toggled(bool)), this, SLOT(EnableStackTraceOnClient(bool))); break; case vtkProcessModule::PROCESS_SERVER: action->setChecked(this->StackTraceOnServer); connect(action, SIGNAL(toggled(bool)), this, SLOT(EnableStackTraceOnServer(bool))); break; case vtkProcessModule::PROCESS_DATA_SERVER: action->setChecked(this->StackTraceOnDataServer); connect(action, SIGNAL(toggled(bool)), this, SLOT(EnableStackTraceOnDataServer(bool))); break; case vtkProcessModule::PROCESS_RENDER_SERVER: action->setChecked(this->StackTraceOnRenderServer); connect(action, SIGNAL(toggled(bool)), this, SLOT(EnableStackTraceOnRenderServer(bool))); break; } context.addAction(action); } //----------------------------------------------------------------------------- QWidget *pqMemoryInspectorPanel::NewGroupWidget(string name, string icon) { QHBoxLayout *hlayout=new QHBoxLayout; QLabel *label=new QLabel; label->setPixmap(QPixmap(icon.c_str())); label->setToolTip(name.c_str()); hlayout->addWidget(label); label=new QLabel; label->setText(name.c_str()); hlayout->addWidget(label); hlayout->addStretch(-1); QFrame *frame=new QFrame; frame->setLayout(hlayout); QFont ffont(frame->font()); ffont.setPointSize(9); ffont.setBold(true); frame->setFont(ffont); return frame; }