diff --git a/script/script.sh b/script/script.sh new file mode 100755 index 0000000000000000000000000000000000000000..02b14738e36cfdb1fd1a3b7fae70ab166e865ac2 --- /dev/null +++ b/script/script.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +#----------------------------------------------------------------------- +# User parameters +#----------------------------------------------------------------------- +#Verify tool path +VERIFY_TOOL="/home/mdm/workspace/nexecs/test/tools/fitsverify" +CHECK_STRING="conform to the FITS format" + +NO_FILE_ERROR="failed to find or open the following file" + +FATAL_ERROR="Fatal" + +EOF_ERROR="End-of-file" + +#----------------------------------------------------------------------- +# Verify script +#----------------------------------------------------------------------- +if [ "$1" == "CHECK" ]; then + res=$($VERIFY_TOOL 2>&1) + check=$(echo $res | grep "$CHECK_STRING" | wc | awk '{print $1}') + if [ "$check" -ge "1" ]; then + echo "CHECK OK" + else + echo "NOT OK" + fi + exit 0 +else + #Check regular expression -> fatal + file=$1 + file_name=${file##*/} + if [[ ! "${file_name,,}" =~ ^[^\.].*\.(fits|fts).*$ ]]; then + echo "FATAL" + exit 0 + fi + + #if fits verify tools exists -> fatal + if [ ! -x $VERIFY_TOOL ]; then + echo "FATAL" + exit 0 + fi + + #if fits file not exists -> fatal + if [ ! -f $1 ]; then + echo "FATAL" + exit 0 + fi + + #Check with fits verify + res=$($VERIFY_TOOL $1 2>&1) + + #if fitsverify return fatal error -> wait + fatal=$(echo $res | grep "$FATAL_ERROR" | wc | awk '{print $1}') + if [ "$fatal" -ge "1" ]; then + echo "WAIT" + exit 0 + fi + + #if fitsverify return end of file -> wait + eof=$(echo $res | grep "$EOF_ERROR" | wc | awk '{print $1}') + if [ "$eof" -ge "1" ]; then + echo "WAIT" + exit 0 + fi + + #else -> ok + echo "OK" + exit 0 +fi +#----------------------------------------------------------------------- diff --git a/src/Configuration.h b/src/Configuration.h index 50574f95ec3e400bd5598d4300b3a9e749bd8508..5d70bba447a50be947d873465049eaa5ed66d750 100644 --- a/src/Configuration.h +++ b/src/Configuration.h @@ -52,7 +52,7 @@ public: return c_sp; } - + std::string getWatchPath() const { return m_watchPath; } std::string getDestPath() const { return m_destPath; } std::string getScriptPath() const { return m_scriptPath; } diff --git a/src/EventThread.cpp b/src/EventThread.cpp index 85efd95dd17206fa27bcccafeeb64563e95c251f..ab737498ec63b377c06283636026088aa2ebce50 100644 --- a/src/EventThread.cpp +++ b/src/EventThread.cpp @@ -16,9 +16,9 @@ namespace PreProcessor_ns //============================================================================== // EventThread::EventThread() //============================================================================== -EventThread::EventThread(Tango::DeviceImpl* deviceImpl_p, - Configuration::SP configuration_sp) : Tango::LogAdapter(deviceImpl_p), - m_configuration_sp(configuration_sp) +EventThread::EventThread(PreProcessor* preProcessor_p, + Configuration::SP configuration_sp) : Tango::LogAdapter(preProcessor_p), + m_preProcessor_p(preProcessor_p), m_configuration_sp(configuration_sp) { DEBUG_STREAM << "EventThread::EventThread()" << endl; @@ -44,10 +44,10 @@ EventThread::~EventThread() //============================================================================== // EventThread::create() //============================================================================== -EventThread::SP EventThread::create(Tango::DeviceImpl* deviceImpl_p, +EventThread::SP EventThread::create(PreProcessor* preProcessor_p, Configuration::SP configuration_sp) { - EventThread::SP e_sp(new EventThread(deviceImpl_p, configuration_sp), + EventThread::SP e_sp(new EventThread(preProcessor_p, configuration_sp), EventThread::Deleter()); return e_sp; @@ -62,7 +62,11 @@ void EventThread::start() try { + initEventBuffer(); + initINotify(); + + initThreadGroup(); } catch(std::exception& ex) { @@ -145,6 +149,101 @@ void EventThread::writeStatus(std::string status) m_status = status; } +//============================================================================== +// EventThread::initEventBuffer() +//============================================================================== +void EventThread::initEventBuffer() throw(std::runtime_error) +{ + DEBUG_STREAM << "EventThread::initEventBuffer()" << endl; + + m_eventBuffer_sp = EventBuffer::create(m_preProcessor_p); + + std::string watchPath(m_configuration_sp->getWatchPath()); + + boost::filesystem::path path(watchPath); + + //Check if watch path exists + if(!boost::filesystem::exists(path)) + throw std::runtime_error("Watch path \"" + + watchPath + "\" does not exist"); + + //And if it's a directory + if(!boost::filesystem::is_directory(path)) + throw std::runtime_error("Watch path \"" + + watchPath + "\" is not a valid directory"); + + //All files in watch path are inserted into event buffer + boost::filesystem::directory_iterator startIt(path); + boost::filesystem::directory_iterator endIt; + + while(startIt != endIt) + { + if(boost::filesystem::is_regular_file(startIt->status())) + m_eventBuffer_sp->insertNew(startIt->path()); + + startIt++; + } +} + +//============================================================================== +// EventThread::initINotify() +//============================================================================== +void EventThread::initINotify() throw(std::runtime_error) +{ + DEBUG_STREAM << "EventThread::initINotify()" << endl; + + if((m_fileDescriptor = inotify_init ()) < 0) + throw std::runtime_error("INotify initialization error"); + + std::string watchPath(m_configuration_sp->getWatchPath()); + + uint32_t iNotifyMask = m_configuration_sp->getINotifyMask(); + + if((m_watchDescriptor = inotify_add_watch( + m_fileDescriptor, watchPath.c_str(), iNotifyMask)) < 0) + throw std::runtime_error("INotify add watch error"); + + int flags; + if((flags = fcntl(m_fileDescriptor,F_GETFL,0)) < 0) + throw std::runtime_error("File descriptor get flags error"); + + if(fcntl(m_fileDescriptor, F_SETFL, flags | O_NONBLOCK) < 0) + throw std::runtime_error("File descriptor set flags error"); +} + +//============================================================================== +// EventThread::initThreadGroup() +//============================================================================== +void EventThread::initThreadGroup() throw(std::runtime_error) +{ + DEBUG_STREAM << "EventThread::initThreadGroup()" << endl; + + m_threadGroup_sp.reset(new boost::thread_group); + + unsigned int workerNumber = m_configuration_sp->getWorkerNumber(); + + //Create a worker thread and pass all arguments + WorkerThread worker(m_preProcessor_p, m_eventBuffer_sp, m_configuration_sp); + + try + { + //Add to thread group event thread + m_threadGroup_sp->add_thread( + new boost::thread(&EventThread::eventLoop, this)); + + //Add to thread group worker threads + for(unsigned int i=0; i<workerNumber; i++) + m_threadGroup_sp->add_thread( + new boost::thread(&WorkerThread::workerLoop, worker)); + } + catch(boost::thread_resource_error& ex) + { + std::stringstream error_stream; + error_stream << "InitThreadGroup: " << ex.what(); + throw std::runtime_error(error_stream.str()); + } +} + //============================================================================== // EventThread::eventLoop() //============================================================================== diff --git a/src/EventThread.h b/src/EventThread.h index 5f8772fb6832b8db9272b12cea6badffba905a2a..90e248f9d6715b7d34dd156ae5e4b0d326ee8eab 100644 --- a/src/EventThread.h +++ b/src/EventThread.h @@ -15,7 +15,7 @@ namespace PreProcessor_ns { -class FitsImporter; +class PreProcessor; class EventThread : public Tango::LogAdapter { @@ -29,7 +29,7 @@ protected: //------------------------------------------------------------------------------ // [Protected] Constructor destructor deleter //------------------------------------------------------------------------------ - EventThread(Tango::DeviceImpl*, Configuration::SP); + EventThread(PreProcessor*, Configuration::SP); virtual ~EventThread(); @@ -45,7 +45,7 @@ public: //------------------------------------------------------------------------------ // [Public] Class creation method //------------------------------------------------------------------------------ - static EventThread::SP create(Tango::DeviceImpl*, Configuration::SP); + static EventThread::SP create(PreProcessor*, Configuration::SP); //------------------------------------------------------------------------------ // [Public] Thread management methods @@ -72,13 +72,19 @@ protected: //------------------------------------------------------------------------------ // [Protected] Utilities methods //------------------------------------------------------------------------------ + virtual void initEventBuffer() throw(std::runtime_error); + + virtual void initINotify() throw(std::runtime_error); + + virtual void initThreadGroup() throw(std::runtime_error); + virtual void eventLoop(); //------------------------------------------------------------------------------ // [Protected] Class variables //------------------------------------------------------------------------------ //Tango server class pointer - FitsImporter* m_fitsImporter_p; + PreProcessor* m_preProcessor_p; //Boost thread group shared pointer boost::scoped_ptr<boost::thread_group> m_threadGroup_sp; diff --git a/src/PreProcessor.cpp b/src/PreProcessor.cpp index e39c73f264cfc9cac154a4ae2845803eed8edee8..e7776cba571c6d3a2fe0c21723c28add7fde3891 100644 --- a/src/PreProcessor.cpp +++ b/src/PreProcessor.cpp @@ -153,11 +153,11 @@ void PreProcessor::init_device() m_eventThread_sp = EventThread::create(this, m_configuration_sp); //Start device if auto start enabled -// if(autoStart) -// { -// INFO_STREAM << "FitsImporter::init_device() auto start enabled " << endl; -// on(); -// } + if(autoStart) + { + INFO_STREAM << "FitsImporter::init_device() auto start enabled " << endl; + on(); + } } catch(std::exception& ex) { @@ -199,6 +199,7 @@ void PreProcessor::get_device_property() dev_prop.push_back(Tango::DbDatum("SleepTime")); dev_prop.push_back(Tango::DbDatum("WaitTime")); dev_prop.push_back(Tango::DbDatum("WorkerNumber")); + dev_prop.push_back(Tango::DbDatum("AutoStart")); // is there at least one property to be read ? if (dev_prop.size()>0) @@ -289,6 +290,18 @@ void PreProcessor::get_device_property() } // And try to extract WorkerNumber value from database if (dev_prop[i].is_empty()==false) dev_prop[i] >> workerNumber; + + // Try to initialize AutoStart from class property + cl_prop = ds_class->get_class_property(dev_prop[++i].name); + if (cl_prop.is_empty()==false) cl_prop >> autoStart; + else { + // Try to initialize AutoStart from default device value + def_prop = ds_class->get_default_device_property(dev_prop[i].name); + if (def_prop.is_empty()==false) def_prop >> autoStart; + } + // And try to extract AutoStart value from database + if (dev_prop[i].is_empty()==false) dev_prop[i] >> autoStart; + } /*----- PROTECTED REGION ID(PreProcessor::get_device_property_after) ENABLED START -----*/ diff --git a/src/PreProcessor.h b/src/PreProcessor.h index 233e5ba5edd62c2859b1ef6ee570c178bf63d4bd..941591a08fa03cf6005365e99fb6e3dda9080e1c 100644 --- a/src/PreProcessor.h +++ b/src/PreProcessor.h @@ -103,6 +103,8 @@ public: Tango::DevUShort waitTime; // WorkerNumber: Tango::DevUShort workerNumber; + // AutoStart: Exec On command after init if state is not fault + Tango::DevBoolean autoStart; // Constructors and destructors diff --git a/src/PreProcessor.xmi b/src/PreProcessor.xmi index 4cf344d1972ad4c4e4274f3edbe7213fbea0828e..4aaa2b33bb9e524b201b1070a233488b37442112 100644 --- a/src/PreProcessor.xmi +++ b/src/PreProcessor.xmi @@ -33,6 +33,11 @@ <type xsi:type="pogoDsl:UShortType"/> <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> </deviceProperties> + <deviceProperties name="AutoStart" description="Exec On command after init if state is not fault"> + <type xsi:type="pogoDsl:BooleanType"/> + <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> + <DefaultPropValue>false</DefaultPropValue> + </deviceProperties> <commands name="State" description="This command gets the device state (stored in its device_state data member) and returns it to the caller." execMethod="dev_state" displayLevel="OPERATOR" polledPeriod="0"> <argin description="none"> <type xsi:type="pogoDsl:VoidType"/> @@ -59,6 +64,9 @@ <type xsi:type="pogoDsl:VoidType"/> </argout> <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> + <excludedStates>ON</excludedStates> + <excludedStates>FAULT</excludedStates> + <excludedStates>ALARM</excludedStates> </commands> <commands name="Off" description="" execMethod="off" displayLevel="OPERATOR" polledPeriod="0"> <argin description=""> @@ -68,6 +76,9 @@ <type xsi:type="pogoDsl:VoidType"/> </argout> <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> + <excludedStates>OFF</excludedStates> + <excludedStates>FAULT</excludedStates> + <excludedStates>ALARM</excludedStates> </commands> <states name="ON" description=""> <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> @@ -75,6 +86,12 @@ <states name="OFF" description=""> <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> </states> + <states name="FAULT" description="Pre processor is in FAULT state (not ready to process data)"> + <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> + </states> + <states name="ALARM" description="Pre processor is in ALARM state (not ready to process data)"> + <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> + </states> <preferences docHome="./doc_html" makefileHome="/usr/local/tango-8.1.2/share/pogo/preferences"/> </classes> </pogoDsl:PogoSystem> diff --git a/src/PreProcessorClass.cpp b/src/PreProcessorClass.cpp index 50bde920f49e03ccaa302868fbca0f452349bded..03f838c9ae8a02f38234d75588da9ff54c2b5ab2 100644 --- a/src/PreProcessorClass.cpp +++ b/src/PreProcessorClass.cpp @@ -353,6 +353,20 @@ void PreProcessorClass::set_default_property() } else add_wiz_dev_prop(prop_name, prop_desc); + prop_name = "AutoStart"; + prop_desc = "Exec On command after init if state is not fault"; + prop_def = "false"; + vect_data.clear(); + vect_data.push_back("false"); + if (prop_def.length()>0) + { + Tango::DbDatum data(prop_name); + data << vect_data ; + dev_def_prop.push_back(data); + add_wiz_dev_prop(prop_name, prop_desc, prop_def); + } + else + add_wiz_dev_prop(prop_name, prop_desc); } //-------------------------------------------------------- diff --git a/src/PreProcessorClass.h b/src/PreProcessorClass.h index 85f629770bec0c8fd6c65b5b63a50ca6d0903ff7..128c6517c04af105ce5e60fc4c70309ea3784cdd 100644 --- a/src/PreProcessorClass.h +++ b/src/PreProcessorClass.h @@ -6,26 +6,26 @@ // description : Include for the PreProcessor root class. // This class is the singleton class for // the PreProcessor device class. -// It contains all properties and methods which the +// It contains all properties and methods which the // PreProcessor requires only once e.g. the commands. // // project : PreProcessor // // This file is part of Tango device class. -// +// // Tango 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. -// +// // Tango 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 for more details. -// +// // You should have received a copy of the GNU General Public License // along with Tango. If not, see <http://www.gnu.org/licenses/>. -// +// // $Author: $ // // $Revision: $ @@ -76,7 +76,7 @@ public: Tango::CmdArgType out) :Command(name,in,out) {}; ~OnClass() {}; - + virtual CORBA::Any *execute (Tango::DeviceImpl *dev, const CORBA::Any &any); virtual bool is_allowed (Tango::DeviceImpl *dev, const CORBA::Any &any) {return (static_cast<PreProcessor *>(dev))->is_On_allowed(any);} @@ -99,7 +99,7 @@ public: Tango::CmdArgType out) :Command(name,in,out) {}; ~OffClass() {}; - + virtual CORBA::Any *execute (Tango::DeviceImpl *dev, const CORBA::Any &any); virtual bool is_allowed (Tango::DeviceImpl *dev, const CORBA::Any &any) {return (static_cast<PreProcessor *>(dev))->is_Off_allowed(any);} @@ -117,8 +117,8 @@ class PreProcessorClass : public Tango::DeviceClass #endif { /*----- PROTECTED REGION ID(PreProcessorClass::Additionnal DServer data members) ENABLED START -----*/ - - + + /*----- PROTECTED REGION END -----*/ // PreProcessorClass::Additionnal DServer data members public: @@ -126,7 +126,7 @@ class PreProcessorClass : public Tango::DeviceClass Tango::DbData cl_prop; Tango::DbData cl_def_prop; Tango::DbData dev_def_prop; - + // Method prototypes static PreProcessorClass *init(const char *); static PreProcessorClass *instance(); @@ -134,7 +134,7 @@ class PreProcessorClass : public Tango::DeviceClass Tango::DbDatum get_class_property(string &); Tango::DbDatum get_default_device_property(string &); Tango::DbDatum get_default_class_property(string &); - + protected: PreProcessorClass(string &); static PreProcessorClass *_instance; @@ -145,7 +145,7 @@ class PreProcessorClass : public Tango::DeviceClass void get_class_property(); string get_cvstag(); string get_cvsroot(); - + private: void device_factory(const Tango::DevVarStringArray *); void create_static_attribute_list(vector<Tango::Attr *> &); diff --git a/src/PreProcessorStateMachine.cpp b/src/PreProcessorStateMachine.cpp index efaab5936b692450c6370f4add7b39a7460e5d75..f22a5e79bdcb917feccdf990d224db6c89df9e17 100644 --- a/src/PreProcessorStateMachine.cpp +++ b/src/PreProcessorStateMachine.cpp @@ -43,6 +43,8 @@ //================================================================ // ON | // OFF | +// FAULT | Pre processor is in FAULT state (not ready to process data) +// ALARM | Pre processor is in ALARM state (not ready to process data) namespace PreProcessor_ns @@ -63,10 +65,16 @@ namespace PreProcessor_ns //-------------------------------------------------------- bool PreProcessor::is_On_allowed(TANGO_UNUSED(const CORBA::Any &any)) { - // Not any excluded states for On command. + // Compare device state with not allowed states. + if (get_state()==Tango::ON || + get_state()==Tango::FAULT || + get_state()==Tango::ALARM) + { /*----- PROTECTED REGION ID(PreProcessor::OnStateAllowed) ENABLED START -----*/ /*----- PROTECTED REGION END -----*/ // PreProcessor::OnStateAllowed + return false; + } return true; } @@ -78,10 +86,16 @@ bool PreProcessor::is_On_allowed(TANGO_UNUSED(const CORBA::Any &any)) //-------------------------------------------------------- bool PreProcessor::is_Off_allowed(TANGO_UNUSED(const CORBA::Any &any)) { - // Not any excluded states for Off command. + // Compare device state with not allowed states. + if (get_state()==Tango::OFF || + get_state()==Tango::FAULT || + get_state()==Tango::ALARM) + { /*----- PROTECTED REGION ID(PreProcessor::OffStateAllowed) ENABLED START -----*/ /*----- PROTECTED REGION END -----*/ // PreProcessor::OffStateAllowed + return false; + } return true; } diff --git a/src/WorkerThread.cpp b/src/WorkerThread.cpp index 47a9e7b7616c7e2ef59c802d133697149b2d7ca7..34c42abdf64f223b697440152c66a467dae0890f 100644 --- a/src/WorkerThread.cpp +++ b/src/WorkerThread.cpp @@ -1,4 +1,5 @@ #include <WorkerThread.h> +#include <PreProcessor.h> #include <cassert> #include <fstream> @@ -18,8 +19,10 @@ namespace PreProcessor_ns //============================================================================== // WorkerThread::WorkerThread() //============================================================================== -WorkerThread::WorkerThread(Tango::DeviceImpl* deviceImpl_p, - EventBuffer::SP eventBuffer_sp) : Tango::LogAdapter(deviceImpl_p) +WorkerThread::WorkerThread(PreProcessor* preProcessor_p, + EventBuffer::SP eventBuffer_sp, Configuration::SP configuration_sp) : + Tango::LogAdapter(preProcessor_p), m_preProcessor_p(preProcessor_p), + m_eventBuffer_sp(eventBuffer_sp), m_configuration_sp(configuration_sp) { DEBUG_STREAM << "WorkerThread::WorkerThread()" << std::endl; } @@ -39,8 +42,8 @@ void WorkerThread::workerLoop() { DEBUG_STREAM << "WorkerThread::workerLoop(): starting loop" << endl; - unsigned int waitTime = m_configuration_sp->getWaitTime(); - std::string watchPath = m_configuration_sp->getWatchPath(); +// unsigned int waitTime = m_configuration_sp->getWaitTime(); +// std::string watchPath = m_configuration_sp->getWatchPath(); // while(true) // { diff --git a/src/WorkerThread.h b/src/WorkerThread.h index 10df7800d4ae4cfb2ca727728d870de016d9c9e8..77d7328cabdb752f7df330c02c12f4831554ffb5 100644 --- a/src/WorkerThread.h +++ b/src/WorkerThread.h @@ -14,13 +14,15 @@ namespace PreProcessor_ns { +class PreProcessor; + class WorkerThread : public Tango::LogAdapter { public: //------------------------------------------------------------------------------ // [Public] Constructor destructor //------------------------------------------------------------------------------ - WorkerThread(Tango::DeviceImpl*, EventBuffer::SP); + WorkerThread(PreProcessor*, EventBuffer::SP, Configuration::SP); virtual ~WorkerThread(); @@ -37,6 +39,9 @@ protected: //------------------------------------------------------------------------------ // [Protected] Class variables //------------------------------------------------------------------------------ + //Tango server class pointer + PreProcessor* m_preProcessor_p; + //Event buffer shared pointer EventBuffer::SP m_eventBuffer_sp;