Commit 4a0791b7 authored by Pavel Vainerman's avatar Pavel Vainerman

Удалил лишние файлы после синхронизации (rebase + pathes) c uniset/2.0

parent 818ffc50
/* This file is part of the UniSet project
* Copyright (c) 2002 Free Software Foundation, Inc.
* Copyright (c) 2002 Pavel Vainerman
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// --------------------------------------------------------------------------
/*! \file
* \author Pavel Vainerman
* \date $Date: 2005/01/28 20:27:06 $
* \version $Id: UniSetObserver_i.idl,v 1.4 2005/01/28 20:27:06 vitlav Exp $
*/
// --------------------------------------------------------------------------
#ifndef UniSetObserver_i_IDL_
#define UniSetObserver_i_IDL_
// --------------------------------------------------------------------------------------------------------------
#include "../UniSetTypes/UniSetTypes_i.idl"
// --------------------------------------------------------------------------------------------------------------
/*!
* \interface UniSetObserver_i
* \brief шаблон "Наблюдатель"
*/
interface UniSetObserver_i
{
// исключения
exception NameNotFound
{
string err;
};
void attach( in UniSetTypes::ObjectId id, in UniSetTypes::ObjectId fromid ) raises(NameNotFound);
void detach( in UniSetTypes::ObjectId id, in UniSetTypes::ObjectId fromid ) raises(NameNotFound);
};
// --------------------------------------------------------------------------------------------------------------
#endif
\ No newline at end of file
/* This file is part of the UniSet project
* Copyright (c) 2002 Free Software Foundation, Inc.
* Copyright (c) 2002 Pavel Vainerman
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// --------------------------------------------------------------------------
/*! \file
* \author Pavel Vainerman
* \date $Date: 2005/11/01 21:44:53 $
* \version $Id: DBServer_i.idl,v 1.5 2005/11/01 21:44:53 vpashka Exp $
*/
// --------------------------------------------------------------------------
#ifndef DBServer_i_IDL_
#define DBServer_i_IDL_
// --------------------------------------------------------------------------
#include "../UniSetTypes/UniSetTypes_i.idl"
#include "../UniSetTypes/UniSetObject_i.idl"
// --------------------------------------------------------------------------
/*!
* \interface DBServer_i
* \brief Интерфейс сервера базы данных системы
*/
interface DBServer_i: UniSetObject_i
{
// исключения
exception DBError
{
string errmsg;
};
void query(in string query) raises(DBError);
string hostname();
string dbname();
};
#endif
\ No newline at end of file
/* This file is part of the UniSet project
* Copyright (c) 2002 Free Software Foundation, Inc.
* Copyright (c) 2002 Pavel Vainerman
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// --------------------------------------------------------------------------
/*! \file
* \author Pavel Vainerman
* \date $Date: 2005/01/28 20:27:06 $
* \version $Id: InfoServer_i.idl,v 1.4 2005/01/28 20:27:06 vitlav Exp $
*/
// --------------------------------------------------------------------------
#ifndef InfoServer_i_IDL_
#define InfoServer_i_IDL_
// --------------------------------------------------------------------------
#include "../UniSetTypes/UniSetTypes_i.idl"
#include "../UniSetTypes/UniSetObject_i.idl"
// --------------------------------------------------------------------------
/*!
* \interface InfoServer_i
* \brief Интерфейс к серверу сообщений
*/
interface InfoServer_i: UniSetObject_i
{
// исключения
exception MsgNotFound
{
UniSetTypes::MessageCode bad_code;
};
// исключения
exception MsgBadRange
{
};
/*! Заказ информации о приходе сообщения */
void ackMessage(in UniSetTypes::MessageCode mid, in UniSetTypes::ConsumerInfo ci,
in UniversalIO::UIOCommand cmd, in boolean acknotify ) raises(MsgNotFound);
/*! Заказ информации о приходе сообщений из диапазона */
void ackMessageRange(in UniSetTypes::MessageCode from, in UniSetTypes::MessageCode to,
in UniSetTypes::ConsumerInfo ci,
in UniversalIO::UIOCommand cmd, in boolean acknotify ) raises(MsgNotFound,MsgBadRange);
};
// --------------------------------------------------------------------------
#endif
############################################################################
# This file is part of the UniSet library #
############################################################################
# Каталоги для размещения генерируемых CC- и HH-файлов соответственно
CCDIR=$(top_builddir)/src/Services
HHDIR=$(top_builddir)/include
# Исходные файлы IDL
IDLFILES=TimerService_i.idl InfoServer_i.idl
include $(top_builddir)/conf/idl.mk
idl_include_HEADERS = *.idl
idl_includedir = $(datadir)/idl/@PACKAGE@/Services
/* This file is part of the UniSet project
* Copyright (c) 2002 Free Software Foundation, Inc.
* Copyright (c) 2002 Pavel Vainerman
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// --------------------------------------------------------------------------
/*! \file
* \author Pavel Vainerman
* \date $Date: 2005/01/28 20:27:06 $
* \version $Id: NetService_i.idl,v 1.4 2005/01/28 20:27:06 vitlav Exp $
*/
// --------------------------------------------------------------------------
#ifndef NetService_i_IDL_
#define BaseProcess_i_IDL_
// --------------------------------------------------------------------------
#include "../UniSetTypes/UniSetTypes_i.idl"
// --------------------------------------------------------------------------
/*!
* \interface NetService_i
*/
interface NetService_i
{
void registration( in BaseObjectName name, in Object ref );
void unregistration( in BaseObjectName name, in Object ref );
Object resolve(in BaseObjectName name);
Object resolveid( in BaseObjectId name);
};
#endif
\ No newline at end of file
/* This file is part of the UniSet project
* Copyright (c) 2002 Free Software Foundation, Inc.
* Copyright (c) 2002 Pavel Vainerman
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// --------------------------------------------------------------------------
/*! \file
* \author Pavel Vainerman
* \date $Date: 2005/11/01 21:44:53 $
* \version $Id: RepositoryAgent_i.idl,v 1.5 2005/11/01 21:44:53 vpashka Exp $
*/
// --------------------------------------------------------------------------
#ifndef RepositoryAgent_i_IDL_
#define RepositoryAgent_i_IDL_
// --------------------------------------------------------------------------
#include "../UniSetTypes/UniSetObject_i.idl"
// --------------------------------------------------------------------------------------------------------------
/*!
* \interface RepositoryAgent_i
* \brief Интерфейс агента репозитория
* Агент репозитрория предназначен для получения доступа к объектам с удаленных узлов.
* Он запускается на каждом узле, и с других узлов через него можно получить доступ
* к процессам, датчикам и т.п на данном узле.
*/
interface RepositoryAgent_i: UniSetObject_i
{
// исключения
exception NameNotFound
{
string errmsg;
};
exception ResolveError
{
string errmsg;
};
// void registration( in BaseObjectName name, in Object ref );
// void unregistration( in BaseObjectName name, in Object ref );
// Object resolve(in BaseObjectName name) raises(NameNotFound, ResolveError);
Object resolveid( in UniSetTypes::ObjectId name) raises(NameNotFound, ResolveError);
};
#endif
\ No newline at end of file
/* This file is part of the UniSet project
* Copyright (c) 2002 Free Software Foundation, Inc.
* Copyright (c) 2002 Pavel Vainerman
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// --------------------------------------------------------------------------
/*! \file
* \author Pavel Vainerman
* \date $Date: 2005/01/28 21:24:12 $
* \version $Id: TimerService_i.idl,v 1.1 2005/01/28 21:24:12 vitlav Exp $
*/
// --------------------------------------------------------------------------
#ifndef TimerService_i_IDL_
#define TimerService_i_IDL_
// --------------------------------------------------------------------------
#include "../UniSetTypes/UniSetTypes_i.idl"
#include "../UniSetTypes/UniSetObject_i.idl"
// --------------------------------------------------------------------------
/*!
* \interface TimerService_i
*/
interface TimerService_i: UniSetObject_i
{
/*! Превышения максимально возможного
* количества таймеров
*/
exception LimitTimers
{
long maxTimers;
};
/*! Таймер с таким id уже заказан
* (от данного заказчика)
*/
exception TimerAlreadyExist
{
};
/*! Задан интервал меньше
* минимально разрешённого
*/
exception TimeMSLowLimit
{
unsigned long lowLimitMS; // instead timeout_t
};
/*! Информация о таймере */
struct Timer
{
UniSetTypes::TimerId timerid;
unsigned long timeMS;
long ticks; // instead clock_t
short msgPriority;
};
/*! заказ таймера */
void askTimer( in Timer ti, in UniSetTypes::ConsumerInfo ci )
raises(LimitTimers, TimerAlreadyExist, TimeMSLowLimit);
// void setSysTime(...);
// void getSysTime(...);
};
#endif
\ No newline at end of file
/* This file is part of the UniSet project
* Copyright (c) 2002 Free Software Foundation, Inc.
* Copyright (c) 2002 Pavel Vainerman
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// --------------------------------------------------------------------------
/*! \file
* \author Pavel Vainerman
* \date $Date: 2007/12/18 20:24:11 $
* \version $Id: ObjectsManager_i.idl,v 1.2 2007/12/18 20:24:11 vpashka Exp $
*/
// --------------------------------------------------------------------------
#ifndef ObjectsManager_i_IDL_
#define ObjectsManager_i_IDL_
// ---------------------------------------------------------------------------
#include "UniSetObject_i.idl"
#include "UniSetTypes_i.idl"
// ---------------------------------------------------------------------------
//module UniSet
//{
/*!
* \interface ObjectsManager_i
* \brief Интерфейс менеджера объектов
* \author Pavel Vainerman
* \version
* \date September 2001-
*
* Базовый класс для менеджеров объектов. Позволяет посылать сообщение
* ко всем объектам сразу.
*/
interface ObjectsManager_i : UniSetObject_i
{
/*!< распространить сообщение всем подчиненным объектам */
void broadcast(in UniSetTypes::TransportMessage msg);
/*! получение информации о состоянии подчиненных объектов(менеджеров)
* \param MaxLength - ограничение размера возвращаемой
* последовательности структур SimpleInfo.
* \note Если у менеджера количество подчиненных объектов
* больше MaxLength, то он вернет информацию только
* о первых MaxLength объектах. Если <=, то количество
* равное количеству объектов.
* \note Возвращаемые данные содержат в себе инфо. о всех
* подчиненных объектах данного менеджера, а также объектах
* подчиненных данному менеджеру менеджерах и их объектах
* и т.п. и т.п. рекурсивно... Так что MaxLength должно быть
* достаточным.
* \todo Подумать насчет применения итератора, при слишком
* большом( >1000 ) количестве подчиненных объектов...
*/
UniSetTypes::SimpleInfoSeq getObjectsInfo( in long MaxLength );
};
//}; // end of module UniSet
#endif
// --------------------------------------------------------------------------------------------------------------
############################################################################
# This file is part of the UniSet library #
############################################################################
bin_PROGRAMS = uniset-infoserver
uniset_infoserver_SOURCES = main.cc
uniset_infoserver_LDADD = $(top_builddir)/lib/libUniSet.la
uniset_infoserver_CPPFLAGS = -I$(top_builddir)/lib $(SIGC_CFLAGS)
include $(top_builddir)/conf/setting.mk
#include "Configuration.h"
#include "InfoServer.h"
#include "ISRestorer.h"
#include "ObjectsActivator.h"
#include "Debug.h"
// --------------------------------------------------------------------------
using namespace UniSetTypes;
using namespace std;
// --------------------------------------------------------------------------
static void short_usage()
{
cout << "Usage: uniset-infoserver --name ObjectId [--askfile filename]"
<< " [--confile configure.xml]\n";
}
// --------------------------------------------------------------------------
int main(int argc, char** argv)
{
try
{
if( argc>1 && !strcmp(argv[1],"--help") )
{
short_usage();
return 0;
}
uniset_init(argc,argv,"configure.xml");
ObjectId ID = conf->getInfoServer();
// определяем ID объекта
string name = conf->getArgParam("--name");
if( !name.empty() )
{
if( ID != UniSetTypes::DefaultObjectId )
{
unideb[Debug::WARN] << "(InfoServer::main): переопределяем ID заданнй в "
<< conf->getConfFileName() << endl;
}
ID = conf->oind->getIdByName(conf->getServicesSection()+"/"+name);
if( ID == UniSetTypes::DefaultObjectId )
{
cerr << "(InfoServer): идентификатор '" << name
<< "' не найден в конф. файле!"
<< " в секции " << conf->getServicesSection() << endl;
return 1;
}
}
else if( ID == UniSetTypes::DefaultObjectId )
{
cerr << "(DBServer::main): Не удалось определить ИДЕНТИФИКАТОР сервера" << endl;
short_usage();
return 1;
}
// определяем ask-файл
string askfile = conf->getArgParam("--askfile",conf->getConfFileName());
if( askfile.empty() )
{
InfoServer is(ID,new ISRestorer_XML(askfile));
ObjectsActivator act;
act.addObject(static_cast<class UniSetObject*>(&is));
act.run(false);
}
else
{
InfoServer is(ID);
ObjectsActivator act;
act.addObject(static_cast<class UniSetObject*>(&is));
act.run(false);
}
return 0;
}
catch(Exception& ex)
{
cerr << "(InfoServer::main): " << ex << endl;
}
catch(...)
{
cerr << "(InfoServer::main): catch ..." << endl;
}
return 1;
}
# This file is a part of the NCS project. (c) 1999-2002 All rights reserved.
# $Id: idl.mk,v 1.2 2006/10/14 16:53:22 vpashka Exp $
# Общий файл для IDL
# Нужно иметь в виду, что когда порождаемые omniidl файлы
# будут кем-либо изменены, они перегенерируются только
# при изменении исходного IDL
IDLFLAGS = -I$(top_builddir)/IDL
# Получения списков генерируемых файлов
HHTARG=$(patsubst %.idl, ${HHDIR}/%.hh, ${IDLFILES})
CCTARG=$(patsubst %.idl, ${CCDIR}/%SK.cc, ${IDLFILES})
########################################################################
all: ${HHTARG} ${CCTARG}
dynamic: all
${HHTARG} ${CCTARG}: ${IDLFILES}
for i in $^; do ${IDL} -v -bcxx ${IDLFLAGS} $$i; done
mv --target-directory=${HHDIR} *.hh
mv --target-directory=${CCDIR} *.cc
.PHONY: clean depend
clean:
${RM} ${HHTARG} ${CCTARG}
depend:
install:
bin_PROGRAMS = @PACKAGE@-udpexchange
noinst_PROGRAMS = @PACKAGE@-udpreceiver @PACKAGE@-unetexchange
#@PACKAGE@-udpsender
# не забывайте править версию в pc-файле
UUDP_VER=@LIBVER@
lib_LTLIBRARIES = libUniSetUDP.la
libUniSetUDP_la_LDFLAGS = -version-info $(UUDP_VER)
libUniSetUDP_la_LIBADD = $(top_builddir)/lib/libUniSet.la \
$(top_builddir)/extensions/SharedMemory/libUniSetSharedMemory.la \
$(top_builddir)/extensions/lib/libUniSetExtensions.la \
$(SIGC_LIBS) $(COMCPP_LIBS)
libUniSetUDP_la_CXXFLAGS = -I$(top_builddir)/extensions/include -I$(top_builddir)/extensions/SharedMemory $(SIGC_CFLAGS) $(COMCPP_CFLAGS)
libUniSetUDP_la_SOURCES = UDPPacket.cc UDPExchange.cc UDPNReceiver.cc UDPReceiver.cc UNetReceiver.cc UNetSender.cc UNetExchange.cc
#UDPSender.cc
#UDPSender.cc
@PACKAGE@_udpexchange_SOURCES = udpexchange.cc
@PACKAGE@_udpexchange_LDADD = libUniSetUDP.la $(top_builddir)/lib/libUniSet.la \
$(top_builddir)/extensions/SharedMemory/libUniSetSharedMemory.la \
$(top_builddir)/extensions/lib/libUniSetExtensions.la \
$(SIGC_LIBS) $(COMCPP_LIBS)
@PACKAGE@_udpexchange_CXXFLAGS = -I$(top_builddir)/extensions/include -I$(top_builddir)/extensions/SharedMemory $(SIGC_CFLAGS) $(COMCPP_CFLAGS)
@PACKAGE@_udpsender_SOURCES = udpsender.cc
@PACKAGE@_udpsender_LDADD = libUniSetUDP.la $(top_builddir)/lib/libUniSet.la \
$(top_builddir)/extensions/SharedMemory/libUniSetSharedMemory.la \
$(top_builddir)/extensions/lib/libUniSetExtensions.la \
$(SIGC_LIBS) $(COMCPP_LIBS)
@PACKAGE@_udpsender_CXXFLAGS = -I$(top_builddir)/extensions/include -I$(top_builddir)/extensions/SharedMemory $(SIGC_CFLAGS) $(COMCPP_CFLAGS)
@PACKAGE@_udpreceiver_SOURCES = udpreceiver.cc
@PACKAGE@_udpreceiver_LDADD = libUniSetUDP.la $(top_builddir)/lib/libUniSet.la \
$(top_builddir)/extensions/SharedMemory/libUniSetSharedMemory.la \
$(top_builddir)/extensions/lib/libUniSetExtensions.la \
$(SIGC_LIBS) $(COMCPP_LIBS)
@PACKAGE@_udpreceiver_CXXFLAGS = -I$(top_builddir)/extensions/include -I$(top_builddir)/extensions/SharedMemory $(SIGC_CFLAGS) $(COMCPP_CFLAGS)
@PACKAGE@_unetexchange_SOURCES = unetexchange.cc
@PACKAGE@_unetexchange_LDADD = libUniSetUDP.la $(top_builddir)/lib/libUniSet.la \
$(top_builddir)/extensions/SharedMemory/libUniSetSharedMemory.la \
$(top_builddir)/extensions/lib/libUniSetExtensions.la \
$(SIGC_LIBS) $(COMCPP_LIBS)
@PACKAGE@_unetexchange_CXXFLAGS = -I$(top_builddir)/extensions/include -I$(top_builddir)/extensions/SharedMemory $(SIGC_CFLAGS) $(COMCPP_CFLAGS)
# install
devel_include_HEADERS = *.h
devel_includedir = $(pkgincludedir)/extensions
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libUniSetUDP.pc
all-local:
ln -sf ../UDPExchange/$(devel_include_HEADERS) ../include
#ifndef UDPExchange_H_
#define UDPExchange_H_
// -----------------------------------------------------------------------------
#include <ostream>
#include <string>
#include <vector>
#include <cc++/socket.h>
#include "UniSetObject_LT.h"
#include "Trigger.h"
#include "Mutex.h"
#include "SMInterface.h"
#include "SharedMemory.h"
#include "ThreadCreator.h"
#include "UDPPacket.h"
#include "UDPNReceiver.h"
// -----------------------------------------------------------------------------
class UDPExchange:
public UniSetObject_LT
{
public:
UDPExchange( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmID, SharedMemory* ic=0 );
virtual ~UDPExchange();
/*! глобальная функция для инициализации объекта */
static UDPExchange* init_udpexchange( int argc, char* argv[],
UniSetTypes::ObjectId shmID, SharedMemory* ic=0 );
/*! глобальная функция для вывода help-а */
static void help_print( int argc, char* argv[] );
struct UItem
{
UItem():
val(0)
{}
IOController_i::SensorInfo si;
IOController::AIOStateList::iterator ait;
IOController::DIOStateList::iterator dit;
UniSetTypes::uniset_spin_mutex val_lock;
// UniSetUDP::UDPMessage::UDPDataList::iterator pack_it;
int pack_ind;
long val;
friend std::ostream& operator<<( std::ostream& os, UItem& p );
};
protected:
xmlNode* cnode;
std::string s_field;
std::string s_fvalue;
SMInterface* shm;
void poll();
void recv();
void send();
void step();
virtual void processingMessage( UniSetTypes::VoidMessage *msg );
void sysCommand( UniSetTypes::SystemMessage *msg );
void sensorInfo( UniSetTypes::SensorMessage*sm );
void askSensors( UniversalIO::UIOCommand cmd );
void waitSMReady();
virtual bool activateObject();
// действия при завершении работы
virtual void sigterm( int signo );
void initIterators();
bool initItem( UniXML_iterator& it );
bool readItem( UniXML& xml, UniXML_iterator& it, xmlNode* sec );
void readConfiguration();
bool check_item( UniXML_iterator& it );
void buildReceiverList();
private:
UDPExchange();
bool initPause;
UniSetTypes::uniset_mutex mutex_start;
PassiveTimer ptHeartBeat;
UniSetTypes::ObjectId sidHeartBeat;
int maxHeartBeat;
IOController::AIOStateList::iterator aitHeartBeat;
UniSetTypes::ObjectId test_id;
int polltime; /*!< переодичность обновления данных, [мсек] */
ost::UDPBroadcast* udp;
ost::IPV4Host host;
ost::tpport_t port;
std::string s_host;
UniSetTypes::uniset_mutex pollMutex;
Trigger trTimeout;
int recvTimeout;
int sendTimeout;
bool activated;
int activateTimeout;
UniSetUDP::UDPMessage mypack;
typedef std::vector<UItem> DMap;
DMap dlist;
int maxItem;
typedef std::list<UDPNReceiver*> ReceiverList;
ReceiverList rlist;
ThreadCreator<UDPExchange>* thr;
long packetnum;
};
// -----------------------------------------------------------------------------
#endif // UDPExchange_H_
// -----------------------------------------------------------------------------
#include <sstream>
#include "Exceptions.h"
#include "Extensions.h"
#include "UDPNReceiver.h"
// -----------------------------------------------------------------------------
using namespace std;
using namespace UniSetTypes;
using namespace UniSetExtensions;
// -----------------------------------------------------------------------------
UDPNReceiver::UDPNReceiver( ost::tpport_t p, ost::IPV4Host h, UniSetTypes::ObjectId shmId, IONotifyController* ic ):
shm(0),
ui(conf),
activate(false),
udp(0),
host(h),
port(p),
recvTimeout(5000),
conn(false)
{
{
ostringstream s;
s << host << ":" << port;
myname = s.str();
}
shm = new SMInterface(shmId,&ui,DefaultObjectId,ic);
if( dlog.debugging(Debug::INFO) )
dlog[Debug::INFO] << "(UDPNReceiver): UDP set to " << host << ":" << port << endl;
try
{
udp = new ost::UDPDuplex(host,port);
}
catch( ost::SockException& e )
{
ostringstream s;
s << e.getString() << ": " << e.getSystemErrorString() << endl;
throw SystemError(s.str());
}
thr = new ThreadCreator<UDPNReceiver>(this, &UDPNReceiver::poll);
thr->start();
}
// -----------------------------------------------------------------------------
UDPNReceiver::~UDPNReceiver()
{
delete udp;
delete shm;
delete thr;
}
// -----------------------------------------------------------------------------
void UDPNReceiver::poll()
{
while( 1 )
{
if( !activate )
{
msleep(1000);
continue;
}
try
{
recv();
}
catch( ost::SockException& e )
{
cerr << e.getString() << ": " << e.getSystemErrorString() << endl;
}
catch( UniSetTypes::Exception& ex)
{
cerr << myname << "(step): " << ex << std::endl;
}
catch(...)
{
cerr << myname << "(step): catch ..." << std::endl;
}
}
cerr << "************* execute FINISH **********" << endl;
}
// -----------------------------------------------------------------------------
void UDPNReceiver::recv()
{
cout << myname << ": recv....(timeout=" << recvTimeout << ")" << endl;
// UniSetUDP::UDPHeader h;
// receive
UniSetUDP::UDPMessage pack;
if( udp->isInputReady(recvTimeout) )
{
/*
size_t ret = udp->UDPReceive::receive(&h,sizeof(h));
if( ret<(size_t)sizeof(h) )
{
cerr << myname << "(receive): ret=" << ret << " sizeof=" << sizeof(pack.msg) << endl;
return;
}
cerr << myname << "(receive): OK. ret=" << ret << " sizeof=" << sizeof(pack.msg) << endl;
}
/*
cout << myname << "(receive): header: " << h << endl;
if( h.dcount <=0 )
{
cout << " data=0" << endl;
return;
}
UniSetUDP::UDPData d;
// ignore echo...
*/
#if 0
if( h.nodeID == conf->getLocalNode() && h.procID == getId() )
{
for( int i=0; i<h.dcount;i++ )
{
size_t ret = udp->UDPReceive::receive(&d,sizeof(d));
if( ret < (size_t)sizeof(d) )
return;
}
return;
}
#endif
for( int i=0; i<100;i++ )
{
size_t ret = udp->UDPReceive::receive(&d,sizeof(d));
if( ret<(size_t)sizeof(d) )
{
cerr << myname << "(receive data " << i << "): ret=" << ret << " sizeof=" << sizeof(d) << endl;
break;
}
cout << myname << "(receive data " << i << "): " << d << endl;
}
}
// else
// {
// cout << "no InputReady.." << endl;
// }
#endif
}
// -----------------------------------------------------------------------------
UDPNReceiver* UDPNReceiver::init_udpreceiver( int argc, char* argv[], UniSetTypes::ObjectId icID, SharedMemory* ic )
{
string name = conf->getArgParam("--udp-name","UDPReceiver1");
if( name.empty() )
{
cerr << "(udpexchange): Не задан name'" << endl;
return 0;
}
ObjectId ID = conf->getObjectID(name);
if( ID == UniSetTypes::DefaultObjectId )
{
cerr << "(udpexchange): идентификатор '" << name
<< "' не найден в конф. файле!"
<< " в секции " << conf->getObjectsSection() << endl;
return 0;
}
dlog[Debug::INFO] << "(rsexchange): name = " << name << "(" << ID << ")" << endl;
//return new UDPNReceiver(ID,icID,ic);
//return new UDPNReceiver(ID,icID,ic);
return 0;
}
// -----------------------------------------------------------------------------
#ifndef UDPNReceiver_H_
#define UDPNReceiver_H_
// -----------------------------------------------------------------------------
#include <ostream>
#include <string>
#include <vector>
#include <cc++/socket.h>
#include "Mutex.h"
#include "Trigger.h"
#include "SMInterface.h"
#include "SharedMemory.h"
#include "ThreadCreator.h"
#include "UDPPacket.h"
// -----------------------------------------------------------------------------
class UDPNReceiver
{
public:
UDPNReceiver( ost::tpport_t port, ost::IPV4Host host, UniSetTypes::ObjectId shmID, IONotifyController* ic=0 );
virtual ~UDPNReceiver();
inline int getPort(){ return port; }
inline bool isConnetcion(){ return conn; }
inline void start(){ activate = true; }
inline void stop(){ activate = false; }
inline void setReceiveTimeout( int t ){ recvTimeout = t; }
inline std::string getName(){ return myname; }
/*! глобальная функция для инициализации объекта */
static UDPNReceiver* init_udpreceiver( int argc, char* argv[],
UniSetTypes::ObjectId shmID, SharedMemory* ic=0 );
protected:
SMInterface* shm;
UniversalInterface ui;
void poll();
void recv();
std::string myname;
private:
UDPNReceiver();
bool activate;
ost::UDPDuplex* udp;
ost::IPV4Host host;
ost::tpport_t port;
int recvTimeout;
bool conn;
ThreadCreator<UDPNReceiver>* thr;
};
// -----------------------------------------------------------------------------
#endif // UDPNReceiver_H_
// -----------------------------------------------------------------------------
#include "UDPPacket.h"
// -----------------------------------------------------------------------------
using namespace std;
using namespace UniSetUDP;
// -----------------------------------------------------------------------------
std::ostream& UniSetUDP::operator<<( std::ostream& os, UniSetUDP::UDPHeader& p )
{
return os << "nodeID=" << p.nodeID
<< " procID=" << p.procID
<< " dcount=" << p.dcount
<< " pnum=" << p.num;
}
// -----------------------------------------------------------------------------
std::ostream& UniSetUDP::operator<<( std::ostream& os, UniSetUDP::UDPData& p )
{
return os << "id=" << p.id << " val=" << p.val;
}
// -----------------------------------------------------------------------------
std::ostream& UniSetUDP::operator<<( std::ostream& os, UniSetUDP::UDPMessage& p )
{
return os;
}
// -----------------------------------------------------------------------------
UDPMessage::UDPMessage():
count(0)
{
}
// -----------------------------------------------------------------------------
bool UDPMessage::addData( const UniSetUDP::UDPData& dat )
{
if( count >= MaxDataCount )
return false;
msg.dat[count] = dat;
count++;
msg.header.dcount = count;
return true;
}
// -----------------------------------------------------------------------------
bool UDPMessage::addData( long id, long val)
{
UDPData d(id,val);
return addData(d);
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
#ifndef UDPPacket_H_
#define UDPPacket_H_
// -----------------------------------------------------------------------------
#include <cc++/socket.h>
#include "UniSetTypes.h"
// -----------------------------------------------------------------------------
namespace UniSetUDP
{
struct UDPHeader
{
UDPHeader():num(0),nodeID(0),procID(0),dcount(0){}
timeout_t num;
long nodeID;
long procID;
size_t dcount;
friend std::ostream& operator<<( std::ostream& os, UDPHeader& p );
}__attribute__((packed));
static unsigned long MaxPacketNum = std::numeric_limits<unsigned long>::max();
struct UDPData
{
UDPData():id(UniSetTypes::DefaultObjectId),val(0){}
UDPData(long id, long val):id(id),val(val){}
long id;
long val;
friend std::ostream& operator<<( std::ostream& os, UDPData& p );
}__attribute__((packed));
static const int MaxDataLen = 8192;
static const int MaxDataCount = ( MaxDataLen - sizeof(UniSetUDP::UDPHeader) ) / sizeof(UDPData);
struct DataPacket
{
UDPHeader header;
UDPData dat[MaxDataCount];
}__attribute__((packed));
struct UDPMessage:
public UDPHeader
{
UDPMessage();
bool addData( const UDPData& dat );
bool addData( long id, long val );
inline bool isFull(){ return count<MaxDataCount; }
inline int size(){ return count; }
inline int byte_size(){ return count*sizeof(UDPData); }
DataPacket msg;
int count;
friend std::ostream& operator<<( std::ostream& os, UDPMessage& p );
};
}
// -----------------------------------------------------------------------------
#endif // UDPPacket_H_
// -----------------------------------------------------------------------------
#ifndef UDPReceiver_H_
#define UDPReceiver_H_
// -----------------------------------------------------------------------------
#include <ostream>
#include <string>
#include <queue>
#include <cc++/socket.h>
#include "UniSetObject_LT.h"
#include "Trigger.h"
#include "Mutex.h"
#include "SMInterface.h"
#include "SharedMemory.h"
#include "ThreadCreator.h"
#include "UDPPacket.h"
// -----------------------------------------------------------------------------
/* Основная идея: сделать проверку очерёдности пакетов, но при этом использовать UDP.
* ===============
* Собственно реализация сделана так:
* В данных передаётся номер пакета. На случай если несколько пакетов придут не в той последовательности
* что были посланы, сделана очередь с приоритетом. В качестве приориета используется номер пакета
* (чем меньше тем старше). И при этом эта очередь постоянно поддерживается наполненной на minBufSize записей.
* Это гарантирует, что соседние пакеты пришедшие не в той последовательности, тем не менее обработаны будут в правильной.
* Т.к. в очереди они "отсортируются" по номеру пакета, ещё до обработки.
*
*
* КЭШ
* ===
* Для оптимизации работы с SM, т.к. в пакетах приходят только пары [id,value] сделан кэш итераторов.
* Кэш расчитан на то, что принимаемые пакеты всегда имеют одну и ту же длину и последовательность.
* Идея проста: сделан вектор размером с количество принимаемых данных. В векторе хранятся итераторы (и всё что необходимо).
* Порядокый номер данных в пакете является индексом в кэше.
* Для защиты от изменения поседовательности внутри пакета, в кэше хранится ID сохраняемого датчика, и если он не совпадёт с тем,
* ID который пришёл в пакете - элемент кэша обновляется.
* Если количество пришедших данных не совпадают с размером кэша.. кэш обновляется.
*/
// -----------------------------------------------------------------------------
class UDPReceiver:
public UniSetObject_LT
{
public:
UDPReceiver( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmID, SharedMemory* ic=0 );
virtual ~UDPReceiver();
/*! глобальная функция для инициализации объекта */
static UDPReceiver* init_udpreceiver( int argc, char* argv[],
UniSetTypes::ObjectId shmID, SharedMemory* ic=0 );
/*! глобальная функция для вывода help-а */
static void help_print( int argc, char* argv[] );
protected:
xmlNode* cnode;
std::string s_field;
std::string s_fvalue;
SMInterface* shm;
void poll();
void recv();
void step();
void update();
virtual void processingMessage( UniSetTypes::VoidMessage *msg );
void sysCommand( UniSetTypes::SystemMessage *msg );
void sensorInfo( UniSetTypes::SensorMessage*sm );
void timerInfo( UniSetTypes::TimerMessage *tm );
void askSensors( UniversalIO::UIOCommand cmd );
void waitSMReady();
virtual bool activateObject();
// действия при завершении работы
virtual void sigterm( int signo );
void initIterators();
enum Timer
{
tmUpdate,
tmStep
};
private:
UDPReceiver();
bool initPause;
UniSetTypes::uniset_mutex mutex_start;
PassiveTimer ptHeartBeat;
UniSetTypes::ObjectId sidHeartBeat;
int maxHeartBeat;
IOController::AIOStateList::iterator aitHeartBeat;
UniSetTypes::ObjectId test_id;
int polltime; /*!< пауза меджду приёмами пакетов, [мсек] */
int updatetime; /*!< переодичность обновления данных в SM, [мсек] */
int steptime; /*!< периодичность вызова step, [мсек] */
ost::UDPDuplex* udp;
ost::IPV4Host host;
ost::tpport_t port;
UniSetTypes::uniset_mutex pollMutex;
Trigger trTimeout;
int recvTimeout;
bool activated;
int activateTimeout;
ThreadCreator<UDPReceiver>* thr;
// функция определения приоритетного сообщения для обработки
struct PacketCompare:
public std::binary_function<UniSetUDP::UDPMessage, UniSetUDP::UDPMessage, bool>
{
bool operator()(const UniSetUDP::UDPMessage& lhs,
const UniSetUDP::UDPMessage& rhs) const;
};
typedef std::priority_queue<UniSetUDP::UDPMessage,std::vector<UniSetUDP::UDPMessage>,PacketCompare> PacketQueue;
PacketQueue qpack; /*!< очередь принятых пакетов (отсортированных по возрастанию номера пакета) */
UniSetUDP::UDPMessage pack; /*!< прсто буфер для получения очерещного сообщения */
UniSetTypes::uniset_mutex packMutex; /*!< mutex для работы с очередью */
long pnum; /*!< текущий номер обработанного сообщения, для проверки непрерывности последовательности пакетов */
/*! Минимальный размер очереди.
* Предназначен для создания буфера, чтобы обработка сообщений шла
* в порядке возрастания номеров пакетов. Даже если при приёме последовательность нарушалась
*/
int minBufSize;
int maxProcessingCount; /*! максимальное число обрабатываемых за один раз сообщений */
struct ItemInfo
{
long id;
IOController::AIOStateList::iterator ait;
IOController::DIOStateList::iterator dit;
UniversalIO::IOTypes iotype;
};
typedef std::vector<ItemInfo> ItemVec;
ItemVec icache; /*!< кэш итераторов */
bool cache_init_ok;
void initCache( UniSetUDP::UDPMessage& pack, bool force=false );
};
// -----------------------------------------------------------------------------
#endif // UDPReceiver_H_
// -----------------------------------------------------------------------------
#ifndef UNetExchange_H_
#define UNetExchange_H_
// -----------------------------------------------------------------------------
#include <ostream>
#include <string>
#include <queue>
#include <cc++/socket.h>
#include "UniSetObject_LT.h"
#include "Trigger.h"
#include "Mutex.h"
#include "SMInterface.h"
#include "SharedMemory.h"
#include "ThreadCreator.h"
#include "UNetReceiver.h"
#include "UNetSender.h"
// -----------------------------------------------------------------------------
class UNetExchange:
public UniSetObject_LT
{
public:
UNetExchange( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmID, SharedMemory* ic=0 );
virtual ~UNetExchange();
/*! глобальная функция для инициализации объекта */
static UNetExchange* init_unetexchange( int argc, char* argv[],
UniSetTypes::ObjectId shmID, SharedMemory* ic=0 );
/*! глобальная функция для вывода help-а */
static void help_print( int argc, char* argv[] );
bool checkExistUNetHost( const std::string host, ost::tpport_t port );
protected:
xmlNode* cnode;
std::string s_field;
std::string s_fvalue;
SMInterface* shm;
void step();
virtual void processingMessage( UniSetTypes::VoidMessage *msg );
void sysCommand( UniSetTypes::SystemMessage *msg );
void sensorInfo( UniSetTypes::SensorMessage*sm );
void timerInfo( UniSetTypes::TimerMessage *tm );
void askSensors( UniversalIO::UIOCommand cmd );
void waitSMReady();
virtual bool activateObject();
// действия при завершении работы
virtual void sigterm( int signo );
void initIterators();
void startReceivers();
void initSender( const std::string host, const ost::tpport_t port, UniXML_iterator& it );
enum Timer
{
tmStep
};
private:
UNetExchange();
bool initPause;
UniSetTypes::uniset_mutex mutex_start;
PassiveTimer ptHeartBeat;
UniSetTypes::ObjectId sidHeartBeat;
int maxHeartBeat;
IOController::AIOStateList::iterator aitHeartBeat;
UniSetTypes::ObjectId test_id;
int steptime; /*!< периодичность вызова step, [мсек] */
bool activated;
int activateTimeout;
typedef std::list<UNetReceiver*> ReceiverList;
ReceiverList recvlist;
bool no_sender; /*!< флаг отключения посылки сообщений */
UNetSender* sender;
};
// -----------------------------------------------------------------------------
#endif // UNetExchange_H_
// -----------------------------------------------------------------------------
#ifndef UNetReceiver_H_
#define UNetReceiver_H_
// -----------------------------------------------------------------------------
#include <ostream>
#include <string>
#include <queue>
#include <cc++/socket.h>
#include "UniSetObject_LT.h"
#include "Trigger.h"
#include "Mutex.h"
#include "SMInterface.h"
#include "SharedMemory.h"
#include "ThreadCreator.h"
#include "UDPPacket.h"
// -----------------------------------------------------------------------------
/* Основная идея: сделать проверку очерёдности пакетов, но при этом использовать UDP.
* ===============
* Собственно реализация сделана так:
* В данных передаётся номер пакета. На случай если несколько пакетов придут не в той последовательности
* что были посланы, сделана очередь с приоритетом. В качестве приориета используется номер пакета
* (чем меньше тем старше). При этом обработка ведётся только тех пакетов, которые идут "подряд",
* как только встречается "дырка" происходит ожидание её "заполения". Если в течение времени (lostTimeout)
* "дырка" не исчезает, увеличивается счётчик потерянных пакетов и обработка продолжается дальше..
* Всё это реализовано в функции UNetReceiver::real_update()
*
* КЭШ
* ===
* Для оптимизации работы с SM, т.к. в пакетах приходят только пары [id,value] сделан кэш итераторов.
* Кэш расчитан на то, что принимаемые пакеты всегда имеют одну и ту же длину и последовательность.
* Идея проста: сделан вектор размером с количество принимаемых данных. В векторе хранятся итераторы (и всё что необходимо).
* Порядокый номер данных в пакете является индексом в кэше.
* Для защиты от изменения поседовательности внутри пакета, в кэше хранится ID сохраняемого датчика, и если он не совпадёт с тем,
* ID который пришёл в пакете - элемент кэша обновляется.
* Если количество пришедших данных не совпадают с размером кэша.. кэш обновляется.
*
* Обработка сбоя или переполнения счётчика пакетов(перехода через максимум)
* =========================================================================
* Для защиты от сбоя счётика сделана следующая логика:
* Если номер очередного пришедшего пакета отличается от последнего обработанного на maxDifferens, то считается,
* что произошёл сбой счётчика и происходит ожидание пока функция update, не обработает основную очередь полностью.
* При этом принимаемые пакеты складываются во временную очередь qtmp. Как только основная очередь пустеет,
* в неё копируется всё накопленное во временной очереди..и опять идёт штатная обработка.
* Если во время "ожидания" опять происходит "разрыв" в номерах пакетов, то временная очередь чиститься
* и данные которые в ней были теряются! Аналог ограниченного буфера (у любых карт), когда новые данные
* затирают старые, если их не успели вынуть и обработать.
* \todo Сделать защиту от бесконечного ожидания "очистки" основной очереди.
*/
// -----------------------------------------------------------------------------
class UNetReceiver
{
public:
UNetReceiver( const std::string host, const ost::tpport_t port, SMInterface* smi );
~UNetReceiver();
void start();
void receive();
void update();
inline bool isRecvOK(){ return ptRecvTimeout.checkTime(); }
inline unsigned long getLostPacketsNum(){ return lostPackets; }
void setReceiveTimeout( timeout_t msec );
void setReceivePause( timeout_t msec );
void setUpdatePause( timeout_t msec );
void setLostTimeout( timeout_t msec );
void setMaxDifferens( unsigned long set );
void setMaxProcessingCount( int set );
inline ost::IPV4Address getAddress(){ return addr; }
inline ost::tpport_t getPort(){ return port; }
protected:
SMInterface* shm;
bool recv();
void step();
void real_update();
void initIterators();
private:
UNetReceiver();
int recvpause; /*!< пауза меджду приёмами пакетов, [мсек] */
int updatepause; /*!< переодичность обновления данных в SM, [мсек] */
ost::UDPReceive* udp;
ost::IPV4Address addr;
ost::tpport_t port;
std::string myname;
UniSetTypes::uniset_mutex pollMutex;
PassiveTimer ptRecvTimeout;
timeout_t recvTimeout;
timeout_t lostTimeout;
PassiveTimer ptLostTimeout;
unsigned long lostPackets; /*!< счётчик потерянных пакетов */
bool activated;
ThreadCreator<UNetReceiver>* r_thr; // receive thread
ThreadCreator<UNetReceiver>* u_thr; // update thread
// функция определения приоритетного сообщения для обработки
struct PacketCompare:
public std::binary_function<UniSetUDP::UDPMessage, UniSetUDP::UDPMessage, bool>
{
bool operator()(const UniSetUDP::UDPMessage& lhs,
const UniSetUDP::UDPMessage& rhs) const;
};
typedef std::priority_queue<UniSetUDP::UDPMessage,std::vector<UniSetUDP::UDPMessage>,PacketCompare> PacketQueue;
PacketQueue qpack; /*!< очередь принятых пакетов (отсортированных по возрастанию номера пакета) */
UniSetUDP::UDPMessage pack; /*!< просто буфер для получения очереlного сообщения */
UniSetTypes::uniset_mutex packMutex; /*!< mutex для работы с очередью */
unsigned long pnum; /*!< текущий номер обработанного сообщения, для проверки непрерывности последовательности пакетов */
/*! максимальная разница межд номерами пакетов, при которой считается, что счётчик пакетов
* прошёл через максимум или сбился...
*/
unsigned long maxDifferens;
PacketQueue qtmp; /*!< очередь на время обработки(очистки) основной очереди */
bool waitClean; /*!< флаг означающий, что ждём очистики очереди до конца */
unsigned long rnum; /*!< текущий номер принятого сообщения, для проверки "переполнения" или "сбоя" счётчика */
int maxProcessingCount; /*! максимальное число обрабатываемых за один раз сообщений */
struct ItemInfo
{
long id;
IOController::AIOStateList::iterator ait;
IOController::DIOStateList::iterator dit;
UniversalIO::IOTypes iotype;
};
typedef std::vector<ItemInfo> ItemVec;
ItemVec icache; /*!< кэш итераторов */
bool cache_init_ok;
void initCache( UniSetUDP::UDPMessage& pack, bool force=false );
};
// -----------------------------------------------------------------------------
#endif // UNetReceiver_H_
// -----------------------------------------------------------------------------
#include <sstream>
#include "Exceptions.h"
#include "Extensions.h"
#include "UNetSender.h"
// -----------------------------------------------------------------------------
using namespace std;
using namespace UniSetTypes;
using namespace UniSetExtensions;
// -----------------------------------------------------------------------------
UNetSender::UNetSender( const std::string s_host, const ost::tpport_t port, SMInterface* smi,
const std::string s_f, const std::string s_val, SharedMemory* ic ):
s_field(s_f),
s_fvalue(s_val),
shm(smi),
s_host(s_host),
sendpause(150),
activated(false),
dlist(100),
maxItem(0),
packetnum(1),
s_thr(0)
{
{
ostringstream s;
s << "(" << s_host << ":" << port << ")";
myname = s.str();
}
// определяем фильтр
// s_field = conf->getArgParam("--udp-filter-field");
// s_fvalue = conf->getArgParam("--udp-filter-value");
dlog[Debug::INFO] << myname << "(init): read fileter-field='" << s_field
<< "' filter-value='" << s_fvalue << "'" << endl;
if( dlog.debugging(Debug::INFO) )
dlog[Debug::INFO] << "(UNetSender): UDP set to " << s_host << ":" << port << endl;
try
{
addr = s_host.c_str();
udp = new ost::UDPBroadcast(addr,port);
}
catch( ost::SockException& e )
{
ostringstream s;
s << e.getString() << ": " << e.getSystemErrorString() << endl;
throw SystemError(s.str());
}
s_thr = new ThreadCreator<UNetSender>(this, &UNetSender::send);
// -------------------------------
if( shm->isLocalwork() )
{
readConfiguration();
dlist.resize(maxItem);
dlog[Debug::INFO] << myname << "(init): dlist size = " << dlist.size() << endl;
}
else
ic->addReadItem( sigc::mem_fun(this,&UNetSender::readItem) );
// выставляем поля, которые не меняются
mypack.msg.header.nodeID = conf->getLocalNode();
mypack.msg.header.procID = shm->ID();
}
// -----------------------------------------------------------------------------
UNetSender::~UNetSender()
{
delete s_thr;
delete udp;
delete shm;
}
// -----------------------------------------------------------------------------
void UNetSender::update( UniSetTypes::ObjectId id, long value )
{
DMap::iterator it=dlist.begin();
for( ; it!=dlist.end(); ++it )
{
if( it->si.id == id )
{
uniset_spin_lock lock(it->val_lock);
it->val = value;
}
break;
}
}
// -----------------------------------------------------------------------------
void UNetSender::send()
{
dlist.resize(maxItem);
dlog[Debug::INFO] << myname << "(init): dlist size = " << dlist.size() << endl;
/*
ost::IPV4Broadcast h = s_host.c_str();
try
{
udp->setPeer(h,port);
}
catch( ost::SockException& e )
{
ostringstream s;
s << e.getString() << ": " << e.getSystemErrorString();
dlog[Debug::CRIT] << myname << "(poll): " << s.str() << endl;
throw SystemError(s.str());
}
*/
while( activated )
{
try
{
real_send();
}
catch( ost::SockException& e )
{
cerr << e.getString() << ": " << e.getSystemErrorString() << endl;
}
catch( UniSetTypes::Exception& ex)
{
cerr << myname << "(send): " << ex << std::endl;
}
catch(...)
{
cerr << myname << "(send): catch ..." << std::endl;
}
msleep(sendpause);
}
cerr << "************* execute FINISH **********" << endl;
}
// -----------------------------------------------------------------------------
void UNetSender::real_send()
{
mypack.msg.header.num = packetnum++;
if( packetnum > UniSetUDP::MaxPacketNum )
packetnum = 1;
// cout << "************* send header: " << mypack.msg.header << endl;
int sz = mypack.byte_size() + sizeof(UniSetUDP::UDPHeader);
if( !udp->isPending(ost::Socket::pendingOutput) )
return;
size_t ret = udp->send( (char*)&(mypack.msg),sz);
if( ret < sz )
dlog[Debug::CRIT] << myname << "(send): FAILED ret=" << ret << " < sizeof=" << sz << endl;
}
// -----------------------------------------------------------------------------
void UNetSender::start()
{
if( !activated )
{
activated = true;
s_thr->start();
}
}
// -----------------------------------------------------------------------------
void UNetSender::readConfiguration()
{
xmlNode* root = conf->getXMLSensorsSection();
if(!root)
{
ostringstream err;
err << myname << "(readConfiguration): not found <sensors>";
throw SystemError(err.str());
}
UniXML_iterator it(root);
if( !it.goChildren() )
{
std::cerr << myname << "(readConfiguration): empty <sensors>?!!" << endl;
return;
}
for( ;it.getCurrent(); it.goNext() )
{
if( check_item(it) )
initItem(it);
}
}
// ------------------------------------------------------------------------------------------
bool UNetSender::check_item( UniXML_iterator& it )
{
if( s_field.empty() )
return true;
// просто проверка на не пустой field
if( s_fvalue.empty() && it.getProp(s_field).empty() )
return false;
// просто проверка что field = value
if( !s_fvalue.empty() && it.getProp(s_field)!=s_fvalue )
return false;
return true;
}
// ------------------------------------------------------------------------------------------
bool UNetSender::readItem( UniXML& xml, UniXML_iterator& it, xmlNode* sec )
{
if( check_item(it) )
initItem(it);
return true;
}
// ------------------------------------------------------------------------------------------
bool UNetSender::initItem( UniXML_iterator& it )
{
string sname( it.getProp("name") );
string tid = it.getProp("id");
ObjectId sid;
if( !tid.empty() )
{
sid = UniSetTypes::uni_atoi(tid);
if( sid <= 0 )
sid = DefaultObjectId;
}
else
sid = conf->getSensorID(sname);
if( sid == DefaultObjectId )
{
if( dlog )
dlog[Debug::CRIT] << myname << "(readItem): ID not found for "
<< sname << endl;
return false;
}
UItem p;
p.si.id = sid;
p.si.node = conf->getLocalNode();
mypack.addData(sid,0);
p.pack_ind = mypack.size()-1;
if( maxItem >= mypack.size() )
dlist.resize(maxItem+10);
dlist[maxItem] = p;
maxItem++;
if( dlog.debugging(Debug::INFO) )
dlog[Debug::INFO] << myname << "(initItem): add " << p << endl;
return true;
}
// ------------------------------------------------------------------------------------------
void UNetSender::initIterators()
{
DMap::iterator it=dlist.begin();
for( ; it!=dlist.end(); it++ )
{
shm->initDIterator(it->dit);
shm->initAIterator(it->ait);
}
}
// -----------------------------------------------------------------------------
std::ostream& operator<<( std::ostream& os, UNetSender::UItem& p )
{
return os << " sid=" << p.si.id;
}
// -----------------------------------------------------------------------------
#ifndef UNetSender_H_
#define UNetSender_H_
// -----------------------------------------------------------------------------
#include <ostream>
#include <string>
#include <vector>
#include <cc++/socket.h>
#include "UniSetObject_LT.h"
#include "Trigger.h"
#include "Mutex.h"
#include "SMInterface.h"
#include "SharedMemory.h"
#include "ThreadCreator.h"
#include "UDPPacket.h"
#include "UDPNReceiver.h"
// -----------------------------------------------------------------------------
/*
* Для защиты от потери пакета при переполнении "номера пакета".
* UNetReceiver при обнаружении "разрыва" в последовательнности, просто игнорирует пакет, обновляет счётчик
* и начинает обработку пока буфер опять не заполнится..
*/
class UNetSender
{
public:
UNetSender( const std::string host, const ost::tpport_t port, SMInterface* smi,
const std::string s_field="", const std::string s_fvalue="", SharedMemory* ic=0 );
~UNetSender();
struct UItem
{
UItem():
val(0)
{}
IOController_i::SensorInfo si;
IOController::AIOStateList::iterator ait;
IOController::DIOStateList::iterator dit;
UniSetTypes::uniset_spin_mutex val_lock;
int pack_ind;
long val;
friend std::ostream& operator<<( std::ostream& os, UItem& p );
};
void start();
void send();
void real_send();
void update( UniSetTypes::ObjectId id, long value );
inline void setSendPause( int msec ){ sendpause = msec; }
protected:
std::string s_field;
std::string s_fvalue;
SMInterface* shm;
void initIterators();
bool initItem( UniXML_iterator& it );
bool readItem( UniXML& xml, UniXML_iterator& it, xmlNode* sec );
void readConfiguration();
bool check_item( UniXML_iterator& it );
private:
UNetSender();
ost::UDPBroadcast* udp;
ost::IPV4Address addr;
ost::tpport_t port;
std::string s_host;
std::string myname;
int sendpause;
bool activated;
UniSetUDP::UDPMessage mypack;
typedef std::vector<UItem> DMap;
DMap dlist;
int maxItem;
unsigned long packetnum;
ThreadCreator<UNetSender>* s_thr; // send thread
};
// -----------------------------------------------------------------------------
#endif // UNetSender_H_
// -----------------------------------------------------------------------------
#!/bin/sh
uniset-start.sh -f ./uniset-udpexchange --udp-name UDPExchange --udp-host 192.168.1.255 \
--udp-broadcast 1 --udp-polltime 100 \
--confile test.xml \
--dlog-add-levels info,crit,warn
# --udp-filter-field udp --udp-filter-value 1 \
#!/bin/sh
uniset-start.sh -f ./uniset-udpexchange --udp-name UDPExchange2 --udp-host localhost --udp-port 3001 \
--confile test.xml \
--udp-filter-field udp --udp-filter-value 2we \
--udp-ip \
--dlog-add-levels info,crit,warn
#!/bin/sh
uniset-start.sh -f ./uniset-udpexchange --udp-name UDPExchange \
--confile test.xml \
--udp-filter-field udp --udp-filter-value 1 \
--dlog-add-levels info,crit,warn
#!/bin/sh
uniset-start.sh -f ./uniset-unetexchange --unet-name UNetExchange \
--confile test.xml \
--unet-filter-field rs --unet-filter-value 2 --unet-maxdifferense 40 \
--dlog-add-levels info,crit,warn
#include <sstream>
#include "ObjectsActivator.h"
#include "Extensions.h"
#include "UNetExchange.h"
// -----------------------------------------------------------------------------
using namespace std;
using namespace UniSetTypes;
using namespace UniSetExtensions;
// -----------------------------------------------------------------------------
int main( int argc, char** argv )
{
try
{
if( argc>1 && (!strcmp(argv[1],"--help") || !strcmp(argv[1],"-h")) )
{
cout << "--smemory-id objectName - SharedMemory objectID. Default: read from <SharedMemory>" << endl;
cout << "--confile filename - configuration file. Default: configure.xml" << endl;
cout << "--unet-logfile filename - logfilename. Default: udpexchange.log" << endl;
cout << endl;
UNetExchange::help_print(argc,argv);
return 0;
}
string confile=UniSetTypes::getArgParam("--confile",argc,argv,"configure.xml");
conf = new Configuration( argc, argv, confile );
string logfilename(conf->getArgParam("--unet-logfile"));
if( logfilename.empty() )
logfilename = "udpexchange.log";
conf->initDebug(dlog,"dlog");
std::ostringstream logname;
string dir(conf->getLogDir());
logname << dir << logfilename;
unideb.logFile( logname.str() );
dlog.logFile( logname.str() );
ObjectId shmID = DefaultObjectId;
string sID = conf->getArgParam("--smemory-id");
if( !sID.empty() )
shmID = conf->getControllerID(sID);
else
shmID = getSharedMemoryID();
if( shmID == DefaultObjectId )
{
cerr << sID << "? SharedMemoryID not found in " << conf->getControllersSection() << " section" << endl;
return 1;
}
UNetExchange* unet = UNetExchange::init_unetexchange(argc,argv,shmID);
if( !unet )
{
dlog[Debug::CRIT] << "(unetexchange): init failed.." << endl;
return 1;
}
ObjectsActivator act;
act.addObject(static_cast<class UniSetObject*>(unet));
SystemMessage sm(SystemMessage::StartUp);
act.broadcast( sm.transport_msg() );
unideb(Debug::ANY) << "\n\n\n";
unideb[Debug::ANY] << "(main): -------------- UDPRecevier START -------------------------\n\n";
dlog(Debug::ANY) << "\n\n\n";
dlog[Debug::ANY] << "(main): -------------- UDPReceiver START -------------------------\n\n";
act.run(false);
return 0;
}
catch( Exception& ex )
{
dlog[Debug::CRIT] << "(unetexchange): " << ex << std::endl;
}
catch( ost::SockException& e )
{
ostringstream s;
s << e.getString() << ": " << e.getSystemErrorString();
dlog[Debug::CRIT] << s.str() << endl;
}
catch(...)
{
dlog[Debug::CRIT] << "(unetexchange): catch ..." << std::endl;
}
return 1;
}
../ModbusMaster/MBExchange.h
\ No newline at end of file
/* This file is part of the UniSet project
* Copyright (c) 2002 Free Software Foundation, Inc.
* Copyright (c) 2002 Pavel Vainerman
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// --------------------------------------------------------------------------
/*! \file
* \brief "Пустая" реализация интерфейса работы с сообщениями
* \author Pavel Vainerman
*/
// --------------------------------------------------------------------------
#ifndef DefaultMessageInterface_H_
#define DefaultMessageInterface_H_
// --------------------------------------------------------------------------
#include "MessageInterface.h"
// --------------------------------------------------------------------------
class DefaultMessageInterface:
public MessageInterface
{
public:
DefaultMessageInterface(){}
virtual ~DefaultMessageInterface(){}
virtual std::string getMessage( UniSetTypes::MessageCode code ){ return ""; }
virtual bool isExist(UniSetTypes::MessageCode code){ return false; }
virtual UniSetTypes::MessageCode getCode( const std::string& msg ){ return UniSetTypes::DefaultMessageCode; }
virtual UniSetTypes::MessageCode getCodeByIdName( const std::string& name ){ return UniSetTypes::DefaultMessageCode; }
virtual std::ostream& printMessagesMap(std::ostream& os){ return os; }
};
// --------------------------------------------------------------------------
#endif
/* This file is part of the UniSet project
* Copyright (c) 2002 Free Software Foundation, Inc.
* Copyright (c) 2002 Vitaly Lipatov
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// --------------------------------------------------------------------------
/*! \file
* \brief Заголовочный файл для организации низкоуровневого ввода-вывода.
* \author Vitaly Lipatov
*/
// --------------------------------------------------------------------------
#ifndef DIGITALCARD_H__
#define DIGITALCARD_H__
/*! Абстрактный класс работы с цифровым вводом/выводом */
class DigitalCard
{
public:
virtual ~DigitalCard(){};
// virtual bool getCurrentState(int module)=0;
virtual bool get(int module) = 0;
virtual void set(int module, bool state) = 0;
};
#endif
/* This file is part of the UniSet project
* Copyright (c) 2002 Free Software Foundation, Inc.
* Copyright (c) 2002 Vitaly Lipatov
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// --------------------------------------------------------------------------
/*! \file
* \brief Заголовочный файл для дискретной карты DIO5600
* \author Vitaly Lipatov
*/
// --------------------------------------------------------------------------
#ifndef __DIO5600_H_
#define __DIO5600_H_
// --------------------------------------------------------------------------
#include "DigitalCard.h"
#include "IOs/IOAccessOld.h"
// портов для функций ввода/вывода
const int DIO5600_A = 0x10;
const int DIO5600_B = 0x02;
const int DIO5600_C_LO = 0x01;
const int DIO5600_C_HI = 0x08;
const int DIO5600_C = (DIO5600_C_LO | DIO5600_C_HI);
class DigitalCard_O5600: public DigitalCard, IOAccess
{
public:
//inline DIO5600() { }
inline DigitalCard_O5600(int ba, char mode)
{
init(1, 0, ba, mode);
}
bool get(int module);
// bool getCurrentState(int module);
void set(int module, bool state);
protected:
// void reinit();
char getMask(int module);
char getPrevious(int module);
int getPort(int module);
void putByte(int port, char val);
int getByte(int ba);
bool init(bool flagInit, int numOfCard, int base_address,char mode);
int baseadr; //
char iomode; //
char portmap[4];
};
#endif
/* This file is part of the UniSet project
* Copyright (c) 2002 Free Software Foundation, Inc.
* Copyright (c) 2002 Vitaly Lipatov
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// --------------------------------------------------------------------------
/*! \file
* \brief Заголовочный файл для организации низкоуровневого ввода-вывода.
* \author Vitaly Lipatov
* \par
* Этот файл предназначен для внутреннего использования в классах
* ввода-вывода
*/
// --------------------------------------------------------------------------
#ifndef _IOACCESS_H_
#define _IOACCESS_H_
// --------------------------------------------------------------------------
#include <unistd.h>
#include <fcntl.h>
#include <iostream>
#include "Exceptions.h"
/*! \class IOAccess
* \brief Предоставление операций для низкоуровневого ввода-вывода.
* \author Vitaly Lipatov
* \par
* Этот класс предназначен для внутреннего использования в классах
* ввода-вывода
*/
class IOAccess
{
public:
/// При создании объекта открываются все порты на запись/чтение
IOAccess()
{
fd_port = open("/dev/port", O_RDWR | O_NDELAY);
if ( fd_port == -1 )
throw UniSetTypes::IOBadParam();
}
~IOAccess()
{
close(fd_port);
}
/*! Получение значений из диапазона портов от port до port+size байт.
Записываются по адресу buf.
*/
void get(int port, void* buf, int size) const
{
if ( lseek(fd_port, port, SEEK_SET) == -1 )
throw UniSetTypes::IOBadParam();
ssize_t s = read(fd_port, buf, size);
if ( s != size )
throw UniSetTypes::IOBadParam();
}
/// Получение байта из указанного порта
int in(int port) const
{
char input;
get(port, &input, 1);
return input;
}
/*! Запись значений в диапазон портов от port до port+size байт.
Значения берутся начиная с адреса buf.
*/
void put(int port, const void* buf, int size) const
{
if ( lseek(fd_port, port, SEEK_SET) == -1 )
throw UniSetTypes::IOBadParam();
ssize_t s = write(fd_port, buf, size);
if ( s != size )
throw UniSetTypes::IOBadParam();
}
/// Вывод байта value в порт port
void out(int port, int value) const
{
char output = value;
put(port,&output,1);
}
private:
/// Дескриптор открытого файла, соотнесённого с портами
int fd_port;
};
#endif
/* This file is part of the UniSet project
* Copyright (c) 2002 Free Software Foundation, Inc.
* Copyright (c) 2002 Vitaly Lipatov
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// --------------------------------------------------------------------------
/*! \file
* \brief Предоставление операций для низкоуровневого ввода-вывода.
* \author Vitaly Lipatov
*/
// --------------------------------------------------------------------------
#include <unistd.h>
#ifdef __GLIBC__
#include <sys/io.h> // для glibc
#else
#include <asm/io.h>
#endif
#ifndef _IOACCESS_H_
#define _IOACCESS_H_
#include <fcntl.h>
#include <iostream>
#include <iomanip>
#include "Exceptions.h"
/*! \class IOAccess
* \par
* Этот класс предназначен для внутреннего использования в классах
* ввода-вывода
*/
class IOAccess
{
public:
/// При создании объекта открываются все порты на запись/чтение
IOAccess()
{
std::cout << "IOAccess!!" << std::endl;
if (ioperm( 0x100, 0x50, 0666 ) == -1 )
throw UniSetTypes::IOBadParam();
}
~IOAccess()
{
}
/*! Получение значений из диапазона портов от port до port+size байт.
Записываются по адресу buf.
*/
/*
void get(int port, void* buf, int size) const
{
if ( lseek(fd_port, port, SEEK_SET) == -1 )
throw IOBadParam();
ssize_t s = read(fd_port, buf, size);
if ( s != size )
throw IOBadParam();
}
*/
/// Получение байта из указанного порта
int in(int port) const
{
char input;
//get(port, &input, 1);
input = inb( port );
return input;
}
/*! Запись значений в диапазон портов от port до port+size байт.
Значения берутся начиная с адреса buf.
*/
/*
void put(int port, const void* buf, int size) const
{
if ( lseek(fd_port, port, SEEK_SET) == -1 )
throw IOBadParam();
ssize_t s = write(fd_port, buf, size);
if ( s != size )
throw IOBadParam();
}
*/
/// Вывод байта value в порт port
void out(int port, int value) const
{
// char output = value;
//put(port,&output,1);
outb( value, port );
}
private:
/// Дескриптор открытого файла, соотнесённого с портами
int fd_port;
};
#endif
############################################################################
# This file is part of the UniSet library #
############################################################################
# install
ios_include_HEADERS = *.h
#$(shell ls $(top_srcdir)/$(subdir) | grep .h )
ios_includedir = $(includedir)/uniset/IOs
/* This file is part of the UniSet project
* Copyright (c) 2002 Free Software Foundation, Inc.
* Copyright (c) 2002 Pavel Vainerman
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// --------------------------------------------------------------------------
/*! \file
* \brief Интерфейс к объекту сохраняющему список заказчиков и сообщений для InfoServer-а
* \author Pavel Vainerman
*/
// --------------------------------------------------------------------------
#ifndef ISRestorer_H_
#define ISRestorer_H_
// ------------------------------------------------------------------------------------------
#include <string>
#include "UniXML.h"
#include "InfoServer.h"
#include "Restorer.h"
// ------------------------------------------------------------------------------------------
/*!
Это абстрактный интерфейс. В чистом виде не используется.
*/
class ISRestorer
{
public:
ISRestorer();
virtual ~ISRestorer();
virtual void read(InfoServer* is, const std::string fname="")=0;
virtual void dump(InfoServer* is, const UniSetTypes::MessageCode code,
const InfoServer::ConsumerList& lst)=0;
protected:
// добавление списка заказчиков
void addlist( InfoServer* is, const UniSetTypes::MessageCode code,
InfoServer::ConsumerList& lst );
};
// ------------------------------------------------------------------------------------------
#if 0
/*!
* \brief Реализация сохранения списка заказчиков в xml.
* \author Pavel Vainerman
*
Реализует сохранение списка заказчиков в xml-файле.
\sa ISRestorer
*/
class ISRestorer_XML:
public ISRestorer,
public Restorer_XML
{
public:
ISRestorer_XML(const std::string fname, bool createIfNotFound=false );
// ISRestorer_XML( UniXML& xml );
virtual ~ISRestorer_XML();
virtual void dump(InfoServer* is, const UniSetTypes::MessageCode code,
const InfoServer::ConsumerList& lst);
virtual void read(InfoServer* is, const std::string fname="");
virtual void read(InfoServer* is, UniXML& xml );
void setFileName(const std::string& file);
inline std::string getFileName(){ return fname; }
ISRestorer_XML();
protected:
virtual void read_list(UniXML& xml, xmlNode* node, InfoServer* is);
};
// ------------------------------------------------------------------------------------------
#endif
/*!
* \brief Реализация сохранения списка заказчиков в xml(работа с файлом проекта)
* \author Pavel Vainerman
*
Реализует сохранение списка заказчиков в xml-файле (версия для работы с файлом проекта).
\sa ISRestorer
*/
class ISRestorer_XML:
public ISRestorer,
public Restorer_XML
{
public:
ISRestorer_XML( const std::string fname );
// ISRestorer_XML( UniXML& xml );
virtual ~ISRestorer_XML();
virtual void dump(InfoServer* is, const UniSetTypes::MessageCode code,
const InfoServer::ConsumerList& lst);
virtual void read(InfoServer* is, const std::string fname="");
virtual void read(InfoServer* is, UniXML& xml );
void setFileName(const std::string& file);
inline std::string getFileName(){ return fname; }
protected:
void read_list(UniXML& xml, xmlNode* node, InfoServer* is);
void create_new_file(const std::string& fname);
xmlNode* bind_node(UniXML& xml, xmlNode* root, const std::string& nodename, const std::string nm="");
xmlNode* rebind_node(UniXML& xml, xmlNode* root, const std::string& nodename, const std::string nm="");
void init( std::string fname );
std::string fname;
UniXML uxml;
};
// ------------------------------------------------------------------------------------------
#endif
/* This file is part of the UniSet project
* Copyright (c) 2002 Free Software Foundation, Inc.
* Copyright (c) 2002 Pavel Vainerman
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// --------------------------------------------------------------------------
/*! \file
* \author Pavel Vainerman
*/
// --------------------------------------------------------------------------
#ifndef InfoServer_H_
#define InfoServer_H_
//---------------------------------------------------------------------------
#include <map>
#include <list>
#include "MessageType.h"
#include "UniSetObject.h"
#include "InfoServer_i.hh"
//---------------------------------------------------------------------------
class ISRestorer;
//---------------------------------------------------------------------------
/*!
\page ServicesPage
\section secInfoServer Сервис сообщений
\subsection subIS_common Общие сведения
В его задачи входит обработка всех сообщений для оператора.
При приходе сообщения он производит следующие действия:
- переправляет сообщение в БД (\ref secDBServer)
- рассылает сообщение на все узлы, если оно помечено как broadcast.
- рассылает сообщение всем занесённым в RouteList(см. конф.файл).
- обрабатывает сообщение специфичным для каждого проекта образом (т.е. вызывает виртуальную
функцию InfoServer::processing() )
\subsection subIS_idea Сценарий работы
На узле, где ведётся БД запускается один экземпляр сервиса. Клиенты могут получить доступ, несколькими способами:
- через NameService
- при помощи UniversalInterface::send()
\par
Сервис является системным, поэтому его идентификатор можно получить при помощи
UniSetTypes::Configuration::getInfoServer() объекта UniSetTypes::conf.
\subsection subIS_interface Интерфейс
InfoServer позволяет заказывать уведомелние о приходе тех или иных сообщений,
а также подтверждения(квитирования). Можно производить заказ сообщения по коду
\code
InfoServer::ackMessage(UniSetTypes::MessageCode msgid, const UniSetTypes::ConsumerInfo& ci,
UniversalIO::UIOCommand cmd, CORBA::Boolean acknotify);
\endcode
или сразу из диапазона кодов
\code
InfoServer::ackMessageRange(UniSetTypes::MessageCode from, UniSetTypes::MessageCode to,
const UniSetTypes::ConsumerInfo& ci,
UniversalIO::UIOCommand cmd, CORBA::Boolean acknotify);
\endcode
Реализацию см. \ref InfoServer
*/
/*!
* \class InfoServer
* \brief Интерфейс для вывода информации
*/
class InfoServer:
public UniSetObject,
public POA_InfoServer_i
{
public:
InfoServer( UniSetTypes::ObjectId id=UniSetTypes::DefaultObjectId, ISRestorer* d=0 );
virtual ~InfoServer();
virtual UniSetTypes::ObjectType getType(){ return UniSetTypes::getObjectType("InfoServer"); }
// реализация IDL интерфейса
/*! заказ уведомления о приходе сообщения */
virtual void ackMessage(UniSetTypes::MessageCode msgid, const UniSetTypes::ConsumerInfo& ci,
UniversalIO::UIOCommand cmd, CORBA::Boolean acknotify);
/*! заказ уведомления о приходе сообщения из диапазона */
virtual void ackMessageRange(UniSetTypes::MessageCode from, UniSetTypes::MessageCode to,
const UniSetTypes::ConsumerInfo& ci,
UniversalIO::UIOCommand cmd, CORBA::Boolean acknotify);
/*! информация о потребителе (заказчике) */
struct ConsumerInfoExt:
public UniSetTypes::ConsumerInfo
{
ConsumerInfoExt( UniSetTypes::ConsumerInfo ci,
UniSetObject_i_ptr ref=0):
ConsumerInfo(ci),ref(ref){}
UniSetObject_i_ptr ref;
CORBA::Boolean ask;
};
/*! Список потребителей */
typedef std::list<ConsumerInfoExt> ConsumerList;
/*! массив пар идентификатор->список потребителей */
typedef std::map<UniSetTypes::MessageCode,ConsumerList> AskMap;
protected:
// Функции обработки пришедших сообщений
virtual void processingMessage( UniSetTypes::VoidMessage *msg );
/*! Функция обработки UniSetTypes::AlarmMessage.
Переопределяется в кокретном проекте, если требуется специфичная обработка. */
virtual void processing(UniSetTypes::AlarmMessage &amsg){};
/*! Функция обработки UniSetTypes::InfoMessage.
Переопределяется в кокретном проекте, если требуется специфичная обработка. */
virtual void processing(UniSetTypes::InfoMessage &imsg){};
/*! Функция обработки UniSetTypes::AckMessage.
Переопределяется в кокретном проекте, если требуется специфичная обработка. */
virtual void processing(UniSetTypes::ConfirmMessage &cmsg){};
/*! Предварительная обработка сообщения. Пересылка на другие узлы и
сохранение в базе.
*/
void preprocessing( UniSetTypes::TransportMessage& tmsg, bool broadcast );
void preprocessingConfirm( UniSetTypes::ConfirmMessage& am, bool broadcast );
virtual bool activateObject();
/*! сохранение списка заказчиков
По умолчанию делает dump, если объявлен dumper.
*/
virtual void dumpOrdersList(UniSetTypes::MessageCode mid, const ConsumerList& lst);
/*! чтение dump-файла */
virtual void readDump();
//! посылка информации об приходе сообщения
template<class TMessage>
void event(UniSetTypes::MessageCode key, TMessage& msg, CORBA::Boolean askn);
//----------------------
//! посылка информации об изменении состояния датчика
template <class TMessage>
void send(ConsumerList& lst, TMessage& msg, CORBA::Boolean acknotify);
bool addConsumer(ConsumerList& lst, const UniSetTypes::ConsumerInfo& cons, CORBA::Boolean acknotify); //!< добавить потребителя сообщения
bool removeConsumer(ConsumerList& lst, const UniSetTypes::ConsumerInfo& cons, CORBA::Boolean acknotify); //!< удалить потребителя сообщения
//! обработка заказа
void ask(AskMap& askLst, UniSetTypes::MessageCode key,
const UniSetTypes::ConsumerInfo& cons, UniversalIO::UIOCommand cmd,
CORBA::Boolean acknotify);
/*! указатель на объект реализующий дамп списка заказчиков */
ISRestorer* restorer;
private:
friend class ISRestorer;
bool dbrepeat; /*!< флаг пересылки сообщений DBServer-у */
AskMap askList; /*!< список потребителей */
/*! замок для блокирования совместного доступа к cписку потребителей */
UniSetTypes::uniset_mutex askMutex;
std::list<UniSetTypes::ConsumerInfo> routeList;
};
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
/* This file is part of the UniSet project
* Copyright (c) 2002 Free Software Foundation, Inc.
* Copyright (c) 2002 Pavel Vainerman
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// --------------------------------------------------------------------------
/*! \file
* \brief Класс работы с сообщениями
* \author Pavel Vainerman
*
* Получение сообщения по id
*/
// --------------------------------------------------------------------------
#ifndef __MESSAGEINTERFACE_H__
#define __MESSAGEINTERFACE_H__
// --------------------------------------------------------------------------
#include <string>
#include "UniSetTypes.h"
// --------------------------------------------------------------------------
class MessageInterface
{
public:
virtual ~MessageInterface(){}
virtual std::string getMessage( UniSetTypes::MessageCode code )=0;
virtual bool isExist(UniSetTypes::MessageCode code)=0;
virtual UniSetTypes::MessageCode getCode( const std::string& msg ){ return UniSetTypes::DefaultMessageCode; }
virtual UniSetTypes::MessageCode getCodeByIdName( const std::string& name ){ return UniSetTypes::DefaultMessageCode; }
virtual std::ostream& printMessagesMap(std::ostream& os)=0;
};
// --------------------------------------------------------------------------
#endif
/* This file is part of the UniSet project
* Copyright (c) 2002 Free Software Foundation, Inc.
* Copyright (c) 2002 Pavel Vainerman
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// --------------------------------------------------------------------------
/*! \file
* \brief Реализация интерфейса работы с сообщениями на основе XML
* \author Pavel Vainerman
*/
// --------------------------------------------------------------------------
#ifndef __MESSAGEINTERFACE_XML_H__
#define __MESSAGEINTERFACE_XML_H__
// --------------------------------------------------------------------------
#include <vector>
#include "UniXML.h"
#include "MessageInterface.h"
// --------------------------------------------------------------------------
class MessageInterface_XML:
public MessageInterface
{
public:
MessageInterface_XML(const std::string confile="", int msize=200);
MessageInterface_XML(UniXML& xml, int msize=200);
virtual ~MessageInterface_XML();
virtual std::string getMessage( UniSetTypes::MessageCode code );
virtual bool isExist(UniSetTypes::MessageCode code);
virtual UniSetTypes::MessageCode getCode( const std::string& msg );
virtual UniSetTypes::MessageCode getCodeByIdName( const std::string& name );
virtual std::ostream& printMessagesMap(std::ostream& os);
friend std::ostream& operator<<(std::ostream& os, MessageInterface_XML& mi );
protected:
void read( UniXML& xml );
std::vector<UniSetTypes::MessageInfo> msgmap;
};
// --------------------------------------------------------------------------
#endif
/*! \file
* \brief Класс работы с сообщениями
* \author Pavel Vainerman
*/
/**************************************************************************/
#ifndef MessageInterface_idXML_H_
#define MessageInterface_idXML_H_
// -----------------------------------------------------------------------------------------
#include <map>
#include <string>
#include "UniSetTypes.h"
#include "MessageInterface.h"
#include "UniXML.h"
// -----------------------------------------------------------------------------------------
class MessageInterface_idXML:
public MessageInterface
{
public:
MessageInterface_idXML( const std::string xmlfile );
MessageInterface_idXML( UniXML& xml );
virtual ~MessageInterface_idXML();
virtual std::string getMessage( UniSetTypes::MessageCode code );
virtual bool isExist( UniSetTypes::MessageCode code );
virtual UniSetTypes::MessageCode getCode( const std::string& msg );
virtual UniSetTypes::MessageCode getCodeByIdName( const std::string& name );
virtual std::ostream& printMessagesMap(std::ostream& os);
friend std::ostream& operator<<(std::ostream& os, MessageInterface_idXML& mi );
protected:
void build( UniXML& xml );
private:
typedef std::map<UniSetTypes::MessageCode, UniSetTypes::MessageInfo> MapMessageKey;
MapMessageKey mmk;
};
// -----------------------------------------------------------------------------------------
#endif
/* This file is part of the UniSet project
* Copyright (c) 2002 Free Software Foundation, Inc.
* Copyright (c) 2002 Pavel Vainerman
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// --------------------------------------------------------------------------
/*! \file
* \brief Активатор объектов
* \author Pavel Vainerman
*/
// --------------------------------------------------------------------------
#ifndef ObjectsActivator_H_
#define ObjectsActivator_H_
// --------------------------------------------------------------------------
#include <omniORB4/CORBA.h>
#include "UniSetTypes.h"
#include "UniSetObject.h"
#include "ObjectsManager.h"
#include "ThreadCreator.h"
//#include "OmniThreadCreator.h"
//----------------------------------------------------------------------------------------
/*! \class ObjectsActivator
* Создает POA менеджер и регистрирует в нем объекты.
* Для обработки CORBA-запросов создается поток или передаются ресурсы
* главного потока см. void activate(bool thread)
*
* Активатор в свою очередь сам является менеджером(и объектом) и обладает всеми его свойствами
*
* \todo Разобраться со всякими oaDestroy, stop, oakill и сделать одну надежную завершающую функцию.
*/
class ObjectsActivator:
public ObjectsManager
{
public:
ObjectsActivator();
ObjectsActivator( UniSetTypes::ObjectId id );
virtual ~ObjectsActivator();
virtual void run(bool thread);
virtual void stop();
virtual void oaDestroy(int signo=0);
void waitDestroy();
inline void oakill(int signo){ raise(signo);}
virtual UniSetTypes::ObjectType getType(){ return UniSetTypes::getObjectType("ObjectsActivator"); }
protected:
/*! Команды доступные при заказе сигналов
* см. askSignal()
*/
enum AskSigCommand {
Ask, /*!< заказать получение сигнала */
Denial /*!< отказаться от получения сигнала */
};
/*! заказ на обработку сигнала signo
* Для обработки предназначена функция signal().
* \warning Сообщение о приходе сигналов SITERM, SIGINT, SIGABRT приходит
* вне зависимости от заказа. От этих сообщений нельзя отказаться...
* \warning Заказ других сигналов пока не работает..
* \warning функция временно недоступна (private). Ведуться работы...
* \todo сделать возможность заказа других сигналов
*/
// void askSignal(int signo, AskSigCommand cmd=Ask);
virtual void work();
inline CORBA::ORB_ptr getORB()
{
return orb;
}
virtual void processingMessage( UniSetTypes::VoidMessage *msg );
virtual void sysCommand( UniSetTypes::SystemMessage *sm );
private:
// static void processingSignal(int signo);
static void terminated(int signo);
static void finishterm(int signo);
static void normalexit();
static void normalterminate();
static void set_signals(bool ask);
void term( int signo );
void init();
friend class ThreadCreator<ObjectsActivator>;
ThreadCreator<ObjectsActivator> *orbthr;
CORBA::ORB_var orb;
bool omDestroy;
bool sig;
pid_t thpid; // pid orb потока
struct Info
{
pid_t msgpid; // pid порожденого потока обработки сообщений
};
struct OInfo:
public Info
{
UniSetObject* obj;
};
struct MInfo:
public Info
{
ObjectsManager* mnr;
};
std::list<OInfo> lstOInfo;
std::list<MInfo> lstMInfo;
void getinfo();
};
/*
template<class TClass>
int ObjectsActivator::attach(TClass* p, void(TClass:: *f)(void*) )
{
if( next >= MAX_CHILD_THREAD )
return -1;
callpull[next] = new OmniThreadCreator<TClass>( p, f);
next++;
return 0;
}
*/
#endif
/* This file is part of the UniSet project
* Copyright (c) 2002 Free Software Foundation, Inc.
* Copyright (c) 2002 Pavel Vainerman
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// --------------------------------------------------------------------------
/*! \file
* \brief Реализация интерфейса менеджера объектов.
* \author Pavel Vainerman
*/
// --------------------------------------------------------------------------
#ifndef ObjectsManager_H_
#define ObjectsManager_H_
// --------------------------------------------------------------------------
#include <omniORB4/CORBA.h>
#include "UniSetTypes.h"
#include "UniSetObject.h"
#include "ObjectsManager_i.hh"
//---------------------------------------------------------------------------
class ObjectsActivator;
class ObjectsManager;
typedef std::list<ObjectsManager*> ObjectsManagerList;
//---------------------------------------------------------------------------
/*! \class ObjectsManager
* \par
* Содержит в себе функции управления объектами. Их регистрации и т.п.
* Создается менеджер объектов, после чего вызывается initObjects()
* для инициализации объектов которыми управляет
* данный менеджер...
* Менеджер в свою очередь сам является объектом и обладает всеми его свойствами
*
* Для пересылки сообщения всем подчиненным объектам используется
* функция ObjectsManager::broadcast(const TransportMessage& msg)
* \par
* У базового менеджера имеются базовые три функции см. ObjectsManager_i.
* \note Только при вызове функции ObjectsManager::broadcast() происходит
* формирование сообщения всем подчиненным объектам... Если команда проиходит
* при помощи push, то пересылки всем починённым объектам не происходит...
*
*
*/
class ObjectsManager:
public UniSetObject,
public POA_ObjectsManager_i
{
public:
ObjectsManager( UniSetTypes::ObjectId id);
ObjectsManager( const std::string name, const std::string section );
virtual ~ObjectsManager();
virtual UniSetTypes::ObjectType getType(){ return UniSetTypes::getObjectType("ObjectsManager"); }
// ------ функции объявленные в интерфейсе(IDL) ------
virtual void broadcast(const UniSetTypes::TransportMessage& msg);
virtual UniSetTypes::SimpleInfoSeq* getObjectsInfo( CORBA::Long MaxLength=300 );
// --------------------------
void initPOA(ObjectsManager* rmngr);
virtual bool addObject(UniSetObject *obj);
virtual bool removeObject(UniSetObject *obj);
virtual bool addManager( ObjectsManager *mngr );
virtual bool removeManager( ObjectsManager *mngr );
/*! Получение доступа к подчиненному менеджеру по идентификатору
* \return объект ненайден будет возвращен 0.
*/
const ObjectsManager* itemM(const UniSetTypes::ObjectId id);
/*! Получение доступа к подчиненному объекту по идентификатору
* \return объект ненайден будет возвращен 0.
*/
const UniSetObject* itemO( const UniSetTypes::ObjectId id );
// Функции для аботы со списками подчиненных объектов
inline ObjectsManagerList::const_iterator beginMList()
{
return mlist.begin();
}
inline ObjectsManagerList::const_iterator endMList()
{
return mlist.end();
}
inline ObjectsList::const_iterator beginOList()
{
return olist.begin();
}
inline ObjectsList::const_iterator endOList()
{
return olist.end();
}
int objectsCount(); // количество подчиненных объектов
PortableServer::POA_ptr getPOA(){ return PortableServer::POA::_duplicate(poa); }
PortableServer::POAManager_ptr getPOAManager(){ return PortableServer::POAManager::_duplicate(pman); }
protected:
ObjectsManager();
enum OManagerCommand{deactiv, activ, initial, term};
// работа со списком объектов
void objects(OManagerCommand cmd);
// работа со списком менеджеров
void managers(OManagerCommand cmd);
virtual void sigterm( int signo );
//! \note Переопределяя не забывайте вызвать базовую
virtual bool activateObject();
//! \note Переопределяя не забывайте вызвать базовую
virtual bool disactivateObject();
typedef ObjectsManagerList::iterator MListIterator;
int getObjectsInfo( ObjectsManager* mngr, UniSetTypes::SimpleInfoSeq* seq,
int begin, const long uplimit );
PortableServer::POA_var poa;
PortableServer::POAManager_var pman;
private:
friend class ObjectsActivator;
int sig;
ObjectsManagerList mlist;
ObjectsList olist;
UniSetTypes::uniset_mutex olistMutex;
UniSetTypes::uniset_mutex mlistMutex;
};
#endif
/* This file is part of the UniSet project
* Copyright (c) 2002 Free Software Foundation, Inc.
* Copyright (c) 2002 Pavel Vainerman
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// --------------------------------------------------------------------------
/*! \file
* \author Pavel Vainerman
*/
//---------------------------------------------------------------------------
#ifndef ObjectsManager_LT_H_
#define ObjectsManager_LT_H_
//--------------------------------------------------------------------------
#include "UniSetTypes.h"
#include "ObjectsManager.h"
#include "LT_Object.h"
//---------------------------------------------------------------------------
/*!
Реализация базового класса с использованием локальных таймеров
*/
class ObjectsManager_LT:
public ObjectsManager
{
public:
ObjectsManager_LT( UniSetTypes::ObjectId id );
ObjectsManager_LT();
virtual ~ObjectsManager_LT();
protected:
/*! заказ локального таймера
\param timerid - идентификатор таймера
\param timeMS - период. 0 - означает отказ от таймера
\param ticks - количество уведомлений. "-1"- постоянно
\return Возвращает время [мсек] оставшееся до срабатывания
очередного таймера
*/
void askTimer( UniSetTypes::TimerId timerid, timeout_t timeMS, short ticks=-1,
UniSetTypes::Message::Priority p=UniSetTypes::Message::High );
/*! функция вызываемая из потока */
virtual void callback();
int sleepTime;
LT_Object lt;
private:
};
//--------------------------------------------------------------------------
#endif
/* This file is part of the UniSet project
* Copyright (c) 2002 Free Software Foundation, Inc.
* Copyright (c) 2002 Pavel Vainerman
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// --------------------------------------------------------------------------
/*! \file
* \brief Интефес для создания и управления потоками
* \author Anthony Korbin
*/
//----------------------------------------------------------------------------
#ifndef PosixThread_h_
#define PosixThread_h_
//----------------------------------------------------------------------------------------
#include <pthread.h>
#include <iostream>
#include <signal.h>
//----------------------------------------------------------------------------------------
/*! \class PosixThread */
class PosixThread
{
public:
PosixThread();
virtual ~PosixThread();
void start( void *args ); /*!< запуск */
void stop();
void thrkill( int signo ); /*!< послать сигнал signo */
enum TAttr{ SCOPE, DETACH, PRIORITY };
void setAttr( TAttr Attr, int state );
pthread_t getTID(){ return tid; }
void setPriority( int priority );
static void* funcp( void * test );
protected:
void reinit();
virtual void work() = 0; /*!< Функция выполняемая в потоке */
void readlock( pthread_rwlock_t *lock = &lockx );
void writelock( pthread_rwlock_t *lock = &lockx );
void lock( pthread_mutex_t *mute = &mutex );
void unlock( pthread_mutex_t *mute = &mutex );
void rwunlock( pthread_rwlock_t *lock = &lockx );
void wait( pthread_cond_t *cond = &condx, pthread_mutex_t *mute = &mutex );
void continueRun( pthread_cond_t *cond = &condx );
void continueRunAll( pthread_cond_t *cond = &condx );
private:
pthread_t tid;
pthread_attr_t *attrPtr;
static pthread_rwlock_t lockx;
static pthread_mutex_t mutex;
static pthread_cond_t condx;
static int countThreads;
};
#endif // PosixThread_h_
/* This file is part of the UniSet project
* Copyright (c) 2002 Free Software Foundation, Inc.
* Copyright (c) 2002 Pavel Vainerman
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// --------------------------------------------------------------------------
// idea: lav@etersoft.ru
// realisation: pv@etersoft.ru, lav@etersoft.ru
// --------------------------------------------------------------------------
#ifndef SandClock_H_
#define SandClock_H_
// --------------------------------------------------------------------------
/*! WARNING! This class is DEPRECATED! Use HourGlass.. */
// --------------------------------------------------------------------------
#include "PassiveTimer.h"
// --------------------------------------------------------------------------
/*! WARNING! This class is DEPRECATED! Use HourGlass.. */
class SandClock
{
public:
SandClock(): _state(false),_sand(0),_size(0){}
~SandClock(){}
// запустить часы (заново)
inline void run( int msec )
{
t.setTiming(msec);
_state = true;
_sand = msec;
_size = msec;
}
inline void reset ()
{
run(_size);
}
inline int duration()
{
return _size;
}
// перевернуть часы
// true - засечь время
// false - перевернуть часы (обратный ход)
// возвращает аргумент (т.е. идёт ли отсчёт времени)
inline bool rotate( bool st )
{
if( st == _state )
return st;
_state = st;
if( !_state )
{
int cur = t.getCurrent();
_sand -= cur;
if( _sand < 0 )
_sand = 0;
// std::cout << "перевернули: прошло " << cur
// << " осталось " << sand
// << " засекаем " << cur << endl;
t.setTiming(cur);
}
else
{
_sand += t.getCurrent();
if( _sand > _size )
_sand = _size;
// std::cout << "вернули: прошло " << t.getCurrent()
// << " осталось " << sand
// << " засекам " << sand << endl;
t.setTiming(_sand);
}
return st;
}
// получить прошедшее время
// для положения st
inline int current( bool st )
{
return t.getCurrent();
}
// получить заданное время
// для положения st
inline int interval( bool st )
{
return t.getInterval();
}
// проверить наступление
inline bool check()
{
// пока часы не "стоят"
// всегда false
if( !_state )
return false;
return t.checkTime();
}
inline bool state(){ return _state; }
protected:
PassiveTimer t;
bool _state;
int _sand;
int _size;
};
// --------------------------------------------------------------------------
#endif
// --------------------------------------------------------------------------
/* This file is part of the UniSet project
* Copyright (c) 2002 Free Software Foundation, Inc.
* Copyright (c) 2002 Pavel Vainerman
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// --------------------------------------------------------------------------
/*! \file
* \author Pavel Vainerman
*/
// --------------------------------------------------------------------------
#ifndef StorageInterface_H_
#define StorageInterface_H_
// ---------------------------------------------------------------------------
#include "IOController_i.hh"
// ---------------------------------------------------------------------------
/*! */
class StorageInterface
{
public:
StorageInterface(){};
virtual ~StorageInterface(){};
virtual IOController_i::DigitalIOInfo find( const IOController_i::SensorInfo& si )=0;
virtual void push( IOController_i::DigitalIOInfo& di )=0;
virtual void remove(const IOController_i::SensorInfo& si)=0;
virtual bool getState(const IOController_i::SensorInfo& si)=0;
virtual long getValue(const IOController_i::SensorInfo& si)=0;
virtual void saveState(const IOController_i::DigitalIOInfo& di,bool st)=0;
virtual void saveValue(const IOController_i::AnalogIOInfo& ai, long val)=0;
protected:
private:
};
// ---------------------------------------------------------------------------
class STLStorage:
public StorageInterface
{
public:
STLStorage();
~STLStorage();
virtual IOController_i::DigitalIOInfo find( const IOController_i::SensorInfo& si );
virtual void push( IOController_i::DigitalIOInfo& di );
virtual void remove(const IOController_i::SensorInfo& si);
virtual bool getState(const IOController_i::SensorInfo& si);
virtual long getValue(const IOController_i::SensorInfo& si);
virtual void saveState(const IOController_i::DigitalIOInfo& di,bool st);
virtual void saveValue(const IOController_i::AnalogIOInfo& ai, long val);
protected:
private:
};
// ---------------------------------------------------------------------------
#endif
// ---------------------------------------------------------------------------
/* This file is part of the UniSet project
* Copyright (c) 2009 Free Software Foundation, Inc.
* Copyright (c) 2009 Ivan Donchevskiy
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// --------------------------------------------------------------------------
/*! \file
* \author Ivan Donchevskiy
*/
// --------------------------------------------------------------------------
#ifndef Storages_H_
#define Storages_H_
#include <stdio.h>
#include <stdlib.h>
#include <cstring>
#include <string>
/*! Эти 2 значения используются в TableBlockStorage как флаги для поля count, чтобы не вводить лишнее поле
в структуре TableBlockStorageElem */
#define EMPTY_BLOCK -5
#define EMPTY_ELEM -1
#define key_size 20
/*! Заголовок таблицы с элементами класса TableBlockStorage */
struct StorageAttr
{
int k_size, inf_size,size,block_number;
int lim, seekpos;
} __attribute__((__packed__));
/*! Заголовок журнала с элементами класса CycleStorage */
struct CycleStorageAttr
{
int size, inf_size, seekpos;
} __attribute__((__packed__));
/*! Основная структура класса TableStorage */
struct TableStorageElem
{
char status;
char key[key_size];
} __attribute__((__packed__));
/*! Основная структура класса TableBlockStorage */
struct TableBlockStorageElem
{
int count;
} __attribute__((__packed__));
/*! Основная структура класса CycleStorage */
struct CycleStorageElem
{
char status;
} __attribute__((__packed__));
class TableStorage
{
FILE *file;
int size,seekpos, inf_size;
int head;
public:
TableStorage(const char* name, int inf_sz, int sz, int seek);
~TableStorage();
int addRow(char* key, char* val);
int delRow(char* key);
char* findKeyValue(char* key, char* val);
};
class TableBlockStorage
{
public:
/*! Конструктор по умолчанию не открывает и не создает новой таблицы */
TableBlockStorage();
/*! Конструктор вызывает функцию Open, а при параметре create=true создает новую таблицу при
несовпадении заголовков или отсутствии старой */
TableBlockStorage(const char* name, int byte_sz, int key_sz, int inf_sz, int inf_count, int block_num, int block_lim, int seek, bool create=false);
~TableBlockStorage();
/*!
\param inf_sz - размер поля информации,
\param key_sz - размер поля ключа,
\param inf_count - кол-во записей в одном блоке таблицы (размером inf_sz+key_sz
+sizeof(int) на ключевое поле)
\param block_num - кол-во блоков (при этом кол-во записей во всей таблице = inf_count*block_num,
\param block_lim - число перезаписей на блок,
\param seek - отступ от начала файла (указывает место, где расположена таблица)
размер всей таблицы будет равен inf_count*block_num*(inf_sz+key_sz+sizeof(int)) +
sizeof(StorageAttr), где последнее слагаемое - размер заголовка,
размер можно получить, вызвав функцию getByteSize()
*/
bool open(const char* name, int byte_sz, int inf_sz, int key_sz, int inf_count, int block_num, int block_lim, int seek);
bool create(const char* name, int byte_sz, int inf_sz, int key_sz, int inf_count, int block_num, int block_lim, int seek);
/*! Добавление информации по ключу, возможна перезапись при совпадении ключа с существующим */
bool addRow(void* key, void* val);
/*! Удаление информации по ключу, фактически освобождения места не происходит, оно только помечается удаленным*/
bool delRow(void* key);
/*! Поиск информации по ключу, при неудаче возвращается 0 */
void* findKeyValue(void* key, void* val);
/*! Получение текущего блока (для тестовой программы) */
int getCurBlock(void);
inline int getByteSize() { return (size*full_size + sizeof(StorageAttr)); }
bool checkAttr( int key_sz, int inf_sz, int sz, int block_num, int block_lim, int seek );
protected:
FILE *file;
int inf_size;
private:
int max,cur_block;
TableBlockStorageElem* mem;
int k_size, lim,seekpos;
int size,block_size,block_number,full_size;
void filewrite(int seek, bool needflush=true);
bool copyToNextBlock();
bool keyCompare(int i, void* key);
void* keyPointer(int num);
void* valPointer(int num);
TableBlockStorageElem* elemPointer(int num);
};
class CycleStorage
{
public:
class CycleStorageIterator
{
public:
typedef CycleStorageIterator Self;
CycleStorageIterator():
str(NULL), cs(NULL), current(0) {}
CycleStorageIterator(CycleStorage* cstor)
{
cs = cstor;
current = 0;
}
CycleStorageIterator(CycleStorage* cstor, int num)
{
cs = cstor;
if( num<0 || num>=cs->getSize() ) current = 0;
current = num;
}
void* operator *() const
{
return str;
}
Self& operator++();
Self operator++(int);
Self& operator--();
Self operator--(int);
inline bool operator==(const Self& other) const
{
if( str==NULL || other.str==NULL )
{
if( str==NULL && other.str==NULL )
return true;
else
return false;
}
if( memcmp(str, other.str, cs->getInfSize())==0 )
return true;
return false;
}
inline bool operator!=(const Self& other) const
{
if( str==NULL || other.str==NULL )
{
if( str==NULL && other.str==NULL )
return false;
else
return true;
}
if( memcmp(str, other.str, cs->getInfSize())==0 )
return false;
return true;
}
private:
void* str;
CycleStorage* cs;
int current;
};
typedef CycleStorageIterator iterator;
/*! Конструктор по умолчанию не открывает и не создает нового журнала */
CycleStorage();
/*! Конструктор вызывает функцию Open, а при параметре create=true создает новый журнал при
несовпадении заголовков или отсутствии старого */
CycleStorage(const char* name, int byte_sz, int inf_sz, int inf_count, int seek,bool create=false);
~CycleStorage();
/*!
\param inf_sz - размер поля информации,
\param inf_count - количество записей (размером inf_sz +1 на ключевое поле)
\param seek - отступ от начала файла (указывает место, где расположен журнал)
размер всего журнала будет равен inf_count*(inf_sz+1) + sizeof(CycleStorageAttr),
где последнее слагаемое - размер заголовка
размер можно получить, вызвав функцию getByteSize()
*/
bool open(const char* name, int byte_sz, int inf_sz, int inf_count, int seek);
bool create(const char* name, int byte_sz, int inf_sz, int inf_count, int seek);
bool isOpen(){ return (file!=NULL); }
/*! Добавление информации в конец журнала */
bool addRow(void* str);
/*! Удаление информации с номером ряда row */
bool delRow(int row);
/*! Очистка журнала */
bool delAllRows(void);
/*! \return Функция возвращает информацию из ряда с номером num */
void* readRow(int num, void* str);
/*! Получение кол-ва итерации при поиске начала/конца журнала (для тестовой программы) */
int getIter(void);
/*! Изменение размера журнала (количества записей в нем) */
bool setSize(int count);
inline int getByteSize() { return (size*full_size + sizeof(CycleStorageAttr)); }
inline int getSize(){ return size; }
inline int getInfSize(){ return inf_size; }
inline int getFullSize(){ return full_size; }
bool checkAttr(int inf_sz, int inf_count, int seek);
inline int getHead(){ return head; }
inline int getTail(){ return tail; }
iterator begin()
{
return iterator(this);
}
iterator end()
{
return iterator(this,this->getTail());
}
protected:
FILE *file;
int inf_size;
int head,tail;
private:
int size,seekpos, iter;
int full_size;
void filewrite(CycleStorageElem* jrn,int seek, bool needflush=true);
void* valPointer(void* pnt);
bool findHead();
};
#endif
/* This file is part of the UniSet project
* Copyright (c) 2002 Free Software Foundation, Inc.
* Copyright (c) 2002 Pavel Vainerman
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//--------------------------------------------------------------------------------
/*! \file
* \brief Реализация SystemGuard
* \author Pavel Vainerman
*/
//--------------------------------------------------------------------------------
#ifndef SystemGuard_H_
#define SystemGuard_H_
//--------------------------------------------------------------------------------
#include <omniORB4/CORBA.h>
#include <omnithread.h>
#include "UniSetTypes.h"
#include "PassiveTimer.h"
#include "ThreadCreator.h"
#include "ObjectsActivator.h"
//--------------------------------------------------------------------------------
/*! \class SystemGuard
* Предназначен для слежения за исправностью работы процессов. А так же отслеживает наличие
* связи c узлами и обновляет эту информацию в ListOfNodes.
*/
class SystemGuard:
public ObjectsActivator
{
public:
SystemGuard(UniSetTypes::ObjectId id);
SystemGuard();
~SystemGuard();
virtual void run( bool thread=false );
virtual void stop();
virtual void oaDestroy(int signo=0);
virtual UniSetTypes::SimpleInfo* getInfo();
virtual UniSetTypes::ObjectType getType(){ return UniSetTypes::getObjectType("SystemGuard"); }
protected:
void execute();
virtual void sigterm( int signo );
virtual bool pingNode();
virtual void updateNodeInfo(const UniSetTypes::NodeInfo& newinf){};
virtual void watchDogTime();
virtual void dumpStateInfo();
virtual void autostart();
private:
void init();
// ObjectsActivator* act;
// CORBA::ORB_var orb;
PassiveTimer wdogt;
PassiveTimer rit;
PassiveTimer dumpt;
// PassiveTimer strt;
friend class ThreadCreator<SystemGuard>;
ThreadCreator<SystemGuard> *thr;
bool active;
int expid;
// omni_mutex omutex;
// omni_condition ocond;
UniSetTypes::uniset_mutex actMutex;
};
//--------------------------------------------------------------------------------
#endif
/* This file is part of the UniSet project
* Copyright (c) 2002 Free Software Foundation, Inc.
* Copyright (c) 2002 Vitaly Lipatov
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*! \file
* \author Vitaly Lipatov
* \par
* Базовый класс получения строки по её индексу
*/
#include <string>
class TextDBIndex
{
public:
virtual ~TextDBIndex(){}
// Получить строку по коду
virtual std::string getText(int id){ return ""; }
};
/* This file is part of the UniSet project
* Copyright (c) 2002 Free Software Foundation, Inc.
* Copyright (c) 2002 Vitaly Lipatov
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*! \file
* \author Vitaly Lipatov
* \par
* Базовый класс получения строки по её индексу
*/
#include <string>
class TextIndex
{
public:
virtual ~TextIndex(){}
// Получить строку по коду
virtual std::string getText(int id)=0;
};
/* This file is part of the UniSet project
* Copyright (c) 2002 Free Software Foundation, Inc.
* Copyright (c) 2002 Pavel Vainerman
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// --------------------------------------------------------------------------
/*! \file
* \brief Реализация TimerService
* \author Pavel Vainerman
*/
//---------------------------------------------------------------------------
#ifndef TimerService_H_
#define TimerService_H_
//---------------------------------------------------------------------------
#include <list>
#include <functional>
#include <omnithread.h>
#include <string>
#include "UniSetTypes.h"
#include "UniSetObject.h"
#include "TimerService_i.hh"
#include "PassiveTimer.h"
//#include "OmniThreadCreator.h"
#include "ThreadCreator.h"
//-----------------------------------------------------------------------------------
/*!
\page ServicesPage
\section secTimerService Сервис таймеров
\subsection subTS_common Общие сведения
Данный сервис предоставляет возможность заказа переодических сообщений
UniSetTypes::TimerMessage т.е. таймеров.
Каждый заказчик может заказывать несколько таймеров, различающихся идентификаторами. При этом
идентификаторы определяет сам заказчик. Они должны быть уникальны только для одного заказчика.
\note
Сервис не гарантирует реальное время и точное соблюдение интервала. Т.к. к указанному в заказе времени
добавляется время на обработку и посылку сообщения, но при достаточных системных ресурсах точность увеличивается.
\subsection subTS_idea Сценарий работы
На узле запускается один экземпляр сервиса. Клиенты могут получить доступ, несколькими способами:
- через NameService
- при помощи UniversalInterface::askTimer()
\par
Сервис является системным, поэтому его идентификатор можно получить при помощи
UniSetTypes::Configuration::getTimerService() объекта UniSetTypes::conf.
\subsection subTS_interface Интерфейс
Сервис предоставляет одну функцию
\code
void TimerService::askTimer( CORBA::Short timerid, CORBA::Long timeMS, const UniSetTypes::ConsumerInfo& ci,
CORBA::Short ticks)
\endcode
при помощи которой осуществялется заказ таймера.
\param timerid - уникальный идентификатор таймера
\par
В случае попытки заказать таймер с уже существующим (для данного заказчика) идентификатором вырабатывается
исключение TimerService_i::TimerAlreadyExist.
\param timeMS - период между уведомлениями. Для отказа от таймера необходимо указать timeMS=0.
\param ticks позволяет ограничить количество уведомлений.
\par
Если ticks<0 уведомления будут посылатся, пока заказчик сам не откажется от них.
Общее количество таймеров (\b на \b всех \b заказчиков) ограничено ( TimerService::MaxCountTimers ).
В случае превышения данного предела на все заказы будет вырабатываться исключение TimerService_i::LimitTimers.
Для преодоления этого ограничения, а так же для обеспечения оптимальной работы сервиса, можно запускать на одном
узле несколько TimerService-ов для распределения нагрузки(заказов) между ними. При этом за распределение заказов
отвечает, разработчик.
\subsection subTS_lifetime Время жизни заказа
Для того, чтобы оптимизировать работу сервиса и уменьшить на него нагрузку вводится понятие
"время жизни заказа". В случае, если в течение TimerService::AskLifeTimeSEC не удаётся послать заказчику
уведомление, в следствие его недоступности - заказ анулируется.
\note Параметры можно задавать в конфигурационном файле
Реализацию см. \ref TimerService
*/
/*! \class TimerService
* Построен на основе PassiveTimer.
*/
class TimerService:
public POA_TimerService_i,
public UniSetObject
{
public:
TimerService( UniSetTypes::ObjectId id, const std::string confNodeName="LocalTimerService");
~TimerService();
//! заказ таймера
virtual void askTimer( const TimerService_i::Timer& ti, const UniSetTypes::ConsumerInfo& ci);
void printList();
protected:
TimerService(const std::string confNodeName="LocalTimerService");
/*! Информация о таймере */
struct TimerInfo
{
TimerInfo():id(0), curTimeMS(0){};
TimerInfo(CORBA::Short id, CORBA::Long timeMS, const UniSetTypes::ConsumerInfo& cinf,
CORBA::Short cnt, unsigned int askLifeTime, UniSetTypes::Message::Priority p):
cinf(cinf),
ref(0),
id(id),
curTimeMS(timeMS),
priority(p),
curTick(cnt-1),
not_ping(false)
{
tmr.setTiming(timeMS);
lifetmr.setTiming(askLifeTime*1000); // [сек]
};
inline void reset()
{
curTimeMS = tmr.getInterval();
tmr.reset();
}
UniSetTypes::ConsumerInfo cinf; /*!< инфою о заказчике */
UniSetObject_i_var ref; /*!< ссылка заказчика */
UniSetTypes::TimerId id; /*!< идентификатор таймера */
timeout_t curTimeMS; /*!< остаток времени */
UniSetTypes::Message::Priority priority; /*!< приоритет посылаемого сообщения */
/*!
* текущий такт
* \note Если задано количество -1 то сообщения будут поылатся постоянно
*/
CORBA::Short curTick;
// заказчик с меньшим временем ожидания имеет больший приоритет
bool operator < ( const TimerInfo& ti ) const
{
return curTimeMS > ti.curTimeMS;
}
PassiveTimer tmr;
PassiveTimer lifetmr; /*! таймер жизни заказа в случае если объект не доступен */
bool not_ping; /* признак недоступности заказчика */
};
typedef std::list<TimerInfo> TimersList;
//! посылка сообщения о наступлении времени
virtual bool send(TimerInfo& ti);
//! Дизактивизация объекта (переопределяется для необходимых действий перед деактивацией)
virtual bool disactivateObject();
virtual bool activateObject();
virtual void sigterm( int signo );
unsigned int MaxCountTimers; /*!< максимально возможное количество таймеров */
unsigned int AskLifeTimeSEC; /*!< [сек] время жизни заказа, если объект недоступен */
void init(const std::string& confnode);
void work();
private:
bool terminate;
bool isSleep;
UniSetTimer* sleepTimer; /*!< таймер для реализации засыпания в отсутствие заказов */
class Timer_eq: public std::unary_function<TimerInfo, bool>
{
public:
Timer_eq(const UniSetTypes::ConsumerInfo& coi, CORBA::Short t):tid(t),ci(coi){}
inline bool operator()(const TimerInfo& ti) const
{
return ( ti.cinf.id == ci.id && ti.cinf.node == ci.node && ti.id == tid );
}
protected:
UniSetTypes::TimerId tid;
UniSetTypes::ConsumerInfo ci;
};
TimersList tlst;
/*! замок для блокирования совместного доступа к cписку таймеров */
UniSetTypes::uniset_mutex lstMutex;
int execute_pid;
ThreadCreator<TimerService>* exthread;
};
#endif
/* This file is part of the UniSet project
* Copyright (c) 2002 Free Software Foundation, Inc.
* Copyright (c) 2002 Pavel Vainerman
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// --------------------------------------------------------------------------
/*! \file
* \brief Базовый класс для реализации шаблона "наблюдатель"
* \author Pavel Vainerman
*/
//---------------------------------------------------------------------------
#ifndef UniSetObserver_H_
#define UniSetObserver_H_
//---------------------------------------------------------------------------
#include <list>
#include "UniSetObject.h"
#include "MessageType.h"
// --------------------------------------------------------------------------
class UniSetSubject
{
public:
UniSetSubject(UniSetTypes::ObjectId id);
~UniSetSubject();
virtual void attach( UniSetObject* o );
virtual void detach( UniSetObject* o );
virtual void attach( UniSetObject* o, int MessageType );
virtual void detach( UniSetObject* o, int MessageType );
protected:
UniSetSubject();
virtual void notify(int notify, int data,
UniSetTypes::Message::Priority priority=UniSetTypes::Message::Low);
virtual void notify( UniSetTypes::TransportMessage& msg );
private:
typedef std::list<UniSetObject*> ObserverList;
ObserverList lst;
UniSetTypes::ObjectId id;
};
//---------------------------------------------------------------------------
#endif
#include <ostream>
#include <Exceptions.h>
#include <ORepHelpers.h>
#include <UniversalInterface.h>
#include <Configuration.h>
#include <UniSetTypes.h>
#include "UInterface.h"
//---------------------------------------------------------------------------
using namespace std;
//---------------------------------------------------------------------------
static UniversalInterface* ui=0;
//---------------------------------------------------------------------------
void UInterface::uniset_init_params( UTypes::Params* p, const char* xmlfile )throw(UException)
{
UInterface::uniset_init(p->argc,p->argv,xmlfile);
}
//---------------------------------------------------------------------------
void UInterface::uniset_init( int argc, char* argv[], const char* xmlfile )throw(UException)
{
try
{
UniSetTypes::uniset_init(argc,argv,xmlfile);
ui = new UniversalInterface();
return;
}
catch( UniSetTypes::Exception& ex )
{
throw UException(ex.what());
}
catch( ... )
{
throw UException();
}
}
//---------------------------------------------------------------------------
long UInterface::getValue( long id )throw(UException)
{
if( !UniSetTypes::conf || !ui )
throw USysError();
UniversalIO::IOTypes t = UniSetTypes::conf->getIOType(id);
try
{
switch(t)
{
case UniversalIO::DigitalInput:
case UniversalIO::DigitalOutput:
return (ui->getState(id) ? 1 : 0);
break;
case UniversalIO::AnalogInput:
case UniversalIO::AnalogOutput:
return ui->getValue(id);
break;
default:
{
ostringstream e;
e << "(getValue): Unknown iotype for id=" << id;
throw UException(e.str());
}
}
}
catch( UException& ex )
{
throw;
}
catch( UniSetTypes::Exception& ex )
{
throw UException(ex.what());
}
catch( ... )
{
throw UException("(getValue): catch...");
}
throw UException("(getValue): unknown error");
}
//---------------------------------------------------------------------------
void UInterface::setValue( long id, long val )throw(UException)
{
if( !UniSetTypes::conf || !ui )
throw USysError();
UniversalIO::IOTypes t = UniSetTypes::conf->getIOType(id);
try
{
switch(t)
{
case UniversalIO::DigitalInput:
ui->saveState(id,val,t);
break;
case UniversalIO::DigitalOutput:
ui->setState(id,val);
break;
case UniversalIO::AnalogInput:
ui->saveValue(id,val,t);
break;
case UniversalIO::AnalogOutput:
ui->setValue(id,val);
break;
default:
{
ostringstream e;
e << "(setValue): Unknown iotype for id=" << id;
throw UException(e.str());
}
}
}
catch( UException& ex )
{
throw;
}
catch( UniSetTypes::Exception& ex )
{
throw UException(ex.what());
}
catch( ... )
{
throw UException("(setValue): catch...");
}
}
//---------------------------------------------------------------------------
long UInterface::getSensorID( const char* name )
{
if( UniSetTypes::conf )
return UniSetTypes::conf->getSensorID(name);
return -1;
}
//---------------------------------------------------------------------------
const char* UInterface::getName( long id )
{
if( UniSetTypes::conf )
return UniSetTypes::conf->oind->getMapName(id).c_str();
return "";
}
//---------------------------------------------------------------------------
const char* UInterface::getShortName( long id )
{
if( UniSetTypes::conf )
return ORepHelpers::getShortName(UniSetTypes::conf->oind->getMapName(id)).c_str();
return "";
}
//---------------------------------------------------------------------------
const char* UInterface::getTextName( long id )
{
if( UniSetTypes::conf )
return UniSetTypes::conf->oind->getTextName(id).c_str();
return "";
}
//---------------------------------------------------------------------------
const char* UInterface::getConfFileName()
{
if( UniSetTypes::conf )
return UniSetTypes::conf->getConfFileName().c_str();
return "";
}
//---------------------------------------------------------------------------
#ifndef UInterface_H_
#define UInterface_H_
// --------------------------------------------------------------------------
#include <string>
#include "UTypes.h"
#include "UExceptions.h"
// --------------------------------------------------------------------------
namespace UInterface
{
void uniset_init_params( UTypes::Params* p, const char* xmlfile )throw(UException);
void uniset_init( int argc, char** argv, const char* xmlfile )throw(UException);
//---------------------------------------------------------------------------
long getValue( long id )throw(UException);
void setValue( long id, long val )throw(UException);
long getSensorID( const char* );
const char* getShortName( long id );
const char* getName( long id );
const char* getTextName( long id );
const char* getConfFileName();
}
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
// This file is part of the NCS project. (c) 1999-2000 All rights reserved.
// 14-ти битная аналоговая карта 16 входов (8 дифф), 2 выхода (12-ти битные)
/*
#include <assert.h>
#include "conf.h"
#include "IOPort.h"
#include "IOs/AnalogCardAI165A.h"
#include "SysTimer.h"
#include "Exceptions.h"
//-----------------------------------------------------------------------------
AnalogCardAI165A::AnalogCardAI165A( void )
{
if( ioperm( base_io_adr, 0x10, PORT_PERMISSION ) == -1 )
throw GlobalError("Невозможно открыть порты");
if (!((inb(base_io_adr+14)=='A')&&(inb(base_io_adr+15)==17)))
throw GlobalError("Модуль AI16-5a-STB с FIFO не найден !");
outw(0x0000,base_io_adr+0);
// Умножение входного сигнала
int u=0x0000;
// u=0x5555;
// case 2 : n=0xAAAA; break;
// case 3 : n=0xFFFF; break;
outw(u,base_io_adr+6);
outw(u,base_io_adr+8);
maxInputChannel=16;
}
//-----------------------------------------------------------------------------
AnalogCardAI165A::~AnalogCardAI165A( void )
{
}
//-----------------------------------------------------------------------------
int AnalogCardAI165A::getValue( int io_channel )
{
assert(io_channel>=0);
assert(io_channel<16);
// if(io_channel>=16)
// printf("%d\n",io_channel);
// io_channel&=0x0F;
outb(0x00, base_io_adr+0);
io_channel|=0x20; // Однопроводное подключение
outb(io_channel, base_io_adr+2);
msleep(10); // можно поставить for (int i=0;i<90;i++);
//int o=inb(base_io_adr+0);
//outb((o&240)|0x80, base_io_adr+0);
outb(0x80, base_io_adr+0); // ST_RDY Старт АЦП
//for (int i=0; i<60; i++); // pause
//while(!(inb(base_io_adr+0)&0x80)); // ST_RDY
while(!(inb(base_io_adr+0)&0x20));
int r=inw(base_io_adr+2);
if (r<0) r=-1;
//if (r>8191) r=8191;
return r;
}
void AnalogCardAI165A::getChainValue( long * data, const int NumChannel )
{
assert(NumChannel>=0);
assert(NumChannel<16);
outw(0x00, base_io_adr+0);
int io_channel=0;
io_channel|=0x20; // Однопроводное подключение
outb(io_channel, base_io_adr+2);
msleep(1);
for(int n=0; n< NumChannel; n++)
{
outb(0x80|0x01, base_io_adr+0); // ST_RDY | n++
while(!(inb(base_io_adr+0)&0x80)); // ST_RDY // Опрос бита готовности
data[n]=inw(base_io_adr+2);
// может быть здесь все же нужна пауза?
}
outw(0x00, base_io_adr+0);
}
//-----------------------------------------------------------------------------
// !!! Не устанавливается номер канала
void AnalogCardAI165A::setValue( int io_channel, int value )
// io_channel -- 0 or 1
{
assert(io_channel==0 || io_channel==1 );
if (value<0)
value=0;
else if (value>4095)
value=4095;
io_channel&=1;
io_channel<<=12;
value&=0x0FFF;
outw(value,base_io_adr+14);
outb(value,base_io_adr+14);
}
*/
/***************************************************************************
* This file is part of the UniSet* library *
* Copyright (C) 1999-2002 SET Research Institute. All rights reserved. *
***************************************************************************/
/*! \file
* \brief Класс для дискретной карты O5600
* \author Vitaly Lipatov
*/
/**************************************************************************/
#include <assert.h>
#include "IOs/DigitalCard_O5600.h"
#include "Exceptions.h"
using namespace std;
// Получить маску для модуля module
char DigitalCard_O5600::getMask( int module )
{
assert ( module >= 0 && module < 24 );
return 1 << ( module & 0x07 );
}
// Получить адрес порта для указанного модуля
int DigitalCard_O5600::getPort( int module )
{
//assert( baseadr + 2 < SIZE_OF_PORTMAP );
if ( ( module >= 0 ) && ( module < 8 ) )
{
return baseadr + 2; // C
}
else if ( module > 7 && module < 16 )
{
return baseadr + 0; // A
}
else if ( module > 15 && module < 24 )
{
return baseadr + 1; // B
}
// Чего за ерунду передаете?!!
//logErr.Save( "Неправильный номер модуля для функции GetPort, module=%d", module );
//throw Exceptions::OutOfRange();
return baseadr;
}
bool DigitalCard_O5600::get( int module )
{
char tmp = ~in( getPort( module ) );
return tmp & getMask( module );
}
char DigitalCard_O5600::getPrevious( int module )
{
assert ( getPort( module ) - baseadr >= 0 );
assert ( getPort( module ) - baseadr < 4 );
return portmap[ getPort( module ) - baseadr ];
}
/*
bool DigitalCard_O5600::getCurrentState( int module )
{
return getPrevious( module ) & getMask( module );
}
*/
void DigitalCard_O5600::putByte( int ba, char val )
{
portmap[ba - baseadr] = val;
out( ba, ~val );
}
int DigitalCard_O5600::getByte( int ba )
{
char tmp = ~in( ba );
return tmp;
}
void DigitalCard_O5600::set( int module, bool state )
{
char val = getPrevious( module );
char mask = getMask( module );
if ( state )
val |= mask;
else
val &= ~mask;
putByte( getPort( module ), val );
}
bool DigitalCard_O5600::init( bool flagInit, int numOfCard, int base_address, char mode )
{
//if ( !Card.portmap )
// logIO.Save( "DigitalCard_O5600: Вызвана Init без предварительного получения памяти" );
//this->numOfCard = numOfCard;
baseadr = base_address;
cout << "baseadr=" << baseadr << endl;
iomode = mode;
//logReg.Save( "DigitalCard_O5600: Начали" );
out( baseadr + 0x03, iomode | 0x80 ); // Настройка режима карты
for ( int k = 0;k < 3;k++ )
{
putByte( baseadr + k, 0 );
}
if ( in( baseadr + 0x03 ) == 0xff ) // Нет карты
return false;
//logReg.Save( "DigitalCard_O5600: Установлен" );
return true;
}
############################################################################
# This file is part of the UniSet library #
############################################################################
noinst_LTLIBRARIES = libIOs.la
libIOs_la_SOURCES = AnalogCard_AI165A.cc DigitalCard_O5600.cc
include $(top_builddir)/conf/setting.mk
/* This file is part of the UniSet project
* Copyright (c) 2002 Free Software Foundation, Inc.
* Copyright (c) 2002 Pavel Vainerman
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// --------------------------------------------------------------------------
/*! \file
* \author Pavel Vainerman
*/
// --------------------------------------------------------------------------
#include "Exceptions.h"
#include "ObjectsManager_LT.h"
#include "Debug.h"
#include "PassiveTimer.h"
// ------------------------------------------------------------------------------------------
using namespace std;
using namespace UniSetTypes;
// ------------------------------------------------------------------------------------------
ObjectsManager_LT::ObjectsManager_LT( UniSetTypes::ObjectId id ):
ObjectsManager(id),
sleepTime(UniSetTimer::WaitUpTime)
{
}
// ------------------------------------------------------------------------------------------
ObjectsManager_LT::ObjectsManager_LT():
sleepTime(UniSetTimer::WaitUpTime)
{
}
// ------------------------------------------------------------------------------------------
ObjectsManager_LT::~ObjectsManager_LT()
{
}
// ------------------------------------------------------------------------------------------
void ObjectsManager_LT::callback()
{
// При реализации с использованием waitMessage() каждый раз при вызове askTimer() необходимо
// проверять возвращаемое значение на UniSetTimers::WaitUpTime и вызывать termWaiting(),
// чтобы избежать ситуации, когда процесс до заказа таймера 'спал'(в функции waitMessage()) и после
// заказа продолжит спать(т.е. обработчик вызван не будет)...
try
{
if( waitMessage(msg, sleepTime) )
processingMessage(&msg);
sleepTime=lt.checkTimers(this);
}
catch(Exception& ex)
{
unideb[Debug::CRIT] << myname << "(callback): " << ex << endl;
}
}
// ------------------------------------------------------------------------------------------
void ObjectsManager_LT::askTimer( UniSetTypes::TimerId timerid, timeout_t timeMS, short ticks, UniSetTypes::Message::Priority p )
{
// проверяйте возвращаемое значение
if( lt.askTimer(timerid, timeMS, ticks, p) != UniSetTimer::WaitUpTime )
termWaiting();
}
// ------------------------------------------------------------------------------------------
/* This file is part of the UniSet project
* Copyright (c) 2002 Free Software Foundation, Inc.
* Copyright (c) 2002 Pavel Vainerman
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// --------------------------------------------------------------------------
/*! \file
* \author Pavel Vainerman
*/
// --------------------------------------------------------------------------
#include "UniSetObserver.h"
#include "Exceptions.h"
#include "UniversalInterface.h"
// ---------------------------------------------------------------------------
using namespace UniSetTypes;
// ---------------------------------------------------------------------------
UniSetSubject::UniSetSubject()
{
}
UniSetSubject::UniSetSubject(ObjectId id):
id(id)
{
}
UniSetSubject::~UniSetSubject()
{
}
// ---------------------------------------------------------------------------
void UniSetSubject::attach( UniSetObject* o )
{
ObserverList::iterator li = find(lst.begin(),lst.end(),o);
if( li==lst.end() )
lst.push_front(o);
}
// ---------------------------------------------------------------------------
void UniSetSubject::detach( UniSetObject* o )
{
lst.remove(o);
}
// ---------------------------------------------------------------------------
void UniSetSubject::notify(int notify, int data, Message::Priority priority)
{
for( ObserverList::iterator li=lst.begin();li!=lst.end();++li )
{
try
{
UpdateMessage msg(id, notify, data, priority, (*li)->getId());
(*li)->push( msg.transport_msg() );
}
catch(Exception& ex)
{
unideb[Debug::WARN] << ex << endl;
}
}
}
// ------------------------------------------------------------------------------------------
void UniSetSubject::notify( UniSetTypes::TransportMessage& msg )
{
for (ObserverList::iterator li=lst.begin();li!=lst.end();++li)
{
try
{
(*li)->push( msg );
}
catch(Exception& ex)
{
unideb[Debug::WARN] << ex << endl;
}
}
}
// ------------------------------------------------------------------------------------------
void UniSetSubject::attach( UniSetObject* o, int MessageType )
{
}
// ------------------------------------------------------------------------------------------
void UniSetSubject::detach( UniSetObject* o, int MessageType )
{
}
// ------------------------------------------------------------------------------------------
/* This file is part of the UniSet project
* Copyright (c) 2002 Free Software Foundation, Inc.
* Copyright (c) 2002 Pavel Vainerman
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// --------------------------------------------------------------------------
/*! \file
* \author Pavel Vainerman
*/
// --------------------------------------------------------------------------
#include "Exceptions.h"
#include "RepositoryAgent.h"
// ------------------------------------------------------------------------------------------
using namespace UniSetTypes;
extern const ObjectInfo *pObjectsMap;
// ------------------------------------------------------------------------------------------
RepositoryAgent::RepositoryAgent():
oind(pObjectsMap)
{
}
RepositoryAgent::~RepositoryAgent()
{
}
/*
RepositoryAgent::RepositoryAgent(const string name, const string section, int* argc, char* **argv):
BaseProcess_i(name, section, argc, argv)
{
}
RepositoryAgent::RepositoryAgent( ObjectId id, int* argc, char* **argv):
BaseProcess_i( id, argc, argv)
{
}
*/
RepositoryAgent::RepositoryAgent( ObjectId id, const ObjectInfo *pObjMap):
BaseProcess(id),
oind(pObjMap)
{
// cout << ui.getNameById(id) << endl;
}
// ------------------------------------------------------------------------------------------
/*
void RepositoryAgent::registration(const char* name, ::CORBA::Object_ptr ref)
{
}
// ------------------------------------------------------------------------------------------
void RepositoryAgent::unregistration(const char* name, ::CORBA::Object_ptr ref)
{
}
*/
// ------------------------------------------------------------------------------------------
CORBA::Object_ptr RepositoryAgent::resolve(const char* name)
{
cout << "resolve: " << name << endl;
CORBA::Object_ptr ref;
try
{
ref= ui.resolve(name);
}
catch(NameNotFound)
{
throw RepositoryAgent_i::NameNotFound();
}
catch(ORepFailed)
{
throw RepositoryAgent_i::ResolveError();
}
return CORBA::Object::_duplicate(ref);
}
// ------------------------------------------------------------------------------------------
CORBA::Object_ptr RepositoryAgent::resolveid(BaseObjectId id)
{
cout << "resolveid: " << ui.getNameById(id) << endl;
CORBA::Object_ptr ref;
try
{
ref= ui.resolve(id);
}
catch(NameNotFound)
{
throw RepositoryAgent_i::NameNotFound();
}
catch(ORepFailed)
{
throw RepositoryAgent_i::ResolveError();
}
return CORBA::Object::_duplicate(ref);
}
// ------------------------------------------------------------------------------------------
void RepositoryAgent::execute()
{
while(active)// for(;;)
{
if ( waitMessage(&msg) )
{
/*
switch(msg.type)
{
case MessageType::Command:
{
cout << BaseProcess_i::myname << ": msg id ="<< msg.id << endl;
break;
}
default:
break;
}
*/
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment