Commit 1c9141ee authored by Pavel Vainerman's avatar Pavel Vainerman

(LogServer): сделал предварительную реализацию 'второй части' - 'удалённое управление логами'

parent 1c0113f4
......@@ -5,15 +5,22 @@
#include "UniSetTypes.h"
#include "Exceptions.h"
#include "LogReader.h"
#include "LogServerTypes.h"
// --------------------------------------------------------------------------
using namespace UniSetTypes;
using namespace std;
// --------------------------------------------------------------------------
static struct option longopts[] = {
{ "help", no_argument, 0, 'h' },
{ "verbose", no_argument, 0, 'v' },
{ "iaddr", required_argument, 0, 'a' },
{ "port", required_argument, 0, 'p' },
{ "verbose", no_argument, 0, 'v' },
{ "add", required_argument, 0, 'l' },
{ "del", required_argument, 0, 'd' },
{ "set", required_argument, 0, 's' },
{ "off", required_argument, 0, 'o' },
{ "on", required_argument, 0, 'n' },
{ "rotate", required_argument, 0, 'r' },
{ NULL, 0, 0, 0 }
};
// --------------------------------------------------------------------------
......@@ -26,17 +33,20 @@ static void print_help()
}
// --------------------------------------------------------------------------
int main( int argc, char **argv )
{
{
int optindex = 0;
int opt = 0;
int verb = 0;
string addr("localhost");
int port = 3333;
DebugStream dlog;
int cmd = LogServerTypes::cmdNOP;
int data = 0;
string sdata("");
try
{
while( (opt = getopt_long(argc, argv, "hva:p:",longopts,&optindex)) != -1 )
while( (opt = getopt_long(argc, argv, "hva:p:l:d:s:onr",longopts,&optindex)) != -1 )
{
switch (opt)
{
......@@ -44,6 +54,34 @@ int main( int argc, char **argv )
print_help();
return 0;
case 'l':
{
cmd = LogServerTypes::cmdAddLevel;
sdata = string(optarg);
}
break;
case 'd':
{
cmd = LogServerTypes::cmdDelLevel;
sdata = string(optarg);
}
break;
case 's':
{
cmd = LogServerTypes::cmdSetLevel;
sdata = string(optarg);
}
break;
case 'o':
cmd = LogServerTypes::cmdOffLogFile;
break;
case 'n':
cmd = LogServerTypes::cmdOnLogFile;
break;
case 'r':
cmd = LogServerTypes::cmdRotate;
break;
case 'a':
addr = string(optarg);
break;
......@@ -71,7 +109,16 @@ int main( int argc, char **argv )
}
LogReader lr;
lr.readlogs( addr, port, verb );
if( !sdata.empty() )
{
data = (int)Debug::value(sdata);
if( verb )
cout << "SEND COMMAND: '" << (LogServerTypes::Command)cmd << " data='" << sdata << "'" << endl;
}
lr.readlogs( addr, port, (LogServerTypes::Command)cmd, data, verb );
}
catch( SystemError& err )
{
......
......@@ -6,6 +6,7 @@
#include <cc++/socket.h>
#include "UTCPStream.h"
#include "DebugStream.h"
#include "LogServerTypes.h"
// -------------------------------------------------------------------------
class LogReader
{
......@@ -14,7 +15,7 @@ class LogReader
LogReader();
~LogReader();
void readlogs( const std::string& addr, ost::tpport_t port, bool verbose = false );
void readlogs( const std::string& addr, ost::tpport_t port, LogServerTypes::Command c, int data, bool verbose = false );
bool isConnection();
......
// -------------------------------------------------------------------------
#ifndef LogServerTypes_H_
#define LogServerTypes_H_
// -------------------------------------------------------------------------
#include <ostream>
// -------------------------------------------------------------------------
namespace LogServerTypes
{
const unsigned int MAGICNUM = 0x20140904;
enum Command
{
cmdNOP, /*!< отсутствие команды */
cmdSetLevel, /*!< установить уровень вывода */
cmdAddLevel, /*!< добавить уровень вывода */
cmdDelLevel, /*!< удалить уровень вывода */
cmdRotate, /*!< пересоздать файл с логами */
cmdOffLogFile, /*!< отключить запись файла логов (если включена) */
cmdOnLogFile /*!< включить запись файла логов (если была отключена) */
// cmdSetLogFile
};
std::ostream& operator<<(std::ostream& os, Command c );
struct lsMessage
{
lsMessage():magic(MAGICNUM),cmd(cmdNOP),data(0){}
unsigned int magic;
Command cmd;
unsigned int data;
// для команды 'cmdSetLogFile'
// static const short MAXLOGFILENAME = 100;
// char logname[MAXLOGFILENAME];
}__attribute__((packed));
std::ostream& operator<<(std::ostream& os, lsMessage& m );
}
// -------------------------------------------------------------------------
#endif // LogServerTypes_H_
// -------------------------------------------------------------------------
......@@ -32,6 +32,7 @@ class LogSession:
LogBuffer lbuf;
std::string peername;
std::string caddr;
DebugStream* log;
timeout_t timeout;
PassiveTimer ptSessionTimeout;
......
......@@ -102,14 +102,17 @@ bool LogReader::isConnection()
return tcp && tcp->isConnected();
}
// -------------------------------------------------------------------------
void LogReader::readlogs( const std::string& _addr, ost::tpport_t _port, bool verbose )
void LogReader::readlogs( const std::string& _addr, ost::tpport_t _port, LogServerTypes::Command cmd, int data, bool verbose )
{
timeout_t inTimeout = 10000;
timeout_t outTimeout = 6000;
timeout_t reconDelay = 5000;
char buf[100001];
if( verbose )
rlog.addLevel(Debug::ANY);
bool send_ok = false;
while( true )
{
......@@ -122,7 +125,26 @@ void LogReader::readlogs( const std::string& _addr, ost::tpport_t _port, bool ve
msleep(reconDelay);
continue;
}
if( !send_ok && cmd != LogServerTypes::cmdNOP )
{
if( tcp->isPending(ost::Socket::pendingOutput,outTimeout) )
{
rlog.info() << "** send command: '" << cmd << "' data='" << data << "'" << endl;
LogServerTypes::lsMessage msg;
msg.cmd = cmd;
msg.data = data;
for( size_t i=0; i<sizeof(msg); i++ )
(*tcp) << ((unsigned char*)(&msg))[i];
tcp->sync();
send_ok = true;
}
else
rlog.warn() << "**** SEND COMMAND ('" << cmd << "' FAILED!" << endl;
}
while( tcp->isPending(ost::Socket::pendingInput,inTimeout) )
{
int n = tcp->peek( buf,sizeof(buf)-1 );
......@@ -137,6 +159,7 @@ void LogReader::readlogs( const std::string& _addr, ost::tpport_t _port, bool ve
}
rlog.warn() << "...connection timeout..." << endl;
send_ok = false; // ??!! делать ли?
disconnect();
}
......
// -------------------------------------------------------------------------
#include "LogServerTypes.h"
// -------------------------------------------------------------------------
using namespace std;
// -------------------------------------------------------------------------
std::ostream& LogServerTypes::operator<<(std::ostream& os, LogServerTypes::Command cmd )
{
switch( cmd )
{
case LogServerTypes::cmdSetLevel:
return os << "cmdSetLevel";
case LogServerTypes::cmdAddLevel:
return os << "cmdAddLevel";
case LogServerTypes::cmdDelLevel:
return os << "cmdDelLevel";
case LogServerTypes::cmdRotate:
return os << "cmdRotate";
case LogServerTypes::cmdOffLogFile:
return os << "cmdOffLogFile";
case LogServerTypes::cmdOnLogFile:
return os << "cmdOnLogFile";
default:
return os << "Unknown";
}
return os;
}
// -------------------------------------------------------------------------
std::ostream& LogServerTypes::operator<<(std::ostream& os, LogServerTypes::lsMessage& m )
{
return os << " magic=" << m.magic << " cmd=" << m.cmd << " data=" << m.data;
}
// -------------------------------------------------------------------------
......@@ -6,6 +6,7 @@
#include <cc++/socket.h>
#include "LogSession.h"
#include "UniSetTypes.h"
#include "LogServerTypes.h"
// -------------------------------------------------------------------------
using namespace std;
using namespace UniSetTypes;
......@@ -20,10 +21,11 @@ LogSession::~LogSession()
}
}
// -------------------------------------------------------------------------
LogSession::LogSession( ost::TCPSocket &server, DebugStream* log, timeout_t msec ):
LogSession::LogSession( ost::TCPSocket &server, DebugStream* _log, timeout_t msec ):
TCPSession(server),
peername(""),
caddr(""),
log(_log),
timeout(msec),
cancelled(false)
{
......@@ -61,19 +63,78 @@ void LogSession::run()
timeout_t inTimeout = 2000;
timeout_t outTimeout = 2000;
string oldLogFile( log->getLogFile() );
// Команды могут посылаться только в начале сессии..
if( isPending(Socket::pendingInput, inTimeout) )
{
LogServerTypes::lsMessage msg;
// проверяем канал..(если данных нет, значит "клиент отвалился"...
if( peek( (void*)(&msg),sizeof(msg)) > 0 )
{
ssize_t ret = readData( &msg,sizeof(msg) );
if( ret!=sizeof(msg) || msg.magic!=LogServerTypes::MAGICNUM )
slog.warn() << peername << "(run): BAD MESSAGE..." << endl;
else
{
slog.info() << peername << "(run): receive command: '" << msg.cmd << "'" << endl;
// Обработка команд..
// \warning Работа с логом ведётся без mutex-а, хотя он разделяется отдельными потоками
switch( msg.cmd )
{
case LogServerTypes::cmdSetLevel:
log->level( (Debug::type)msg.data );
break;
case LogServerTypes::cmdAddLevel:
log->addLevel((Debug::type)msg.data );
break;
case LogServerTypes::cmdDelLevel:
log->delLevel( (Debug::type)msg.data );
break;
case LogServerTypes::cmdRotate:
{
string lfile( log->getLogFile() );
if( !lfile.empty() )
log->logFile(lfile);
}
break;
case LogServerTypes::cmdOffLogFile:
{
string lfile( log->getLogFile() );
if( !lfile.empty() )
log->logFile("");
}
break;
case LogServerTypes::cmdOnLogFile:
{
if( !oldLogFile.empty() && oldLogFile != log->getLogFile() )
log->logFile(oldLogFile);
}
break;
default:
slog.warn() << peername << "(run): Unknown command '" << msg.cmd << "'" << endl;
break;
}
}
}
}
cancelled = false;
while( !cancelled && !ptSessionTimeout.checkTime() )
{
if( isPending(Socket::pendingInput, inTimeout) )
{
char buf[100];
// проверка только ради проверки "целостности" соединения
if( isPending(Socket::pendingInput, 10) )
{
char buf[10];
// проверяем канал..(если данных нет, значит "клиент отвалился"...
if( peek(buf,sizeof(buf)) <=0 )
break;
ptSessionTimeout.reset();
slog.warn() << peername << "(run): receive command.." << endl;
// Обработка команд..
}
if( isPending(Socket::pendingOutput, outTimeout) )
......@@ -83,12 +144,14 @@ void LogSession::run()
uniset_rwmutex_wrlock l(mLBuf);
if( !lbuf.empty() )
slog.info() << peername << "(run): send messages.." << endl;
while( !lbuf.empty() )
{
*tcp() << lbuf.front();
lbuf.pop_front();
slog.info() << peername << "(run): send messages.." << endl;
while( !lbuf.empty() )
{
*tcp() << lbuf.front();
lbuf.pop_front();
}
tcp()->sync();
}
}
}
......
......@@ -4,6 +4,5 @@
noinst_LTLIBRARIES = libLogServer.la
libLogServer_la_CPPFLAGS = $(SIGC_CFLAGS) $(COMCPP_CFLAGS)
#libLogServer_la_LIBADD = $(top_builddir)/src/Communications/TCP/libTCP.la $(SIGC_LIBS) $(COMCPP_LIBS)
libLogServer_la_LIBADD = $(SIGC_LIBS) $(COMCPP_LIBS)
libLogServer_la_SOURCES = LogServer.cc LogSession.cc LogReader.cc
libLogServer_la_SOURCES = LogServerTypes.cc LogServer.cc LogSession.cc LogReader.cc
......@@ -375,9 +375,15 @@ void DebugStream::logFile( const std::string& f )
} else {
internal = new debugstream_internal;
}
internal->fbuf.open(f.c_str(), ios::out|ios::app);
delete rdbuf(new threebuf(cerr.rdbuf(),
if( !f.empty() )
{
internal->fbuf.open(f.c_str(), ios::out|ios::app);
delete rdbuf(new threebuf(cerr.rdbuf(),
&internal->fbuf,&internal_sbuf->sbuf));
}
else
delete rdbuf(new teebuf(cerr.rdbuf(),&internal_sbuf->sbuf));
}
//--------------------------------------------------------------------------
std::ostream & DebugStream::debug(Debug::type t)
......
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