00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "MonitorWindow.h"
00019 #include "RioError.h"
00020 #include "Events.h"
00021
00022
00023 #include "CommonLibraries.h"
00024 #include "LogRotation.h"
00025 #include <zlib.h>
00026
00027
00028 #include <sys/socket.h>
00029 #include <netinet/in.h>
00030 #include <arpa/inet.h>
00031
00032 #include <qapplication.h>
00033 #include <qmenubar.h>
00034 #include <qdatetime.h>
00035 #include <qmessagebox.h>
00036 #include <qprogressbar.h>
00037 #include <qsplitter.h>
00038 #include <qobjectlist.h>
00039 #include <qvbox.h>
00040 #include <qbuttongroup.h>
00041 #include <qradiobutton.h>
00042 #include <qpushbutton.h>
00043 #include <qlayout.h>
00044 #include <qdatetime.h>
00045 #include <qpixmap.h>
00046 #include <qfiledialog.h>
00047
00048
00049 #include <qt.h>
00050 #include <qwt_legend.h>
00051 #include <qsizepolicy.h>
00052 #include <qwt_painter.h>
00053 #include <qwt_plot_curve.h>
00054 #include <qwt_plot_layout.h>
00055
00056 #include <string>
00057 #include "images/client_icon.xpm"
00058 #include "images/storage_icon.xpm"
00059 #include "images/disk_icon.xpm"
00060
00061 #define CLIENT_TOTAL_COLS 5
00062 enum { IP, PORT, VIDEO, TIME, QUEUE };
00063
00064 #define STORAGE_TOTAL_COLS 4
00065 enum { S_IP, S_HOSTNAME, S_DISK, S_QUEUE };
00066
00067 #define STORAGE_RESIZE_FACTOR 10
00068 #define CLIENT_RESIZE_FACTOR 10
00069
00070 #define STORAGE_CLEAR_INTERVAL 2000
00071
00072
00073 ClientTable::ClientTable( QWidget *parent, const char *name )
00074 : QTable( parent, name )
00075 {
00076 setNumRows( 0 );
00077 setNumCols( CLIENT_TOTAL_COLS );
00078 horizontalHeader()->setLabel( IP, tr( "Client IP" ) );
00079 horizontalHeader()->setLabel( PORT, tr( "Port" ) );
00080 horizontalHeader()->setLabel( VIDEO, tr( "Current Video" ) );
00081 horizontalHeader()->setLabel( TIME, tr( "Connection Time" ) );
00082 horizontalHeader()->setLabel( QUEUE, tr( "Queue Size" ) );
00083
00084 int column;
00085 for( column = 0; column < CLIENT_TOTAL_COLS; column++ )
00086 {
00087 setColumnWidth( column, 0 );
00088 adjustColumn( column );
00089 }
00090
00091 horizontalHeader()->setStretchEnabled( true, QUEUE );
00092 horizontalHeader()->adjustHeaderSize();
00093
00094 setCaption( tr( "Connected Clients" ) );
00095 setShowGrid( false );
00096 setReadOnly( true );
00097 }
00098
00099 void ClientTable::setTable( vector<ClientData> table )
00100 {
00101 setNumRows( table.size() );
00102 for( unsigned int row = 0; row < table.size(); row++ )
00103 {
00104 verticalHeader()->setLabel( row,
00105 QIconSet( (const char **) image_client_icon ),
00106 QString::number( row + 1 ) );
00107 if( text( row, IP ) != table[row].m_ip )
00108 setText( row, IP, table[row].m_ip );
00109 if( text( row, PORT ) != QString::number( table[row].m_port ) )
00110 setText( row, PORT, QString::number( table[row].m_port ) );
00111 if( text( row, VIDEO ) != table[row].m_video )
00112 setText( row, VIDEO, table[row].m_video );
00113
00114 QTime time;
00115 time = time.addSecs( table[row].m_time );
00116 if( text( row, TIME ) != time.toString( Qt::TextDate ) )
00117 setText( row, TIME, time.toString( Qt::TextDate ) );
00118
00119 if( cellWidget( row, QUEUE ) == 0 )
00120 {
00121 QProgressBar *prog_bar = new QProgressBar();
00122 prog_bar->setPercentageVisible( false );
00123 setCellWidget( row, QUEUE, prog_bar );
00124 setRowHeight( row, (int)(1.25 * rowHeight( row )) );
00125 prog_bar->setFixedHeight( rowHeight( row ) );
00126 }
00127 if( ((QProgressBar *)cellWidget( row, QUEUE ))->progress() !=
00128 table[row].m_queue )
00129 ((QProgressBar *)cellWidget( row, QUEUE ))->setProgress(
00130 table[row].m_queue );
00131 }
00132
00133 for( int column = 0; column < CLIENT_TOTAL_COLS-1; column++ )
00134 adjustColumn( column );
00135 horizontalHeader()->adjustHeaderSize();
00136 }
00137
00138
00139 StorageTable::StorageTable( QWidget *parent, const char *name )
00140 : QTable( parent, name )
00141 {
00142 setNumRows( 0 );
00143 setNumCols( STORAGE_TOTAL_COLS );
00144 horizontalHeader()->setLabel( S_IP, tr( "IP" ) );
00145 horizontalHeader()->setLabel( S_HOSTNAME, tr( "Host Name" ) );
00146 horizontalHeader()->setLabel( S_DISK, tr( "Disks" ) );
00147 horizontalHeader()->setLabel( S_QUEUE, tr( "Queue Size" ) );
00148
00149 int column;
00150 for( column = 0; column < STORAGE_TOTAL_COLS; column++ )
00151 {
00152 setColumnWidth( column, 0 );
00153 adjustColumn( column );
00154 }
00155
00156 horizontalHeader()->setStretchEnabled( true, S_QUEUE );
00157 horizontalHeader()->adjustHeaderSize();
00158
00159 setCaption( tr( "Storage Nodes" ) );
00160 setShowGrid( false );
00161 setReadOnly( true );
00162 }
00163
00164 void StorageTable::clear()
00165 {
00166 for( int row = 0; row < numRows(); row++ )
00167 {
00168 QProgressBar *prog_bar = ((QProgressBar *)cellWidget( row, S_QUEUE ));
00169 prog_bar->setProgress( 0 );
00170 }
00171 }
00172
00173 void StorageTable::setTable( vector<StorageData> table )
00174 {
00175 setNumRows( table.size() );
00176 int host_num = 0, disk_num = 0;
00177 for( unsigned int row = 0; row < table.size(); row++ )
00178 {
00179 if( text( row, S_IP ) != table[row].m_ip )
00180 setText( row, S_IP, table[row].m_ip );
00181 if( text( row, S_HOSTNAME ) != table[row].m_hostname )
00182 setText( row, S_HOSTNAME, table[row].m_hostname );
00183 if( text( row, S_DISK ) != table[row].m_diskname )
00184 setText( row, S_DISK, table[row].m_diskname );
00185 if( cellWidget( row, S_QUEUE ) == 0 )
00186 {
00187 QProgressBar *prog_bar = new QProgressBar();
00188 prog_bar->setPercentageVisible( false );
00189 setCellWidget( row, S_QUEUE, prog_bar );
00190 setRowHeight( row, (int)(1.25 * rowHeight( row )) );
00191 prog_bar->setFixedHeight( rowHeight( row ) );
00192 verticalHeader()->setLabel( row, "0" );
00193 }
00194 if( ((QProgressBar *)cellWidget( row, S_QUEUE ))->progress() !=
00195 table[row].m_queue )
00196 ((QProgressBar *)cellWidget( row, S_QUEUE ))->setProgress(
00197 table[row].m_queue );
00198
00199 if( text( row, S_IP ).isEmpty() )
00200 {
00201 QString row_text =
00202 QString::number( host_num ) + "." +
00203 QString::number( ++disk_num );
00204 if( verticalHeader()->label( row ) != row_text )
00205 verticalHeader()->setLabel( row,
00206 QIconSet( (const char **) image_disk_icon ),
00207 row_text );
00208 }
00209 else
00210 {
00211 QString row_text = QString::number( ++host_num );
00212 disk_num = 0;
00213 if( verticalHeader()->label( row ) != row_text )
00214 verticalHeader()->setLabel( row,
00215 QIconSet( (const char **) image_storage_icon ),
00216 row_text );
00217 }
00218 }
00219
00220 for( int column = 0; column < STORAGE_TOTAL_COLS-1; column++ )
00221 adjustColumn( column );
00222 horizontalHeader()->adjustHeaderSize();
00223 }
00224
00225
00226
00227
00228
00229 QwtData *LogPoints::copy() const
00230 {
00231 LogPoints *CopyPoints;
00232 CopyPoints = new LogPoints;
00233 if( CopyPoints != NULL )
00234 CopyPoints->Points = Points;
00235 return CopyPoints;
00236 }
00237
00238
00239 size_t LogPoints::size() const
00240 {
00241 return Points.size();
00242 }
00243
00244
00245 double LogPoints::x( size_t i ) const
00246 {
00247 if( i < Points.size() )
00248 return Points[ i ].x();
00249 else
00250 return -1;
00251 }
00252
00253
00254 double LogPoints::y( size_t i ) const
00255 {
00256 if( i < Points.size() )
00257 return Points[ i ].y();
00258 else
00259 return -1;
00260 }
00261
00262
00263 bool LogPoints::push( double x, double y )
00264 {
00265 unsigned int ExpectedSize;
00266 QwtDoublePoint NewPoint( x, y );
00267 ExpectedSize = Points.size() + 1;
00268 Points.push_back( NewPoint );
00269 return( ExpectedSize != Points.size() );
00270 }
00271
00272
00273 double LogPoints::firstX()
00274 {
00275 if( Points.size() > 0 )
00276 return Points.front().x();
00277 else
00278 return -1;
00279 }
00280
00281 double LogPoints::firstY()
00282 {
00283 if( Points.size() > 0 )
00284 return Points.front().y();
00285 else
00286 return -1;
00287 }
00288
00289
00290 double LogPoints::lastX()
00291 {
00292 if( Points.size() > 0 )
00293 return Points.back().x();
00294 else
00295 return -1;
00296 }
00297
00298 double LogPoints::lastY()
00299 {
00300 if( Points.size() > 0 )
00301 return Points.back().y();
00302 else
00303 return -1;
00304 }
00305
00306
00307 bool LogPoints::setLastX( double x )
00308 {
00309 if( Points.size() > 0 )
00310 {
00311 Points.back().setX( x );
00312 return true;
00313 }
00314 else
00315 return false;
00316 }
00317
00318
00319 bool LogPoints::setLastY( double y )
00320 {
00321 if( Points.size() > 0 )
00322 {
00323 Points.back().setY( y );
00324 return true;
00325 }
00326 else
00327 return false;
00328 }
00329
00330
00331 void LogPoints::clear()
00332 {
00333 Points.clear();
00334 }
00335
00336
00337
00338
00339 TimeScaleDraw::TimeScaleDraw()
00340 {
00341 m_AxisLabel = TimeLabel;
00342 }
00343
00344
00345
00346
00347 AxisLabel TimeScaleDraw::getAxisLabel()
00348 {
00349 return m_AxisLabel;
00350 }
00351
00352
00353
00354 void TimeScaleDraw::setAxisLabel( AxisLabel Label )
00355 {
00356 m_AxisLabel = Label;
00357 }
00358
00359
00360
00361 QwtText TimeScaleDraw::label( double v ) const
00362 {
00363 QDateTime date_time;
00364 date_time.setTime_t( (int)v );
00365 if( m_AxisLabel == DateLabel )
00366 return QwtText( date_time.toString( "dd/MM" ) );
00367 else
00368 return QwtText( date_time.toString( "hh:mm" ) );
00369 }
00370
00371
00372 LogPlot::LogPlot( QWidget *parent, char *name ) : QwtPlot( parent, name )
00373 {
00374
00375 QwtLegend *legend = new QwtLegend();
00376 insertLegend( legend, QwtPlot::TopLegend );
00377
00378 setCanvasBackground( Qt::white );
00379
00380 xAxis = new TimeScaleDraw();
00381 setAxisScaleDraw( xBottom, xAxis );
00382
00383 plotLayout()->setAlignCanvasToScales( true );
00384 }
00385
00386
00387
00388 bool LogPlot::ProcessConnectedClientsLogLine( char *LogLine )
00389 {
00390
00391 unsigned long LogTime;
00392
00393
00394 unsigned int LogValue;
00395
00396 char LogOperation[ MAXLOGLINESIZE + 1 ];
00397
00398
00399 int ScanCount;
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415 ScanCount = sscanf( LogLine, "%lu %u %s %*s %*s %*u", &LogTime, &LogValue,
00416 ( char * ) &LogOperation );
00417 if( ( ScanCount == 3 ) &&
00418 ( ( strcmp( LogOperation, "Connected" ) == 0 ) ||
00419 ( strcmp( LogOperation, "Disconnected" ) == 0 ) ) )
00420 {
00421 #ifdef RIO_DEBUG2
00422 RioErr << "MonitorWindow::ProcessConnectedClientsLogLine verificando o "
00423 << "log no tempo " << LogTime << " e o valor " << LogValue
00424 << ". Numero de pontos e igual a " << Points.size() << endl;
00425 #endif
00426
00427
00428 if( ( Points.size() == 0 ) ||
00429 ( ( unsigned int ) Points.lastX() != LogTime ) )
00430 {
00431
00432 if( Points.size() != 0 )
00433 {
00434
00435
00436
00437
00438
00439
00440
00441
00442 unsigned int StartTime;
00443 StartTime = ( ( unsigned int ) Points.lastX() ) + 1;
00444
00445 #ifdef RIO_DEBUG2
00446 RioErr << "MonitorWindow::ProcessConnectedClientsLogLine "
00447 << "colocando os pontos com os tempos de " << StartTime
00448 << " ate " << LogTime - 1 << " usando o valor "
00449 << Points.lastY() << " em cada um destes pontos"
00450 << endl;
00451 #endif
00452
00453 Points.push( StartTime, LogValue );
00454 }
00455 #ifdef RIO_DEBUG2
00456 RioErr << "MonitorWindow::ProcessConnectedClientsLogLine colocando "
00457 << "o ponto (" << LogTime << ", " << LogValue
00458 << ") em Points" << endl;
00459 #endif
00460
00461 Points.push( LogTime, LogValue );
00462 }
00463 else
00464 {
00465
00466
00467 if( Points.lastX() < LogValue )
00468 {
00469 #ifdef RIO_DEBUG2
00470 RioErr << "MonitorWindow::ProcessConnectedClientsLogLine "
00471 << "atualizando o ponto (" << Points.lastX() << ", "
00472 << Points.lastY() << ") para o ponto (" << LogTime
00473 << ", " << LogValue << ") em Points" << endl;
00474 #endif
00475 Points.setLastY( LogValue );
00476 }
00477 }
00478 return true;
00479 }
00480 else if( ScanCount == 3 )
00481 {
00482
00483 #ifdef RIO_DEBUG2
00484 RioErr << "MonitorWindow::ProcessConnectedClientsLogLine LogOperation "
00485 << LogOperation << endl;
00486 RioErr << "MonitorWindow::ProcessConnectedClientsLogLine a linha "
00487 << LogLine << " foi ignorada!" << endl;
00488 #endif
00489 return true;
00490 }
00491 else
00492 {
00493
00494 #ifdef RIO_DEBUG2
00495 RioErr << "MonitorWindow::ProcessConnectedClientsLogLine a linha "
00496 << LogLine << " esta em um formato incorreto!" << endl;
00497 #endif
00498 return false;
00499 }
00500 }
00501
00502
00503
00504 bool LogPlot::ProcessSendRateLogLine( char *LogLine )
00505 {
00506
00507 unsigned long LogTime;
00508
00509
00510 unsigned int LogValue;
00511
00512
00513
00514
00515
00516
00517
00518
00519 if( sscanf( LogLine, "%lu %u", &LogTime, &LogValue ) == 2 )
00520 {
00521 #ifdef RIO_DEBUG2
00522 RioErr << "MonitorWindow::ProcessSendRateLogLine verificando o log no "
00523 << "tempo " << LogTime << " e o valor " << LogValue
00524 << ". Numero de pontos e igual a " << Points.size() << endl;
00525 #endif
00526
00527
00528 if( ( Points.size() == 0 ) ||
00529 ( ( unsigned int ) Points.lastX() != LogTime ) )
00530 {
00531
00532 if( Points.size() != 0 )
00533 {
00534
00535
00536 Points.setLastY( Points.lastY() / 1000000.0 );
00537
00538
00539
00540
00541
00542
00543
00544 unsigned int StartTime;
00545 StartTime = ( ( unsigned int ) Points.lastX() ) + 1;
00546
00547 #ifdef RIO_DEBUG2
00548 RioErr << "MonitorWindow::ProcessSendRateLogLine colocando os "
00549 << "pontos com os tempos de " << StartTime << " ate "
00550 << LogTime - 1 << " usando o valor 0 em cada um destes "
00551 << "pontos" << endl;
00552 #endif
00553
00554 for( unsigned int t = StartTime; t < LogTime; t++ )
00555 Points.push( t, 0 );
00556 }
00557
00558 #ifdef RIO_DEBUG2
00559 RioErr << "MonitorWindow::ProcessSendRateLogLine colocando o ponto"
00560 << " (" << LogTime << ", " << ( LogValue * 8 ) / 1000000.0
00561 << ") em Points" << endl;
00562 #endif
00563
00564
00565
00566 #ifdef RIO_DEBUG2
00567 RioErr << "MonitorWindow::ProcessSendRateLogLine atualizando o "
00568 << "ponto (" << Points.lastX() << ", " << Points.lastY()
00569 << ") para o ponto (" << LogTime << ", "
00570 << ( Points.lastY() + ( LogValue * 8 ) ) << ") em Points"
00571 << endl;
00572 #endif
00573 Points.push( LogTime, ( LogValue * 8 ) );
00574 }
00575 else
00576 {
00577
00578
00579
00580 Points.setLastY( Points.lastY() + ( LogValue * 8 ) );
00581 }
00582 return true;
00583 }
00584 else
00585 {
00586
00587 #ifdef RIO_DEBUG2
00588 RioErr << "MonitorWindow::ProcessSendRateLogLine a linha " << LogLine
00589 << " esta em um formato incorreto!" << endl;
00590 #endif
00591 return false;
00592 }
00593 }
00594
00595
00596 bool LogPlot::ProcessSearchLogs( char *FileName, unsigned int SearchType,
00597 QString ServerAddress )
00598 {
00599
00600 gzFile File;
00601
00602 char LogLine[ MAXLOGLINESIZE + 1 ];
00603
00604
00605 bool NoError;
00606
00607 QwtPlotCurve *Curve;
00608
00609
00610 Points.clear();
00611 detachItems();
00612
00613
00614 if( ( SearchType == SEARCHINTRAFFICLOGS ) ||
00615 ( SearchType == SEARCHINCLIENTSLOGS ) )
00616 {
00617
00618 File = gzopen( FileName, "rb" );
00619 NoError = ( File != NULL );
00620 }
00621 else
00622 {
00623 NoError = false;
00624 File = NULL;
00625 }
00626 if( File != NULL )
00627 {
00628 while( ( NoError ) && ( !gzeof( File ) ) )
00629 {
00630
00631 if( gzgets( File, LogLine, MAXLOGLINESIZE ) != Z_NULL )
00632 {
00633 #ifdef RIO_DEBUG2
00634 RioErr << "MonitorWindow::ProcessSearchLogs Processando a "
00635 << " linha " << LogLine << " do arquivo " << FileName
00636 << endl;
00637 #endif
00638
00639 switch( SearchType )
00640 {
00641
00642
00643 case SEARCHINTRAFFICLOGS:
00644 NoError = ProcessSendRateLogLine( LogLine );
00645 break;
00646
00647 case SEARCHINCLIENTSLOGS:
00648 NoError = ProcessConnectedClientsLogLine( LogLine );
00649 break;
00650
00651
00652 default:
00653 NoError = false;
00654 break;
00655 }
00656 }
00657 else
00658 NoError = false;
00659 }
00660
00661 gzclose( File );
00662 }
00663
00664
00665 if( !NoError )
00666 {
00667 #ifdef RIO_DEBUG2
00668 RioErr << "MonitorWindow::ProcessSearchLogs Erro ao ler o arquivo "
00669 << FileName << " com os logs" << endl;
00670 #endif
00671 Points.clear();
00672
00673 return false;
00674 }
00675 else
00676 {
00677
00678
00679
00680 if( ( Points.size() != 0 ) && ( SearchType == SEARCHINTRAFFICLOGS ) )
00681 Points.setLastY( Points.lastY() / 1000000.0 );
00682
00683
00684 #ifdef RIO_DEBUG2
00685 RioErr << "MonitorWindow::ProcessSearchLogs O arquivo " << FileName
00686 << " foi processado com sucesso" << endl;
00687 #endif
00688
00689
00690 Curve = new QwtPlotCurve( ServerAddress );
00691
00692
00693 Curve->setData( Points );
00694
00695
00696 setAxisScale( QwtPlot::xBottom, Points.firstX(), Points.lastX() );
00697
00698 Curve->setPen( QPen( blue ) );
00699
00700
00701
00702
00703
00704 if( Points.lastX() - Points.firstX() > 86400 )
00705 xAxis->setAxisLabel( DateLabel );
00706 else
00707 xAxis->setAxisLabel( TimeLabel );
00708
00709
00710
00711 if( SearchType == SEARCHINCLIENTSLOGS )
00712 {
00713 setTitle( "Connected Clients" );
00714 setAxisTitle( xBottom, "Time" );
00715 setAxisTitle( yLeft, "Clients" );
00716 Curve->setStyle( QwtPlotCurve::Steps );
00717 }
00718 else
00719 {
00720 setTitle( "Storage Send Rate" );
00721 setAxisTitle( xBottom, "Time" );
00722 setAxisTitle( yLeft, "Send Rate (Mbits/s)" );
00723 Curve->setStyle( QwtPlotCurve::Lines );
00724 }
00725
00726 Curve->attach(this);
00727
00728 replot();
00729
00730 return true;
00731
00732 }
00733 }
00734
00735 bool LogPlot::SaveLogsData( const char *DataFileName )
00736 {
00737 ofstream DataFile( DataFileName );
00738 for( unsigned int i = 0 ; i < Points.size(); i++ )
00739 DataFile << ( unsigned int ) Points.x( i ) << " "
00740 << ( unsigned int ) Points.y( i ) << endl;
00741 DataFile.close();
00742 return true;
00743 }
00744
00745
00746 MonitorWindow::MonitorWindow( QWidget *parent, RioQt *rioQt,
00747 int UpdateInterval )
00748 : QMainWindow( parent, "MonitorWindow", 0 )
00749 {
00750
00751
00752
00753
00754
00755
00756
00757
00758 this->rioQt = rioQt;
00759 timer = new QTimer( this );
00760
00761 QSplitter *splitter = new QSplitter( Qt::Horizontal, this );
00762 splitter->setChildrenCollapsible( false );
00763 setCentralWidget( splitter );
00764
00765 QScrollView *scroll = new QScrollView( splitter );
00766 scroll->setResizePolicy( QScrollView::AutoOneFit );
00767
00768 splitter->setResizeMode( scroll, QSplitter::KeepSize );
00769 splitter->setMargin( 0 );
00770
00771
00772 data_bg = new QButtonGroup( 12, Qt::Vertical, "Data", scroll->viewport() );
00773 scroll->addChild( data_bg );
00774
00775 QGroupBox *rt_box = new QGroupBox( 0, Qt::Vertical,
00776 "Real time data", data_bg );
00777 rt_box->setFlat( true );
00778 rt_box->setInsideMargin(0);
00779 rt_box->setAlignment( Qt::AlignHCenter );
00780
00781 new QRadioButton( "Client List", data_bg );
00782 new QRadioButton( "Storage Queues", data_bg );
00783
00784 QHBox *update_box = new QHBox( data_bg );
00785 new QLabel( "Refresh period (ms): ", update_box );
00786 refresh_period_sb = new QSpinBox( 500, 60000, 1, update_box );
00787 refresh_period_sb->setValue( UpdateInterval );
00788 refresh_period_sb->setEnabled( false );
00789
00790 connect( refresh_period_sb, SIGNAL(valueChanged(int)),
00791 this, SLOT(setUpdateInterval(int)));
00792
00793 new QLabel( "", data_bg );
00794
00795 QGroupBox *hst_box = new QGroupBox( 0, Qt::Vertical,
00796 "Historical data", data_bg );
00797 hst_box->setFlat( true );
00798 hst_box->setInsideMargin(0);
00799 hst_box->setAlignment( Qt::AlignHCenter );
00800 new QRadioButton( "Connected Clients", data_bg );
00801 new QRadioButton( "Storage Send Rate", data_bg );
00802
00803
00804 storages_address = new QComboBox( data_bg );
00805 storages_address->setEnabled( false );
00806
00807 QHBox *start_box = new QHBox( data_bg );
00808 new QLabel( "Start time: ", start_box );
00809 history_start_date_time = new QDateTimeEdit( QDateTime::currentDateTime(),
00810 start_box );
00811 history_start_date_time->setEnabled( false );
00812
00813 QHBox *end_box = new QHBox( data_bg );
00814 new QLabel( "End time: ", end_box );
00815 history_end_date_time = new QDateTimeEdit( QDateTime::currentDateTime(),
00816 end_box );
00817 history_end_date_time->setEnabled( false );
00818
00819 QHBox *gen_box = new QHBox( data_bg );
00820 gen_box->layout()->addItem( new QSpacerItem( 0, 0, QSizePolicy::Maximum,
00821 QSizePolicy::Maximum ) );
00822 gen_button = new QPushButton( "Generate", gen_box );
00823 gen_button->setFixedSize( gen_button->sizeHint() );
00824 gen_button->setEnabled( false );
00825
00826 save_button = new QPushButton( "Save", gen_box );
00827 save_button->setFixedSize( save_button->sizeHint() );
00828 gen_box->layout()->addItem( new QSpacerItem( 0, 0, QSizePolicy::Maximum,
00829 QSizePolicy::Maximum ) );
00830 save_button->setEnabled( false );
00831
00832 connect( gen_button, SIGNAL(clicked()), this, SLOT(generateStats()));
00833 connect( save_button, SIGNAL(clicked()), this, SLOT(saveGraph()));
00834
00835 connect( data_bg, SIGNAL(clicked(int)),
00836 this, SLOT(buttonSelected(int)));
00837
00838
00839 results_widgets = new QWidgetStack( splitter );
00840 splitter->setResizeMode( results_widgets, QSplitter::FollowSizeHint );
00841
00842 generate_msg = new QLabel(
00843 "For real time data, choose your option.\n\
00844 For historical data, choose your option and a date range and click\
00845 \"Generate\".",
00846 results_widgets );
00847 generate_msg->setAlignment( Qt::AlignCenter );
00848 results_widgets->addWidget( generate_msg );
00849
00850 client_table = new ClientTable( results_widgets );
00851 results_widgets->addWidget( client_table );
00852 storage_table = new StorageTable( results_widgets );
00853 results_widgets->addWidget( storage_table );
00854 data_plot = new LogPlot( results_widgets );
00855 results_widgets->addWidget( data_plot );
00856
00857 results_widgets->raiseWidget( generate_msg );
00858
00859
00860 m_UsedHistoricData = false;
00861 }
00862
00863 void MonitorWindow::buttonSelected( int id )
00864 {
00865 if( data_bg->selectedId() < 2 )
00866 {
00867 refresh_period_sb->setEnabled( true );
00868 history_start_date_time->setEnabled( false );
00869 history_end_date_time->setEnabled( false );
00870 storages_address->setEnabled( false );
00871 save_button->setEnabled( false );
00872 gen_button->setEnabled( false );
00873 generateStats();
00874 }
00875 else
00876 {
00877 bool showLastGraph;
00878 refresh_period_sb->setEnabled( false );
00879 history_start_date_time->setEnabled( true );
00880 history_end_date_time->setEnabled( true );
00881 gen_button->setEnabled( true );
00882 if( data_bg->selectedId() == 3 )
00883 {
00884 storages_address->setEnabled( true );
00885 showLastGraph = m_UsedHistoricData &&
00886 ( m_LastSearchType == SEARCHINTRAFFICLOGS );
00887 }
00888 else
00889 {
00890 storages_address->setEnabled( false );
00891 showLastGraph = m_UsedHistoricData &&
00892 ( m_LastSearchType == SEARCHINCLIENTSLOGS );
00893 }
00894 if( showLastGraph )
00895 {
00896 save_button->setEnabled( true );
00897 results_widgets->raiseWidget( data_plot );
00898 }
00899 else
00900 {
00901 save_button->setEnabled( false );
00902 results_widgets->raiseWidget( generate_msg );
00903 }
00904 generate_msg->setText( QString( "For real time data, choose your \
00905 option.\nFor historical data, choose your option and a date range and click\
00906 \"Generate\"." ) );
00907 }
00908 }
00909
00910 void MonitorWindow::closeEvent( QCloseEvent *closeEvent )
00911 {
00912 WindowClosedEvent *event = new WindowClosedEvent( this );
00913 QApplication::postEvent( rioQt, event );
00914 closeEvent->accept();
00915 }
00916
00917 void MonitorWindow::generateStats()
00918 {
00919 unsigned int SearchType;
00920 time_t StartTime, EndTime;
00921
00922 switch( data_bg->selectedId() )
00923 {
00924 case 0:
00925 setUpdateInterval( refresh_period_sb->value() );
00926 results_widgets->raiseWidget( client_table );
00927 refresh();
00928 return;
00929 case 1:
00930 setUpdateInterval( refresh_period_sb->value() );
00931 results_widgets->raiseWidget( storage_table );
00932 refresh();
00933 return;
00934 case 2:
00935 case 3:
00936
00937 StartTime = history_start_date_time->dateTime().toTime_t();
00938 EndTime = history_end_date_time->dateTime().toTime_t();
00939
00940 m_UsedHistoricData = false;
00941
00942 if( StartTime <= EndTime )
00943 {
00944 if( data_bg->selectedId() == 2 )
00945
00946 SearchType = SEARCHINCLIENTSLOGS;
00947 else
00948 SearchType = SEARCHINTRAFFICLOGS;
00949 generate_msg->setText( QString( "Getting Logs. Please wait! "
00950 ) );
00951 results_widgets->raiseWidget( generate_msg );
00952 setEnabled( false );
00953
00954 QApplication::setOverrideCursor( QCursor( Qt::WaitCursor ) );
00955 if( ExecuteSearch( SearchType, StartTime, EndTime ) )
00956 return;
00957 else
00958 {
00959 generate_msg->setText( QString( "Error when starting the\
00960 search in logs " ) );
00961 setEnabled( true );
00962
00963 QApplication::restoreOverrideCursor();
00964 return;
00965 }
00966 }
00967 else
00968 {
00969 QString message;
00970 message = "O Tempo inicial " +
00971 history_start_date_time->dateTime().toString() +
00972 " (" + QString::number( StartTime ) +
00973 ") e maior do que o tempo final " +
00974 history_end_date_time->dateTime().toString() + " (" +
00975 QString::number( EndTime ) + ")";
00976 showMessage( ERROR_MSG, message );
00977
00978 }
00979 default:
00980 break;
00981 }
00982 generate_msg->setText( QString( "For real time data, choose your option.\n\
00983 For historical data, choose your option and a date range and click\
00984 \"Generate\"." ) );
00985 results_widgets->raiseWidget( generate_msg );
00986 }
00987
00988 void MonitorWindow::saveGraph()
00989 {
00990 switch( QMessageBox::question( this, "Save graph",
00991 "In which format would you like to save the graph?",
00992 "Text (.log)", "Image (.jpg)" ) )
00993 {
00994 case -1:
00995 {
00996 return;
00997 }
00998 case 0:
00999 {
01000 QString log_file = QFileDialog::getSaveFileName(
01001 "/home/" + QString( getenv( "USER" ) ),
01002 "Text log files (*.log)" );
01003 if( log_file == QString::null )
01004 return;
01005 if( !log_file.endsWith( ".log" ) )
01006 log_file += ".log";
01007
01008 data_plot->SaveLogsData( log_file.latin1() );
01009 return;
01010 }
01011 case 1:
01012 {
01013 QString file = QFileDialog::getSaveFileName(
01014 "/home/" + QString( getenv( "USER" ) ),
01015 "JPEG image files (*.jpg)" );
01016 if( file == QString::null )
01017 return;
01018 if( !file.endsWith( ".jpg" ) )
01019 file += ".jpg";
01020
01021 QPixmap *temp_pixmap = new QPixmap( data_plot->size() );
01022 temp_pixmap->fill( data_plot->backgroundColor() );
01023 data_plot->print( *temp_pixmap );
01024 temp_pixmap->save( file,
01025 "JPEG" );
01026 delete temp_pixmap;
01027 return;
01028 }
01029 }
01030 }
01031
01032 ClientTable *MonitorWindow::getClientTable()
01033 {
01034 return client_table;
01035 }
01036
01037 StorageTable *MonitorWindow::getStorageTable()
01038 {
01039 return storage_table;
01040 }
01041
01042 void MonitorWindow::setUpdateInterval( int UpdateInterval )
01043 {
01044 timer->changeInterval( UpdateInterval );
01045 refresh();
01046 }
01047
01048 bool MonitorWindow::showMessage( int type, string message, string title )
01049 {
01050 bool status = true;
01051 ShowMessageEvent * event;
01052 if( title == "" )
01053 event = new ShowMessageEvent( type, message );
01054 else
01055 event = new ShowMessageEvent( type, message, title );
01056 if( type == RioExplorer::QUESTION_MSG )
01057 {
01058 QApplication::sendEvent( rioQt, event );
01059 if( event->getResult() == QMessageBox::No )
01060 status = false;
01061 delete event;
01062 }
01063 else
01064 QApplication::postEvent( rioQt, event );
01065
01066 return status;
01067 }
01068
01069 void MonitorWindow::updateCopyProgress( void )
01070 {
01071 }
01072
01073 void MonitorWindow::setMD5Calculation( char *object, bool finished )
01074 {
01075 }
01076
01077 void MonitorWindow::setSyncCheck( char *object, bool finished )
01078 {
01079 }
01080
01081 bool MonitorWindow::connectRioServer( char *hostName, char *user, char *passwd )
01082 {
01083 bool status = true;
01084 string message;
01085
01086 userName = user;
01087 session = createSession( hostName, user, passwd );
01088
01089 if( session != NULL )
01090 {
01091 if( !getBlockSize( &blockSize, session ) )
01092 {
01093 message = "Erro ao tentar obter tamanho de bloco da sessão RIO ";
01094 message += hostName;
01095 message += ".\n";
01096 showMessage( ERROR_MSG, message );
01097 status = false;
01098 }
01099
01100
01101
01102 session->GetServerAddress( &m_ServerAddress, &m_ServerAddressSize );
01103
01104
01105
01106
01107 for( unsigned int i = 1; i < m_ServerAddressSize; i++ )
01108 storages_address->insertItem( QString( inet_ntoa(
01109 m_ServerAddress[ i ].sin_addr ) ) );
01110
01111 host = session->GetServerName();
01112 setCaption( QString( user ) + "@" + host );
01113
01114 connect( timer, SIGNAL(timeout()), this, SLOT(refresh()));
01115
01116 if( refresh() )
01117 timer->start( refresh_period_sb->value() );
01118 else
01119 status = false;
01120 }
01121 else
01122 status = false;
01123
01124 return status;
01125 }
01126
01127 bool MonitorWindow::refresh()
01128 {
01129 if( ( results_widgets->visibleWidget() != client_table ) &&
01130 ( results_widgets->visibleWidget() != storage_table ) )
01131 return true;
01132 vector<ClientData> client_data;
01133 vector<StorageData> storage_data;
01134 char *user = strdup( userName.latin1() );
01135 if( !( getMonitorTable( session, user, &client_data, &storage_data ) ) )
01136 {
01137 string message;
01138 message = "Erro ao tentar obter tabelas de monitoramento da ";
01139 message += "sessão RIO ";
01140 message += host;
01141 message += ".\n";
01142 if( timer->isActive() )
01143 {
01144 message += "A sessão será paralisada.\n";
01145 timer->stop();
01146 }
01147 showMessage( ERROR_MSG, message );
01148 free( user );
01149 return false;
01150 }
01151 else
01152 {
01153 client_table->setTable( client_data );
01154 storage_table->setTable( storage_data );
01155 free( user );
01156 return true;
01157 }
01158 }
01159
01160
01161 bool MonitorWindow::ExecuteSearch( unsigned int SearchType, time_t StartTime,
01162 time_t EndTime )
01163 {
01164
01165 MonitorLogsData *LogsData;
01166
01167 unsigned int Server;
01168
01169 RioResult Result;
01170
01171
01172 LogsData = new MonitorLogsData;
01173 if( LogsData == NULL )
01174 {
01175 string message;
01176 message = "Erro de alocacao de memoria ao executar a busca ";
01177 showMessage( ERROR_MSG, message );
01178 return false;
01179 }
01180
01181
01182 LogsData->Monitor = this;
01183 LogsData->SearchType = SearchType;
01184 LogsData->ResultFileName = new char[ MaxPathSize ];
01185 if( LogsData->ResultFileName == NULL )
01186 {
01187 string message;
01188 message = "Erro de alocacao de memoria ao executar a busca ";
01189 showMessage( ERROR_MSG, message );
01190 delete LogsData;
01191 return false;
01192 }
01193
01194 if( SearchType == SEARCHINTRAFFICLOGS )
01195 strcpy( LogsData->ResultFileName, "StorageSendRate-XXXXXXXXXX" );
01196 else
01197 strcpy( LogsData->ResultFileName, "ConnectedClients-XXXXXXXXXX" );
01198 if( !RIOmktemp( LogsData->ResultFileName ) )
01199 {
01200 string message;
01201 message = "Erro ao criar um arquivo temporario ao executar a busca";
01202 showMessage( ERROR_MSG, message );
01203 delete LogsData;
01204 delete[] LogsData->ResultFileName;
01205 return false;
01206 }
01207 strcat( LogsData->ResultFileName, ".gz" );
01208
01209
01210 if( SearchType == SEARCHINCLIENTSLOGS )
01211 Server = 0;
01212 else
01213 Server = 1 + storages_address->currentItem();
01214 Result = session->SearchLogs( SearchType, StartTime, EndTime,
01215 m_ServerAddress[ Server ].sin_addr.s_addr,
01216 m_ServerAddress[ Server ].sin_port,
01217 LogsData->ResultFileName,
01218 &ExecuteSearchCallback, ( void * ) LogsData );
01219
01220 if( FAILED( Result ) )
01221 {
01222 string message;
01223 message = "Erro ao executar solicitacao de busca";
01224 showMessage( ERROR_MSG, message );
01225 delete LogsData;
01226 delete[] LogsData->ResultFileName;
01227 return false;
01228 }
01229
01230 return true;
01231 }
01232
01233
01234
01235 void MonitorWindow::ExecuteSearchCallback( void *callbackparm, int result )
01236 {
01237
01238
01239 MonitorLogsData *LogsData;
01240
01241 SearchLogsEvent *event;
01242
01243 LogsData = ( MonitorLogsData* ) callbackparm;
01244
01245
01246
01247 event = new SearchLogsEvent( LogsData->Monitor, LogsData->ResultFileName,
01248 LogsData->SearchType, result );
01249
01250 QApplication::postEvent( LogsData->Monitor->rioQt, event );
01251
01252
01253
01254
01255 delete LogsData;
01256 }
01257
01258
01259 void MonitorWindow::processSearchLogsEvent( SearchLogsEvent *event )
01260 {
01261
01262
01263
01264
01265 switch( event->getSearchResult() )
01266 {
01267 case SEARCHLOGSFAILED:
01268
01269 generate_msg->setText( QString( "No logs in selected time interval"
01270 ) );
01271 break;
01272 case SEARCHLOGSSUCESS:
01273
01274
01275
01276 unsigned int SearchType, Server;
01277 char *ResultFileName;
01278 SearchType = event->getSearchType();
01279 ResultFileName = event->getResultFileName();
01280
01281
01282 if( SearchType == SEARCHINCLIENTSLOGS )
01283 Server = 0;
01284 else
01285 Server = 1 + storages_address->currentItem();
01286
01287 if( !data_plot->ProcessSearchLogs( ResultFileName, SearchType,
01288 QString( inet_ntoa(
01289 m_ServerAddress[ Server ].sin_addr
01290 ) ) ) )
01291 {
01292 #ifdef RIO_DEBUG2
01293 RioErr << "MonitorWindow::processSearchLogsEvent erro ao gerar "
01294 << " o grafico do arquivo " << ResultFileName
01295 << " usando o tipo " << SearchType << endl;
01296 #endif
01297 string message;
01298 message = "Erro ao gerar o grafico";
01299 showMessage( ERROR_MSG, message );
01300 }
01301 else
01302 {
01303
01304 save_button->setEnabled( true );
01305
01306 m_UsedHistoricData = true;
01307
01308 m_LastSearchType = SearchType;
01309
01310 results_widgets->raiseWidget( data_plot );
01311 }
01312
01313 remove( ResultFileName );
01314 break;
01315 case SEARCHLOGSERROR:
01316
01317
01318 generate_msg->setText( QString( "Error search request failed" ) );
01319 break;
01320 default:
01321
01322
01323
01324 generate_msg->setText( QString( "Error invalid error code" ) );
01325 break;
01326 }
01327
01328 setEnabled( true );
01329
01330 QApplication::restoreOverrideCursor();
01331 }