2014-09-23 15:04:57 +02:00
/////////////////////////////////////////////////////////////////////////////////
2012-05-18 09:45:23 +02:00
//
2014-09-23 15:04:57 +02:00
// Copyright (C) 2011- Statoil ASA
// Copyright (C) 2013- Ceetron Solutions AS
// Copyright (C) 2011-2012 Ceetron AS
2012-05-18 09:45:23 +02:00
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
2013-05-06 10:55:00 +02:00
# include "RiaSocketServer.h"
2013-05-22 09:18:57 +02:00
# include "RiaSocketCommand.h"
2013-10-08 14:21:18 +02:00
# include "RiaSocketTools.h"
2012-05-18 09:45:23 +02:00
2013-03-22 16:24:42 +01:00
# include "RiaApplication.h"
2013-05-06 10:55:00 +02:00
2016-01-06 23:01:27 +01:00
# include "RigCaseCellResultsData.h"
# include "RigCaseData.h"
# include "RigGridBase.h"
# include "Rim3dOverlayInfoConfig.h"
# include "RimCaseCollection.h"
2015-06-25 13:45:32 +02:00
# include "RimCellEdgeColors.h"
2013-05-26 21:55:05 +02:00
# include "RimCellRangeFilterCollection.h"
2016-01-06 23:01:27 +01:00
# include "RimEclipseCase.h"
# include "RimEclipseCaseCollection.h"
# include "RimEclipseCellColors.h"
2015-06-25 13:05:28 +02:00
# include "RimEclipsePropertyFilterCollection.h"
2016-01-06 23:01:27 +01:00
# include "RimEclipseView.h"
2015-06-25 13:36:15 +02:00
# include "RimEclipseWellCollection.h"
2013-05-26 21:55:05 +02:00
# include "RimIdenticalGridCaseGroup.h"
2016-01-06 23:01:27 +01:00
# include "RimOilField.h"
# include "RimProject.h"
2014-07-24 14:03:17 +02:00
# include "RimReservoirCellResultsStorage.h"
2016-01-06 23:01:27 +01:00
# include "RimScriptCollection.h"
2013-05-26 21:55:05 +02:00
2016-01-06 23:01:27 +01:00
# include "RiuMainWindow.h"
# include "RiuViewer.h"
2013-05-06 10:55:00 +02:00
2013-05-16 11:15:34 +02:00
# include "cafFactory.h"
2016-01-06 23:01:27 +01:00
# include <QtGui>
# include <QtNetwork>
# include <stdlib.h>
2013-05-16 11:15:34 +02:00
2012-05-18 09:45:23 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaSocketServer : : RiaSocketServer ( QObject * parent )
: QObject ( parent ) ,
m_tcpServer ( NULL ) ,
m_currentClient ( NULL ) ,
m_currentCommandSize ( 0 ) ,
2013-05-26 21:55:05 +02:00
m_currentCommand ( NULL ) ,
m_currentCaseId ( - 1 )
2012-05-18 09:45:23 +02:00
{
2013-03-22 17:17:56 +01:00
m_errorMessageDialog = new QErrorMessage ( RiuMainWindow : : instance ( ) ) ;
2012-05-18 09:45:23 +02:00
// TCP server setup
m_tcpServer = new QTcpServer ( this ) ;
2013-10-08 14:21:18 +02:00
m_nextPendingConnectionTimer = new QTimer ( this ) ;
m_nextPendingConnectionTimer - > setInterval ( 100 ) ;
m_nextPendingConnectionTimer - > setSingleShot ( true ) ;
2012-05-18 09:45:23 +02:00
if ( ! m_tcpServer - > listen ( QHostAddress : : LocalHost , 40001 ) )
{
m_errorMessageDialog - > showMessage ( " Octave communication disabled : \n "
" \n "
2013-04-16 12:08:45 +02:00
" This instance of ResInsight could not start the Socket Server enabling octave to get and set data. \n "
2012-05-18 09:45:23 +02:00
" This is probably because you already have a running ResInsight process. \n "
" Octave can only communicate with one ResInsight process at a time, so the Octave \n "
" communication in this ResInsight instance will be disabled. \n "
" \n "
+ tr ( " The error from the socket system is: %1. " ) . arg ( m_tcpServer - > errorString ( ) ) ) ;
return ;
}
2014-09-08 15:39:23 +02:00
connect ( m_nextPendingConnectionTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( slotNewClientConnection ( ) ) ) ;
2012-10-15 15:13:41 +02:00
connect ( m_tcpServer , SIGNAL ( newConnection ( ) ) , this , SLOT ( slotNewClientConnection ( ) ) ) ;
2012-05-18 09:45:23 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaSocketServer : : ~ RiaSocketServer ( )
{
2013-05-16 11:15:34 +02:00
assert ( m_currentCommand = = NULL ) ;
2012-05-18 09:45:23 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
unsigned short RiaSocketServer : : serverPort ( )
{
if ( m_tcpServer ) return m_tcpServer - > serverPort ( ) ;
else return 0 ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2012-10-15 15:13:41 +02:00
void RiaSocketServer : : slotNewClientConnection ( )
2012-05-18 09:45:23 +02:00
{
2013-10-04 14:29:11 +02:00
// If we are currently handling a connection, just ignore the new one until the current one is disconnected.
2012-05-18 09:45:23 +02:00
2014-09-08 15:39:23 +02:00
if ( m_currentClient & & ( m_currentClient - > state ( ) ! = QAbstractSocket : : UnconnectedState ) )
2012-10-15 15:13:41 +02:00
{
2013-10-08 14:21:18 +02:00
//PMonLog("Starting Timer");
m_nextPendingConnectionTimer - > start ( ) ; // Reset and start again
2013-10-04 14:29:11 +02:00
return ;
2012-10-15 15:13:41 +02:00
}
2013-10-04 14:29:11 +02:00
// Read pending data from socket
2012-05-18 09:45:23 +02:00
2013-10-04 14:29:11 +02:00
if ( m_currentClient & & m_currentCommand )
2012-05-18 09:45:23 +02:00
{
2013-10-04 14:29:11 +02:00
bool isFinshed = m_currentCommand - > interpretMore ( this , m_currentClient ) ;
if ( ! isFinshed )
{
m_errorMessageDialog - > showMessage ( tr ( " ResInsight SocketServer: \n " ) + tr ( " Warning : The command did not finish up correctly at the presence of a new one. " ) ) ;
}
2012-05-18 09:45:23 +02:00
}
2013-10-04 14:29:11 +02:00
handleNextPendingConnection ( ) ;
2012-05-18 09:45:23 +02:00
}
//--------------------------------------------------------------------------------------------------
2013-05-15 14:37:03 +02:00
/// Find the requested reservoir by caseId
2012-05-18 09:45:23 +02:00
//--------------------------------------------------------------------------------------------------
2015-05-15 08:40:27 +02:00
RimEclipseCase * RiaSocketServer : : findReservoir ( int caseId )
2012-05-18 09:45:23 +02:00
{
2013-09-27 16:25:40 +02:00
int currCaseId = caseId ;
2013-05-15 14:37:03 +02:00
if ( caseId < 0 )
2013-09-27 16:25:40 +02:00
{
currCaseId = this - > currentCaseId ( ) ;
}
if ( currCaseId < 0 )
2012-05-18 09:45:23 +02:00
{
2015-05-21 10:05:33 +02:00
RimEclipseView * riv = dynamic_cast < RimEclipseView * > ( RiaApplication : : instance ( ) - > activeReservoirView ( ) ) ;
2015-05-08 14:13:26 +02:00
if ( riv )
2012-05-18 09:45:23 +02:00
{
2015-05-08 14:13:26 +02:00
return riv - > eclipseCase ( ) ;
2012-05-18 09:45:23 +02:00
}
2016-01-06 23:01:27 +01:00
// If the active mdi window is different from an Eclipse view, search through available mdi windows to find the last activated
// Eclipse view. The sub windows are returned with the most recent activated window at the back.
QList < QMdiSubWindow * > subWindows = RiuMainWindow : : instance ( ) - > subWindowList ( QMdiArea : : ActivationHistoryOrder ) ;
for ( int i = subWindows . size ( ) - 1 ; i > - 1 ; i - - )
{
RiuViewer * viewer = subWindows [ i ] - > widget ( ) - > findChild < RiuViewer * > ( ) ;
if ( viewer )
{
RimEclipseView * riv = dynamic_cast < RimEclipseView * > ( viewer - > ownerReservoirView ( ) ) ;
if ( riv )
{
return riv - > eclipseCase ( ) ;
}
}
}
2012-05-18 09:45:23 +02:00
}
else
{
2013-03-22 15:50:44 +01:00
RimProject * project = RiaApplication : : instance ( ) - > project ( ) ;
2012-05-18 09:45:23 +02:00
if ( ! project ) return NULL ;
2015-05-15 18:51:49 +02:00
std : : vector < RimCase * > cases ;
2013-05-15 14:37:03 +02:00
project - > allCases ( cases ) ;
for ( size_t i = 0 ; i < cases . size ( ) ; i + + )
{
2013-09-27 17:06:20 +02:00
if ( cases [ i ] - > caseId = = currCaseId )
2013-05-15 14:37:03 +02:00
{
2015-05-15 18:51:49 +02:00
return dynamic_cast < RimEclipseCase * > ( cases [ i ] ) ;
2013-05-15 14:37:03 +02:00
}
}
2012-05-18 09:45:23 +02:00
}
return NULL ;
}
//--------------------------------------------------------------------------------------------------
2013-10-04 14:29:11 +02:00
/// Reads the command name size, the command string and creates a new command object based on the string read.
/// Tries to interpret the command as well.
/// Returns whether the command actually was completely finished in one go.
2012-05-18 09:45:23 +02:00
//--------------------------------------------------------------------------------------------------
2013-10-04 14:29:11 +02:00
bool RiaSocketServer : : readCommandFromOctave ( )
2012-05-18 09:45:23 +02:00
{
QDataStream socketStream ( m_currentClient ) ;
2013-05-22 09:18:57 +02:00
socketStream . setVersion ( riOctavePlugin : : qtDataStreamVersion ) ;
2012-05-18 09:45:23 +02:00
// If we have not read the currentCommandSize
// read the size of the command if all the data is available
2013-10-04 14:29:11 +02:00
2012-05-18 09:45:23 +02:00
if ( m_currentCommandSize = = 0 )
{
2013-10-04 14:29:11 +02:00
if ( m_currentClient - > bytesAvailable ( ) < ( int ) sizeof ( qint64 ) ) return false ;
2012-05-18 09:45:23 +02:00
socketStream > > m_currentCommandSize ;
}
// Check if the complete command is available, return and whait for readyRead() if not
2013-10-04 14:29:11 +02:00
if ( m_currentClient - > bytesAvailable ( ) < m_currentCommandSize ) return false ;
2012-05-18 09:45:23 +02:00
2013-10-04 14:29:11 +02:00
// Now we can read the command name
2012-05-18 09:45:23 +02:00
QByteArray command = m_currentClient - > read ( m_currentCommandSize ) ;
QTextStream commandStream ( command ) ;
QList < QByteArray > args ;
while ( ! commandStream . atEnd ( ) )
{
QByteArray arg ;
commandStream > > arg ;
args . push_back ( arg ) ;
}
CVF_ASSERT ( args . size ( ) > 0 ) ;
2013-10-04 14:29:11 +02:00
// Create the actual RiaSocketCommand object that will interpret the socket data
2013-05-16 11:15:34 +02:00
m_currentCommand = RiaSocketCommandFactory : : instance ( ) - > create ( args [ 0 ] ) ;
2013-05-24 11:36:59 +02:00
2013-05-16 11:15:34 +02:00
if ( m_currentCommand )
{
bool finished = m_currentCommand - > interpretCommand ( this , args , socketStream ) ;
2013-10-04 14:29:11 +02:00
return finished ;
2013-05-16 11:15:34 +02:00
}
else
{
2012-05-18 09:45:23 +02:00
m_errorMessageDialog - > showMessage ( tr ( " ResInsight SocketServer: \n " ) + tr ( " Unknown command: %1 " ) . arg ( args [ 0 ] . data ( ) ) ) ;
2013-10-04 14:29:11 +02:00
return true ;
2012-05-18 09:45:23 +02:00
}
}
2012-06-26 16:10:41 +02:00
2012-05-18 09:45:23 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaSocketServer : : slotCurrentClientDisconnected ( )
{
2013-05-24 11:36:59 +02:00
if ( m_currentCommand )
{
2013-10-04 14:29:11 +02:00
// Make sure we read what can be read.
bool isFinished = m_currentCommand - > interpretMore ( this , m_currentClient ) ;
if ( ! isFinished )
2013-05-24 11:36:59 +02:00
{
2013-10-04 14:29:11 +02:00
m_errorMessageDialog - > showMessage ( tr ( " ResInsight SocketServer: \n " ) + tr ( " Warning : The command was interrupted and did not finish because the connection to octave disconnected. " ) ) ;
2013-05-24 11:36:59 +02:00
}
}
2013-10-04 14:29:11 +02:00
handleNextPendingConnection ( ) ;
2012-10-15 15:13:41 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaSocketServer : : slotReadyRead ( )
{
2013-05-24 11:36:59 +02:00
if ( m_currentCommand )
{
2013-10-04 14:29:11 +02:00
bool isFinished = m_currentCommand - > interpretMore ( this , m_currentClient ) ;
2013-05-29 10:07:35 +02:00
2013-10-04 14:29:11 +02:00
if ( isFinished )
{
handleNextPendingConnection ( ) ;
2013-05-24 11:36:59 +02:00
}
}
else
{
2013-10-04 14:29:11 +02:00
bool isFinished = readCommandFromOctave ( ) ;
if ( isFinished )
{
handleNextPendingConnection ( ) ;
}
2013-05-24 11:36:59 +02:00
}
2012-05-18 09:45:23 +02:00
}
2012-10-19 10:05:55 +02:00
2013-05-26 21:55:05 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaSocketServer : : setCurrentCaseId ( int caseId )
{
m_currentCaseId = caseId ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RiaSocketServer : : currentCaseId ( ) const
{
return m_currentCaseId ;
}
2013-10-04 14:29:11 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaSocketServer : : terminateCurrentConnection ( )
{
if ( m_currentClient )
{
m_currentClient - > disconnect ( SIGNAL ( disconnected ( ) ) ) ;
m_currentClient - > disconnect ( SIGNAL ( readyRead ( ) ) ) ;
m_currentClient - > deleteLater ( ) ;
m_currentClient = NULL ;
}
// Clean up more state:
if ( m_currentCommand )
{
delete m_currentCommand ;
m_currentCommand = NULL ;
}
m_currentCommandSize = 0 ;
}
2013-05-29 10:07:35 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2013-10-04 14:29:11 +02:00
void RiaSocketServer : : handleNextPendingConnection ( )
2013-05-29 10:07:35 +02:00
{
2014-09-08 15:39:23 +02:00
if ( m_currentClient & & ( m_currentClient - > state ( ) ! = QAbstractSocket : : UnconnectedState ) )
2013-05-29 10:07:35 +02:00
{
2013-10-08 14:21:18 +02:00
//PMonLog("Starting Timer");
m_nextPendingConnectionTimer - > start ( ) ; // Reset and start again
2013-10-04 14:29:11 +02:00
return ;
}
2013-10-08 14:21:18 +02:00
// Stop timer
if ( m_nextPendingConnectionTimer - > isActive ( ) )
{
//PMonLog("Stopping Timer");
m_nextPendingConnectionTimer - > stop ( ) ;
}
2013-10-04 14:29:11 +02:00
terminateCurrentConnection ( ) ;
QTcpSocket * clientToHandle = m_tcpServer - > nextPendingConnection ( ) ;
if ( clientToHandle )
{
CVF_ASSERT ( m_currentClient = = NULL ) ;
CVF_ASSERT ( m_currentCommand = = NULL ) ;
2013-05-29 10:07:35 +02:00
2013-10-04 14:29:11 +02:00
m_currentClient = clientToHandle ;
m_currentCommandSize = 0 ;
connect ( m_currentClient , SIGNAL ( disconnected ( ) ) , this , SLOT ( slotCurrentClientDisconnected ( ) ) ) ;
connect ( m_currentClient , SIGNAL ( readyRead ( ) ) , this , SLOT ( slotReadyRead ( ) ) ) ;
if ( m_currentClient - > bytesAvailable ( ) )
{
bool isFinished = this - > readCommandFromOctave ( ) ;
if ( isFinished )
{
// Call ourselves recursively until there are none left, or until it can not be processed in one go.
this - > handleNextPendingConnection ( ) ;
}
}
2013-05-29 10:07:35 +02:00
}
}