Commit 2f34b787 authored by Pavel Vainerman's avatar Pavel Vainerman

(IOC): рефакторинг функции getInfo(), добавил возможность получения

статистики по конкретному заказчику
parent 604c1732
......@@ -588,6 +588,12 @@ uniset::SimpleInfo* <xsl:value-of select="$CLASSNAME"/>_SK::getInfo( const char*
inf &lt;&lt; "LogServer: NONE" &lt;&lt; endl;
<xsl:if test="normalize-space($STAT)='1'">
size_t smCount = 0;
for( const auto&amp; s: smStat )
smCount += s.second;
inf &lt;&lt; "smCount=" &lt;&lt; smCount &lt;&lt; endl;
inf &lt;&lt; "statistics: " &lt;&lt; endl
&lt;&lt; " processingMessageCatchCount: " &lt;&lt; processingMessageCatchCount &lt;&lt; endl;
......
......@@ -8,7 +8,7 @@
ВСЕ ВАШИ ИЗМЕНЕНИЯ БУДУТ ПОТЕРЯНЫ.
*/
// --------------------------------------------------------------------------
// generate timestamp: 2017-04-29+03:00
// generate timestamp: 2017-04-30+03:00
// -----------------------------------------------------------------------------
#ifndef UObject_SK_H_
#define UObject_SK_H_
......
......@@ -11,7 +11,7 @@
ВСЕ ВАШИ ИЗМЕНЕНИЯ БУДУТ ПОТЕРЯНЫ.
*/
// --------------------------------------------------------------------------
// generate timestamp: 2017-04-29+03:00
// generate timestamp: 2017-04-30+03:00
// -----------------------------------------------------------------------------
#include <memory>
#include <iomanip>
......@@ -525,6 +525,12 @@ uniset::SimpleInfo* UObject_SK::getInfo( const char* userparam )
inf << "LogServer: NONE" << endl;
size_t smCount = 0;
for( const auto& s: smStat )
smCount += s.second;
inf << "smCount=" << smCount << endl;
inf << "statistics: " << endl
<< " processingMessageCatchCount: " << processingMessageCatchCount << endl;
......
......@@ -293,7 +293,11 @@ namespace uniset
virtual void checkThreshold(IOController::IOStateList::iterator& li, const uniset::ObjectId sid, bool send_msg = true );
//! поиск информации о пороговом датчике
ThresholdExtList::iterator findThreshold( const uniset::ObjectId sid, const uniset::ThresholdId tid );
ThresholdInfoExt* findThreshold( AskThresholdMap& tmap, const uniset::ObjectId sid, const uniset::ThresholdId tid );
// обновление статистики
bool updateThresholdStat( AskThresholdMap& tmap, uniset::ObjectId sid, uniset::ThresholdId tid, const uniset::ConsumerInfo& ci, size_t stat_smCount );
bool updateSensorStat( IOController::IOStateList::iterator& it, const uniset::ConsumerInfo& ci, size_t stat_smCount );
/*! сохранение списка заказчиков
По умолчанию делает dump, если объявлен dumper.
......@@ -331,6 +335,12 @@ namespace uniset
Poco::JSON::Object::Ptr getConsumers(uniset::ObjectId sid, ConsumerListInfo& clist, bool ifNotEmpty = true );
#endif
// статистика
void showStatisticsForConsumer( std::ostringstream& inf, const std::string& consumer );
void showStatisticsForLostConsumers( std::ostringstream& inf );
void showStatisticsForConsusmers( std::ostringstream& inf );
void showStatisticsForConsumersWithLostEvent( std::ostringstream& inf );
private:
friend class NCRestorer;
......
......@@ -76,118 +76,272 @@ IONotifyController::~IONotifyController()
conInit.disconnect();
}
// ------------------------------------------------------------------------------------------
SimpleInfo* IONotifyController::getInfo( const char* userparam )
void IONotifyController::showStatisticsForConsumer( ostringstream& inf, const std::string& consumer )
{
uniset::SimpleInfo_var i = IOController::getInfo(userparam);
ObjectId consumer_id = uniset_conf()->getObjectID(consumer);
if( consumer_id == DefaultObjectId )
{
inf << "not found consumer '" << consumer << "'" << endl;
return;
}
ostringstream inf;
// Формируем статистику по каждому датчику..
struct StatInfo
{
StatInfo( ObjectId id, const ConsumerInfoExt& c ):inf(c),sid(id){}
inf << i->info << endl;
const ConsumerInfoExt inf;
ObjectId sid;
};
auto oind = uniset_conf()->oind;
std::list<StatInfo> stat;
{
std::lock_guard<std::mutex> lock(lostConsumersMutex);
// общее количество SensorMessage полученное этим заказчиком
size_t smCount = 0;
{ // lock askIOMutex
if( lostConsumers.size() > 0 )
// выводим информацию по конкретному объекту
uniset_rwmutex_rlock lock(askIOMutex);
for( auto&& a : askIOList )
{
inf << "-------------------------- lost consumers list [maxAttemtps=" << maxAttemtps << "] ------------------" << endl;
auto& i = a.second;
uniset_rwmutex_rlock lock(i.mut);
for( const auto& l : lostConsumers )
if( i.clst.empty() )
continue;
// ищем среди заказчиков
for( const auto& c : i.clst )
{
inf << " " << "(" << setw(6) << l.first << ")"
<< setw(35) << std::left << ORepHelpers::getShortName(oind->getMapName(l.first))
<< " lostCount=" << l.second.count
<< endl;
if( c.id == consumer_id )
{
stat.emplace_back(a.first,c);
smCount += c.smCount;
break;
}
}
}
} // unlock askIOMutex
inf << "----------------------------------------------------------------------------------" << endl;
{
// выводим информацию по конкретному объекту
uniset_rwmutex_rlock lock(trshMutex);
for( auto&& a: askTMap )
{
uniset_rwmutex_rlock lock2(a.second.mut);
for( auto&& t: a.second.list )
{
uniset_rwmutex_rlock lock3(t.clst.mut);
for( const auto& c: t.clst.clst )
{
if( c.id == consumer_id )
{
if( t.sid != DefaultObjectId )
stat.emplace_back(t.sid,c);
else
stat.emplace_back(a.first,c);
smCount += c.smCount;
break;
}
}
}
}
}
//! \todo Назвать параметры нормально
std::string param(userparam);
// печатаем отчёт
inf << "Statisctic for consumer '" << consumer << "'(smCount=" << smCount << "):"
<< endl
<< "--------------------------------------------"
<< endl;
if( param == "1" || param == "2" )
if( stat.empty() )
{
inf << "------------------------------- consumers list ------------------------------" << endl;
inf << "[userparam=" << userparam << "]" << endl;
inf << "NOT FOUND STATISTIC FOR '" << consumer << "'" << endl;
}
else
{
inf << std::right;
auto oind = uniset_conf()->oind;
for( const auto& s: stat )
{
uniset_rwmutex_rlock lock(askIOMutex);
inf << " " << "(" << setw(6) << s.sid << ") "
<< setw(35) << ORepHelpers::getShortName(oind->getMapName(s.sid))
<< " ["
<< " lostEvents: " << setw(3) << s.inf.lostEvents
<< " attempt: " << setw(3) << s.inf.attempt
<< " smCount: " << setw(5) << s.inf.smCount
<< " ]"
<< endl;
}
}
for( auto && a : askIOList )
{
auto& i = a.second;
inf << "--------------------------------------------" << endl;
}
// ------------------------------------------------------------------------------------------
void IONotifyController::showStatisticsForLostConsumers( ostringstream& inf )
{
std::lock_guard<std::mutex> lock(lostConsumersMutex);
uniset_rwmutex_rlock lock(i.mut);
if( lostConsumers.empty() )
{
inf << "..empty lost consumers list..." << endl;
return;
}
// отображаем только датчики с "не пустым" списком заказчиков
if( i.clst.empty() )
continue;
auto oind = uniset_conf()->oind;
for( const auto& l : lostConsumers )
{
inf << " " << "(" << setw(6) << l.first << ") "
<< setw(35) << std::left << ORepHelpers::getShortName(oind->getMapName(l.first))
<< " lostCount=" << l.second.count
<< endl;
}
}
// ------------------------------------------------------------------------------------------
void IONotifyController::showStatisticsForConsusmers( ostringstream& inf )
{
uniset_rwmutex_rlock lock(askIOMutex);
// Т.к. сперва выводится имя датчика, а только потом его заказчики
// то если надо выводить только тех, у кого есть "потери"(lostEvent>0)
// предварительно смотрим список есть ли там хоть один с "потерями", а потом уже выводим
if( param == "2" )
{
bool lost = false;
auto oind = uniset_conf()->oind;
for( const auto& c : i.clst )
{
if( c.lostEvents > 0 )
{
lost = true;
break;
}
}
for( auto&& a : askIOList )
{
auto& i = a.second;
if( !lost )
continue;
uniset_rwmutex_rlock lock(i.mut);
// выводим тех у кого lostEvent>0
inf << "(" << setw(6) << a.first << ")[" << oind->getMapName(a.first) << "]" << endl;
// отображаем только датчики с "не пустым" списком заказчиков
if( i.clst.empty() )
continue;
for( const auto& c : i.clst )
{
if( c.lostEvents > 0 )
{
inf << " " << "(" << setw(6) << c.id << ")"
<< setw(35) << ORepHelpers::getShortName(oind->getMapName(c.id))
<< " ["
<< " lostEvents=" << c.lostEvents
<< " attempt=" << c.attempt
<< " smCount=" << c.smCount
<< "]"
<< endl;
}
}
}
else // просто выводим всех
{
inf << "(" << setw(6) << a.first << ")[" << oind->getMapName(a.first) << "]" << endl;
inf << "(" << setw(6) << a.first << ")[" << oind->getMapName(a.first) << "]" << endl;
for( const auto& c : i.clst )
{
inf << " " << "(" << setw(6) << c.id << ")"
<< setw(35) << ORepHelpers::getShortName(oind->getMapName(c.id))
<< " ["
<< " lostEvents=" << c.lostEvents
<< " attempt=" << c.attempt
<< " smCount=" << c.smCount
<< "]"
<< endl;
}
}
}
// ------------------------------------------------------------------------------------------
void IONotifyController::showStatisticsForConsumersWithLostEvent( ostringstream& inf )
{
uniset_rwmutex_rlock lock(askIOMutex);
for( const auto& c : i.clst )
{
inf << " " << "(" << setw(6) << c.id << ")"
<< setw(35) << ORepHelpers::getShortName(oind->getMapName(c.id))
<< " ["
<< " lostEvents=" << c.lostEvents
<< " attempt=" << c.attempt
<< " smCount=" << c.smCount
<< "]"
<< endl;
}
}
auto oind = uniset_conf()->oind;
bool empty = true;
for( auto&& a : askIOList )
{
auto& i = a.second;
uniset_rwmutex_rlock lock(i.mut);
// отображаем только датчики с "не пустым" списком заказчиков
if( i.clst.empty() )
continue;
// Т.к. сперва выводится имя датчика, а только потом его заказчики
// то если надо выводить только тех, у кого есть "потери"(lostEvent>0)
// для предварительно смотрим список есть ли там хоть один с "потерями", а потом уже выводим
bool lost = false;
for( const auto& c : i.clst )
{
if( c.lostEvents > 0 )
{
lost = true;
break;
}
}
inf << "-----------------------------------------------------------------------------" << endl << endl;
if( !lost )
continue;
empty = false;
// выводим тех у кого lostEvent>0
inf << "(" << setw(6) << a.first << ")[" << oind->getMapName(a.first) << "]" << endl;
for( const auto& c : i.clst )
{
if( c.lostEvents > 0 )
{
inf << " " << "(" << setw(6) << c.id << ")"
<< setw(35) << ORepHelpers::getShortName(oind->getMapName(c.id))
<< " ["
<< " lostEvents=" << c.lostEvents
<< " attempt=" << c.attempt
<< " smCount=" << c.smCount
<< "]"
<< endl;
}
}
}
if( empty )
inf << "...not found consumers with lost event..." << endl;
}
// ------------------------------------------------------------------------------------------
SimpleInfo* IONotifyController::getInfo( const char* userparam )
{
uniset::SimpleInfo_var i = IOController::getInfo(userparam);
//! \todo Назвать параметры нормально
//!
std::string param(userparam);
ostringstream inf;
inf << i->info << endl;
auto oind = uniset_conf()->oind;
if( param.empty() )
{
inf << "-------------------------- lost consumers list [maxAttemtps=" << maxAttemtps << "] ------------------" << endl;
showStatisticsForLostConsumers(inf);
inf << "----------------------------------------------------------------------------------" << endl;
}
inf << "IONotifyController::UserParam help: " << endl
<< " 0. Common info" << endl
<< " 1. Consumers list " << endl
<< " 2. Consumers list with lostEvent > 0" << endl;
if( param == "consumers" )
{
inf << "------------------------------- consumers list ------------------------------" << endl;
showStatisticsForConsusmers(inf);
inf << "-----------------------------------------------------------------------------" << endl << endl;
}
else if( param == "lost" )
{
inf << "------------------------------- consumers list (lost event)------------------" << endl;
showStatisticsForConsumersWithLostEvent(inf);
inf << "-----------------------------------------------------------------------------" << endl << endl;
}
else if( !param.empty() )
{
showStatisticsForConsumer(inf, param);
}
else
{
inf << "IONotifyController::UserParam help: " << endl
<< " Default - Common info" << endl
<< " consumers - Consumers list " << endl
<< " lost - Consumers list with lostEvent > 0" << endl
<< " name - Statistic for consumer 'name'"
<< endl;
}
i->info = inf.str().c_str();
......@@ -302,6 +456,7 @@ void IONotifyController::askSensor(const uniset::ObjectId sid,
try
{
ui->send(ci.id, std::move(smsg.transport_msg()), ci.node);
updateSensorStat(li,ci,1);
}
catch( const uniset::Exception& ex )
{
......@@ -751,7 +906,12 @@ void IONotifyController::askThreshold(uniset::ObjectId sid, const uniset::Consum
UniSetObject_i_var ref = UniSetObject_i::_narrow(op);
if(!CORBA::is_nil(ref))
{
ref->push( std::move(sm.transport_msg()) );
// askTMap уже залочен trshMutex
updateThresholdStat(askTMap, sid, tid, ci, 1);
}
}
// Проверка верхнего предела
else if( val >= hiLimit )
......@@ -761,7 +921,12 @@ void IONotifyController::askThreshold(uniset::ObjectId sid, const uniset::Consum
UniSetObject_i_var ref = UniSetObject_i::_narrow(op);
if(!CORBA::is_nil(ref))
{
ref->push( std::move(sm.transport_msg()) );
// askTMap уже залочен trshMutex
updateThresholdStat(askTMap, sid, tid, ci, 1);
}
}
}
catch( const uniset::Exception& ex )
......@@ -799,6 +964,7 @@ void IONotifyController::askThreshold(uniset::ObjectId sid, const uniset::Consum
break;
}
// askTMap уже залочен trshMutex
it = askTMap.find(sid);
if( li != myioEnd() )
......@@ -813,6 +979,60 @@ void IONotifyController::askThreshold(uniset::ObjectId sid, const uniset::Consum
} // unlock
}
// --------------------------------------------------------------------------------------------------------------
bool IONotifyController::updateThresholdStat( AskThresholdMap& tmap, uniset::ObjectId sid, uniset::ThresholdId tid, const uniset::ConsumerInfo& ci, size_t smCount )
{
auto ti = findThreshold(tmap, sid, tid);
if( !ti )
return false;
uniset::uniset_rwmutex_rlock lock(ti->clst.mut);
for( auto&& c: ti->clst.clst )
{
if( c.id == ci.id && c.node == ci.node )
{
c.smCount += smCount;
return true;
}
}
return false;
}
// --------------------------------------------------------------------------------------------------------------
bool IONotifyController::updateSensorStat( IOController::IOStateList::iterator& it, const ConsumerInfo& ci, size_t smCount )
{
if( it == myioEnd() )
return false;
ConsumerListInfo* clist = nullptr;
if( it->second->userdata[udataConsumerList] )
clist = static_cast<ConsumerListInfo*>(it->second->userdata[udataConsumerList]);
if( !clist )
{
uniset_rwmutex_wrlock lock(askIOMutex);
auto i = askIOList.find(it->second->si.id);
if( i == askIOList.end() )
return false;
}
if( !clist )
return false;
uniset_rwmutex_wrlock lock(clist->mut);
for( auto&& c: clist->clst )
{
if( c.id == ci.id && c.node == ci.node )
{
c.smCount += smCount;
return true;
}
}
return false;
}
// --------------------------------------------------------------------------------------------------------------
bool IONotifyController::addThreshold( ThresholdExtList& lst, ThresholdInfoExt&& ti, const uniset::ConsumerInfo& ci )
{
for( auto it = lst.begin(); it != lst.end(); ++it)
......@@ -959,27 +1179,24 @@ void IONotifyController::checkThreshold( std::shared_ptr<IOController::USensorIn
}
}
// --------------------------------------------------------------------------------------------------------------
IONotifyController::ThresholdExtList::iterator IONotifyController::findThreshold( const uniset::ObjectId sid, const uniset::ThresholdId tid )
IONotifyController::ThresholdInfoExt* IONotifyController::findThreshold( AskThresholdMap& tmap, const uniset::ObjectId sid, const uniset::ThresholdId tid )
{
{
// lock
uniset_rwmutex_rlock lock(trshMutex);
// поиск списка порогов
auto lst = askTMap.find(sid);
// поиск списка порогов
auto lst = tmap.find(sid);
if( lst != askTMap.end() )
if( lst != tmap.end() )
{
for( auto it = lst->second.list.begin(); it != lst->second.list.end(); ++it)
{
for( auto it = lst->second.list.begin(); it != lst->second.list.end(); ++it)
{
if( it->id == tid )
return it;
}
if( it->id == tid )
return &(*it);
}
}
return ThresholdExtList::iterator();
return nullptr;
}
// --------------------------------------------------------------------------------------------------------------
IONotifyController_i::ThresholdInfo IONotifyController::getThresholdInfo( uniset::ObjectId sid, uniset::ThresholdId tid )
{
uniset_rwmutex_rlock lock(trshMutex);
......
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