summaryrefslogtreecommitdiff
path: root/cesar/maximus/system/src/Station.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cesar/maximus/system/src/Station.cpp')
-rw-r--r--cesar/maximus/system/src/Station.cpp555
1 files changed, 555 insertions, 0 deletions
diff --git a/cesar/maximus/system/src/Station.cpp b/cesar/maximus/system/src/Station.cpp
new file mode 100644
index 0000000000..91792630f1
--- /dev/null
+++ b/cesar/maximus/system/src/Station.cpp
@@ -0,0 +1,555 @@
+/************************************************************************
+ Station.cpp - Copyright buret
+
+Here you can write a license for your code, some comments or any other
+information you want to have in your generated code. To to this simply
+configure the "headings" directory in uml to point to a directory
+where you have your heading files.
+
+or you can just replace the contents of this file with your own.
+If you want to do this, this file is located at
+
+/usr/share/apps/umbrello/headings/heading.cpp
+
+-->Code Generators searches for heading files based on the file extension
+ i.e. it will look for a file name ending in ".h" to include in C++ header
+ files, and for a file name ending in ".java" to include in all generated
+ java code.
+ If you name the file "heading.<extension>", Code Generator will always
+ choose this file even if there are other files with the same extension in the
+ directory. If you name the file something else, it must be the only one with that
+ extension in the directory to guarantee that Code Generator will choose it.
+
+you can use variables in your heading files which are replaced at generation
+time. possible variables are : author, date, time, filename and filepath.
+just write %variable_name%
+
+This file was generated on %date% at %time%
+The original location of this file is /home/buret/eclipse/maximus/system/src/Station.cpp
+**************************************************************************/
+
+#include "Station.h"
+
+#include "StationConfiguration.h"
+
+#include "Error.h"
+#include "Logger.h"
+
+#include "host/socket.h" // for 'STATION_SOCK'
+
+#include <sys/types.h> // for 'waitpid()'
+#include <sys/wait.h> // for 'waitpid()'
+#include <fcntl.h>
+#include <unistd.h> // for 'exec()' and 'system()'
+#include <sys/signal.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <iomanip> // for 'setfill()' and 'setw()'
+using namespace std;
+
+extern bool UNITTEST;
+extern string stationTest;
+
+
+// Constructors/Destructors
+//
+
+
+Station::Station ( const string & station_executable, const Network_Clock_Tick current_tick_value ):
+mInputFileDescriptor(-1),
+mOutputFileDescriptor(-1),
+mLogPipe(-1),
+mPid(0),
+mStationStatus(MAXIMUS_STATION_STATUS_NONE),
+mStationIdleCounter(1), // once a station has been launched, Maximus has to wait for a system IDLE message
+mpStationConfiguration(NULL)
+{
+ logFunction();
+ string stationExecutable = station_executable;
+
+ if (UNITTEST)
+ {
+ stationExecutable = stationTest;
+ }
+
+ mpStationConfiguration = new StationConfiguration (stationExecutable);
+ if (NULL == mpStationConfiguration)
+ {
+ throw Error(__PRETTY_FUNCTION__ , "Station configuration pointer is NULL");
+ }
+
+ initAttributes();
+
+ startProcess(current_tick_value);
+}
+
+
+void Station::initAttributes ( )
+{
+ logFunction();
+}
+
+
+Station::~Station ( )
+{
+ logFunction();
+ clog << logger(LOG_COM) << "delete station " \
+ << getStationId() << " (0x" << setfill('0') << setw(4) << uppercase << hex << getStationId() << ")" << dec << endl;
+
+ stopProcess();
+ if (NULL != mpStationConfiguration)
+ {
+ delete (mpStationConfiguration);
+ mpStationConfiguration = NULL;
+ }
+}
+
+
+//
+// Methods
+//
+
+
+// Other methods
+//
+
+
+// public methods
+//
+
+
+bool Station::operator== ( const Station & station ) const
+{
+ logFunction();
+ bool bOperator = false;
+
+ if ( (getStationStatus() == station.getStationStatus())
+ && (getStationConfiguration() == station.getStationConfiguration())
+ && (getInputFileDescriptor() == station.getInputFileDescriptor())
+ && (getOutputFileDescriptor() == station.getOutputFileDescriptor())
+ && (getLogFileDescriptor() == station.getLogFileDescriptor())
+ && (getStationId() == station.getStationId()) )
+ {
+ bOperator = true;
+ }
+
+ return bOperator;
+}
+
+
+Station & Station::operator= ( const Station & station )
+{
+ logFunction();
+
+ if ( (!setInputFileDescriptor (station.getInputFileDescriptor()))
+ || (!setOutputFileDescriptor (station.getOutputFileDescriptor()))
+ || (!setLogFileDescriptor (station.getLogFileDescriptor()))
+ || (!setStationStatus (station.getStationStatus()))
+ || (!setStationConfiguration (station.getStationConfiguration())) )
+ {
+ throw Error(__PRETTY_FUNCTION__ , "Error when setting attributes");
+ }
+
+ return *this;
+}
+
+
+void Station::displayStation ( ) const
+{
+ logFunction();
+
+ clog << logger(LOG_INFO) << "\t[input file descriptor = " << dec << getInputFileDescriptor() \
+ << ", output file descriptor = " << getOutputFileDescriptor() \
+ << ", log file descriptor = " << getLogFileDescriptor() \
+ << ", process id = " << getStationId() << " (0x" << setfill('0') << setw(4) << uppercase << hex << getStationId() << ")" \
+ << ", executable = " << getStationConfiguration()->getStationExecutable() \
+ << ", name = " << getStationConfiguration()->getStationName() << "]" << dec << endl;
+}
+
+
+bool Station::launchDebugger ( const string & command_line ) const
+{
+ logFunction();
+ bool bLaunch = false;
+
+ string commandLine(command_line);
+ size_t found = 0;
+
+ do
+ {
+ found = commandLine.find("%n", found, 2);
+ if (string::npos != found)
+ {
+ commandLine.replace(found, 2, getStationConfiguration()->getStationName());
+ }
+ }
+ while (found != string::npos);
+
+ found = 0;
+ do
+ {
+ found = commandLine.find("%e", found, 2);
+ if (string::npos != found)
+ {
+ commandLine.replace(found, 2, getStationConfiguration()->getStationExecutable());
+ }
+ }
+ while (found != string::npos);
+
+ found = 0;
+ do
+ {
+ found = commandLine.find("%p", found, 2);
+ if (string::npos != found)
+ {
+ char processId[6];
+ sprintf(processId, "%d", getPid());
+ commandLine.replace(found, 2, processId);
+ }
+ }
+ while (found != string::npos);
+
+ clog << logger(LOG_INFO) << "debugger command line = " << commandLine << endl;
+
+ system(commandLine.c_str());
+
+ return bLaunch;
+}
+
+
+// Accessor methods
+//
+
+
+// public attribute accessor methods
+//
+
+
+// private attribute accessor methods
+//
+
+
+const Sci_Msg_Station_Id Station::getStationId ( ) const
+{
+ return static_cast<Sci_Msg_Station_Id>(mPid);
+}
+
+
+const pid_t Station::getPid ( ) const
+{
+ return mPid;
+}
+
+
+bool Station::setInputFileDescriptor ( const File_Descriptor input_file_descriptor )
+{
+ mInputFileDescriptor = input_file_descriptor;
+
+ return true;
+}
+
+
+bool Station::setOutputFileDescriptor ( const File_Descriptor output_file_descriptor )
+{
+ mOutputFileDescriptor = output_file_descriptor;
+
+ return true;
+}
+
+
+bool Station::setLogFileDescriptor ( const File_Descriptor log_file_descriptor )
+{
+ mLogPipe = log_file_descriptor;
+
+ return true;
+}
+
+
+const File_Descriptor Station::getInputFileDescriptor ( ) const
+{
+ return mInputFileDescriptor;
+}
+
+
+const File_Descriptor Station::getOutputFileDescriptor ( ) const
+{
+ return mOutputFileDescriptor;
+}
+
+
+const File_Descriptor Station::getLogFileDescriptor ( ) const
+{
+ return mLogPipe;
+}
+
+
+Station_Status Station::getStationStatus ( ) const
+{
+ return mStationStatus;
+}
+
+
+bool Station::setStationStatus ( const Station_Status status )
+{
+ mStationStatus = status;
+
+ return true;
+}
+
+
+const unsigned short int Station::getStationIdleCounter ( ) const
+{
+ return mStationIdleCounter;
+}
+
+
+bool Station::incrementStationIdleCounter ( )
+{
+ mStationIdleCounter++;
+
+ return true;
+}
+
+
+bool Station::decrementStationIdleCounter ( )
+{
+ logFunction();
+ bool bDecrement = false;
+
+ if (0 < mStationIdleCounter)
+ {
+ mStationIdleCounter--;
+ bDecrement = true;
+ }
+ else
+ {
+ clog << logger(LOG_WARNING) << "station with id " << dec << getStationId() \
+ << " (0x" << setfill('0') << setw(4) << uppercase << hex << getStationId() \
+ << ") is already IDLE" << dec << endl;
+ }
+
+ return bDecrement;
+}
+
+
+bool Station::setStationConfiguration ( StationConfiguration * p_station_configuration )
+{
+ logFunction();
+ bool bSetConfig = false;
+
+ if (NULL != p_station_configuration)
+ {
+ mpStationConfiguration = p_station_configuration;
+ bSetConfig = true;
+ }
+ else
+ {
+ errno = EINVAL;
+ throw Error(__PRETTY_FUNCTION__ , "Station configuration pointer is NULL", errno);
+ }
+
+ return bSetConfig;
+}
+
+
+StationConfiguration * Station::getStationConfiguration ( ) const
+{
+ if (NULL == mpStationConfiguration)
+ {
+ throw Error(__PRETTY_FUNCTION__ , "Station configuration pointer is NULL");
+ }
+
+ return mpStationConfiguration;
+}
+
+
+bool Station::setStationName ( const std::string & station_name )
+{
+ return getStationConfiguration()->setStationName(station_name);
+}
+
+
+// private methods
+//
+
+
+void Station::startProcess ( const Network_Clock_Tick current_tick_value )
+{
+ logFunction();
+
+ // Start the station process
+ //
+ if(getStationConfiguration()->getStationExecutable().empty())
+ {
+ throw Error(__PRETTY_FUNCTION__, "Executable not set", errno);
+ }
+ if(0 == (mPid = fork()))
+ {
+ char stationExecutable[getStationConfiguration()->getStationExecutable().size()+1];
+ size_t stringLength = getStationConfiguration()->getStationExecutable().copy(stationExecutable, getStationConfiguration()->getStationExecutable().size());
+ stationExecutable[stringLength] = '\0';
+
+ char currentTickValue[32];
+ sprintf(currentTickValue, "%llu", current_tick_value);
+
+ if (-1 == execlp(stationExecutable, stationExecutable, currentTickValue, NULL))
+ {
+ throw Error(__PRETTY_FUNCTION__, "Cannot launch station executable", errno);
+ }
+ exit(1);
+ }
+
+ // Loop until pipe creation: max = STATION_WAIT_LOOP_NB * STATION_WAIT_TIMEOUT_MS ms
+ //
+ int loop;
+ int fd_status;
+ char nameBuffer[256];
+
+ #ifdef STATION_SOCK
+
+ struct sockaddr_un sockaddr;
+ int bufsize = STATION_MAX_SOCK_BUFFER_SIZE;
+ sprintf(nameBuffer, "%s/%s_sock_%d", STATION_SOCK_PATH, STATION_SOCK_PREFIX, getPid());
+ // open the socket
+ if((mInputFileDescriptor = socket (PF_UNIX, SOCK_STREAM, 0)) < 0)
+ {
+ throw Error(__FUNCTION__ , "Cannot create socket", errno);
+ }
+
+ // avoid other stations to inherit the socket
+ fd_status = fcntl(mInputFileDescriptor, F_GETFD);
+ fcntl(mInputFileDescriptor, F_SETFD, fd_status | FD_CLOEXEC);
+
+ // extend send buffer size
+ if(setsockopt (mInputFileDescriptor, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize)) < 0)
+ {
+ throw Error(__FUNCTION__ , "Cannot increase buffer size", errno);
+ }
+ sockaddr.sun_family = AF_UNIX;
+ strcpy (sockaddr.sun_path, nameBuffer);
+
+ for(loop = 0; loop < STATION_WAIT_LOOP_NB; loop++)
+ {
+ // Connect to server
+ //
+ if((connect(mInputFileDescriptor, (struct sockaddr *)&sockaddr, sizeof(sockaddr))) >= 0)
+ {
+ break;
+ }
+ usleep(STATION_WAIT_TIMEOUT_MS * 1000);
+ }
+
+ if(loop >= STATION_WAIT_LOOP_NB)
+ {
+ stopProcess();
+ throw Error(__FUNCTION__ , "Cannot connect to station", errno);
+ }
+ else
+ {
+ setOutputFileDescriptor(mInputFileDescriptor);
+ }
+
+ #else /* !STATION_SOCK */
+
+ // Open input pipe
+ sprintf(nameBuffer, "%s/%s_out_%d", STATION_PIPE_PATH, STATION_PIPE_PREFIX, getPid());
+ for(loop = 0; loop < STATION_WAIT_LOOP_NB; loop++)
+ {
+ // Connect to server
+ //
+ if((mInputFileDescriptor = open(nameBuffer, O_RDONLY | O_NONBLOCK)) >= 0)
+ {
+ break;
+ }
+ usleep(STATION_WAIT_TIMEOUT_MS * 1000);
+ }
+ if(loop >= STATION_WAIT_LOOP_NB)
+ {
+ stopProcess();
+ throw Error(__FUNCTION__ , "Cannot connect to station", errno);
+ }
+
+ // avoid other stations to inherit the pipe
+ fd_status = fcntl(mInputFileDescriptor, F_GETFD);
+ fcntl(mInputFileDescriptor, F_SETFD, fd_status | FD_CLOEXEC);
+
+ // Open output pipe
+ sprintf(nameBuffer, "%s/%s_in_%d", STATION_PIPE_PATH, STATION_PIPE_PREFIX, getPid());
+ if((mOutputFileDescriptor = open(nameBuffer, O_WRONLY | O_NONBLOCK)) < 0)
+ {
+ stopProcess();
+ throw Error(__PRETTY_FUNCTION__, "Cannot open output pipe", errno);
+ }
+ // avoid other stations to inherit the pipe
+ fd_status = fcntl(mOutputFileDescriptor, F_GETFD);
+ fcntl(mOutputFileDescriptor, F_SETFD, fd_status | FD_CLOEXEC);
+
+ #endif /* STATION_SOCK */
+
+ // Open log pipe
+ //
+ sprintf(nameBuffer, "%s/%s_log_%d", STATION_PIPE_PATH, STATION_PIPE_PREFIX, getPid());
+ if((mLogPipe = open(nameBuffer, O_RDONLY | O_NONBLOCK)) < 0)
+ {
+ stopProcess();
+ throw Error(__PRETTY_FUNCTION__, "Cannot open log pipe", errno);
+ }
+
+ // avoid other stations to inherit the pipe
+ fd_status = fcntl(mLogPipe, F_GETFD);
+ fcntl(mLogPipe, F_SETFD, fd_status | FD_CLOEXEC);
+}
+
+
+void Station::stopProcess ( )
+{
+ logFunction();
+ if(mInputFileDescriptor >= 0)
+ {
+ close(mInputFileDescriptor);
+ }
+ if(mOutputFileDescriptor >= 0)
+ {
+ close(mOutputFileDescriptor);
+ }
+ if(mLogPipe >= 0)
+ {
+ close(mLogPipe);
+ }
+ if(mPid > 0)
+ {
+ kill(mPid, SIGTERM);
+ waitpid(mPid, NULL, 0);
+ }
+}
+
+
+void Station::displayStationStatus ( ) const
+{
+ logFunction();
+
+ switch (getStationStatus())
+ {
+ case 0:
+ clog << logger(LOG_INFO) << "MAXIMUS_STATION_STATUS_NONE" << endl;
+ break;
+ case 1:
+ clog << logger(LOG_INFO) << "MAXIMUS_STATION_STATUS_IDLE" << endl;
+ break;
+ case 2:
+ clog << logger(LOG_INFO) << "MAXIMUS_STATION_STATUS_BUSY" << endl;
+ break;
+ case 3:
+ clog << logger(LOG_INFO) << "MAXIMUS_STATION_STATUS_DEACTIVATED" << endl;
+ break;
+ default:
+ clog << logger(LOG_INFO) << "unknown!" << endl;
+ break;
+ }
+}
+
+
+// protected methods
+//
+