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-03-22 16:12:00 +01:00
#include "RiaStdInclude.h"
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
#include <QtGui>
#include <QtNetwork>
#include <stdlib.h>
2013-03-22 16:24:42 +01:00
#include "RiaApplication.h"
2013-03-22 17:30:50 +01:00
#include "RiuMainWindow.h"
2013-05-06 10:55:00 +02:00
#include "RimReservoirView.h"
#include "RimProject.h"
2013-05-24 12:02:52 +02:00
#include "RimCase.h"
2013-05-06 10:55:00 +02:00
2013-05-26 21:55:05 +02:00
#include "RimResultSlot.h"
#include "RimCellEdgeResultSlot.h"
#include "RimCellRangeFilterCollection.h"
#include "RimCellPropertyFilterCollection.h"
#include "RimWellCollection.h"
#include "Rim3dOverlayInfoConfig.h"
#include "RimIdenticalGridCaseGroup.h"
#include "RimScriptCollection.h"
#include "RimCaseCollection.h"
#include "RimWellPathCollection.h"
2014-07-24 14:03:17 +02:00
#include "RimReservoirCellResultsStorage.h"
2013-05-26 21:55:05 +02:00
2013-05-06 10:55:00 +02:00
#include "RigCaseData.h"
#include "RigCaseCellResultsData.h"
2013-05-16 11:15:34 +02:00
#include "cafFactory.h"
2013-05-21 21:03:05 +02:00
#include "RigGridBase.h"
2013-06-06 15:02:35 +02:00
#include "RimOilField.h"
#include "RimAnalysisModels.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
//--------------------------------------------------------------------------------------------------
2013-05-15 14:37:03 +02:00
RimCase * 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
{
2013-03-22 15:50:44 +01:00
if ( RiaApplication :: instance () -> activeReservoirView ())
2012-05-18 09:45:23 +02:00
{
2013-03-22 15:50:44 +01:00
return RiaApplication :: instance () -> activeReservoirView () -> 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 ;
2013-05-15 14:37:03 +02:00
std :: vector < RimCase *> cases ;
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
{
return cases [ i ];
}
}
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
}
}