Commit c5810154 authored by Sebastien Ponce's avatar Sebastien Ponce
Browse files

Changed the logging facilities of the C++ part to use DLF

parent 4acd9dfe
......@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* @(#)$RCSfile: BaseObject.cpp,v $ $Revision: 1.4 $ $Release$ $Date: 2004/06/23 12:44:22 $ $Author: sponcec3 $
* @(#)$RCSfile: BaseObject.cpp,v $ $Revision: 1.5 $ $Release$ $Date: 2004/07/07 16:01:07 $ $Author: sponcec3 $
*
*
*
......@@ -32,14 +32,31 @@
#include "castor/exception/Exception.hpp"
#include "castor/exception/Internal.hpp"
#include "Cglobals.h"
#include <Cthread_api.h>
// -----------------------------------------------------------------------
// static values initialization
// -----------------------------------------------------------------------
castor::MsgSvc* castor::BaseObject::s_msgSvc(0);
int castor::BaseObject::s_lock(0);
// -----------------------------------------------------------------------
// constructor
// -----------------------------------------------------------------------
castor::BaseObject::BaseObject() throw() {}
// -----------------------------------------------------------------------
// destructor
// -----------------------------------------------------------------------
castor::BaseObject::~BaseObject() throw() {}
// -----------------------------------------------------------------------
// msgSvc
// -----------------------------------------------------------------------
castor::MsgSvc* castor::BaseObject::msgSvc()
castor::MsgSvc* castor::BaseObject::msgSvc(std::string name)
throw (castor::exception::Exception) {
IService* svc = svcs()->service("MsgSvc",
castor::MsgSvc::ID());
IService* svc = castor::Services::globalService
(name, castor::MsgSvc::ID());
if (0 == svc) {
castor::exception::Internal e;
e.getMessage() << "Unable to retrieve MsgSvc";
......@@ -93,10 +110,30 @@ void castor::BaseObject::getTLS(void **thip)
}
}
//------------------------------------------------------------------------------
// initLog
//------------------------------------------------------------------------------
void castor::BaseObject::initLog(std::string name)
throw(castor::exception::Exception) {
Cthread_mutex_lock(&s_lock);
if (0 != s_msgSvc) {
s_msgSvc->release();
s_msgSvc = 0;
}
// This always return some sensible value if no exception is raised
s_msgSvc = msgSvc(name);
Cthread_mutex_unlock(&s_lock);
}
//------------------------------------------------------------------------------
// clog
//------------------------------------------------------------------------------
castor::logstream& castor::BaseObject::clog()
throw(castor::exception::Exception) {
return msgSvc()->stream();
if (0 == s_msgSvc) {
castor::exception::Internal e;
e.getMessage() << "Please call initLog() before calling clog()";
throw e;
}
return s_msgSvc->stream();
}
......@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* @(#)$RCSfile: BaseObject.hpp,v $ $Revision: 1.4 $ $Release$ $Date: 2004/06/23 12:44:23 $ $Author: sponcec3 $
* @(#)$RCSfile: BaseObject.hpp,v $ $Revision: 1.5 $ $Release$ $Date: 2004/07/07 16:01:07 $ $Author: sponcec3 $
*
* Basic object support, including pointer to Services and log support
*
......@@ -43,6 +43,16 @@ namespace castor {
class BaseObject {
public:
/**
* constructor
*/
BaseObject() throw();
/**
* destructor
*/
virtual ~BaseObject() throw();
/**
* Static access to the underlying Services object
......@@ -55,14 +65,21 @@ namespace castor {
Services* svcs() throw(castor::exception::Exception);
/**
* gets the message service.
* gets a given message service from its name.
* Note that the service has to be released after usage
* @param name the name of the MsgSvc to retrieve
* @return a pointer to the message service. This is always
* a valid pointer if no exception was raised
* @exception Exception if something went wrong
*/
MsgSvc* msgSvc() throw(castor::exception::Exception);
MsgSvc* msgSvc(std::string name) throw(castor::exception::Exception);
/**
* Initialization of to the log stream
* @param name the name of the log stream
*/
void initLog(std::string name) throw(castor::exception::Exception);
/**
* Access to the log stream
*/
......@@ -75,6 +92,19 @@ namespace castor {
*/
static void getTLS(void** thip) throw(castor::exception::Exception);
private:
/**
* The message service to be used for logging
* This is shared among instances
*/
static castor::MsgSvc* s_msgSvc;
/**
* a lock to synchronize the s_msgSvc creation/deletion
*/
static int s_lock;
}; // end of class BaseObject
} // end of namespace castor
......
......@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* @(#)$RCSfile: MsgSvc.cpp,v $ $Revision: 1.1.1.1 $ $Release$ $Date: 2004/05/12 12:13:34 $ $Author: sponcec3 $
* @(#)$RCSfile: MsgSvc.cpp,v $ $Revision: 1.2 $ $Release$ $Date: 2004/07/07 16:01:07 $ $Author: sponcec3 $
*
*
*
......@@ -44,40 +44,16 @@ std::string castor::MsgSvc::s_defaultLogfilename = "log";
// -----------------------------------------------------------------------
// Constructor
// -----------------------------------------------------------------------
castor::MsgSvc::MsgSvc(const std::string name) :
castor::MsgSvc::MsgSvc(const std::string name) throw() :
BaseSvc(name) {
// Gather some configurations
char* logFileRead = getconfent("LogFile", (char*)name.c_str(), 0);
const char* logFile;
if (0 == logFileRead) {
logFile = s_defaultLogfilename.c_str();
} else {
logFile = strdup(logFileRead);
}
char* logLevel = getconfent((char*)logFile, "Level", 0);
castor::logstream::Level l = castor::logstream::INFO;
if (0 == logLevel) {
} else if (0 == strncmp(logLevel, "VER", 3)) {
l = castor::logstream::VERBOSE;
} else if (0 == strncmp(logLevel, "DEB", 3)) {
l = castor::logstream::DEBUG;
} else if (0 == strncmp(logLevel, "WAR", 3)) {
l = castor::logstream::WARNING;
} else if (0 == strncmp(logLevel, "ERR", 3)) {
l = castor::logstream::ERROR;
} else if (0 == strncmp(logLevel, "FAT", 3)) {
l = castor::logstream::FATAL;
} else if (0 == strncmp(logLevel, "ALW", 3)) {
l = castor::logstream::ALWAYS;
}
// create the inner stream
m_stream = new castor::logstream(logFile, l);
m_stream = new castor::logstream(name);
}
// -----------------------------------------------------------------------
// Destructor
// -----------------------------------------------------------------------
castor::MsgSvc::~MsgSvc() {
castor::MsgSvc::~MsgSvc() throw() {
m_stream->close();
delete m_stream;
}
......
......@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* @(#)$RCSfile: MsgSvc.hpp,v $ $Revision: 1.1.1.1 $ $Release$ $Date: 2004/05/12 12:13:34 $ $Author: sponcec3 $
* @(#)$RCSfile: MsgSvc.hpp,v $ $Revision: 1.2 $ $Release$ $Date: 2004/07/07 16:01:07 $ $Author: sponcec3 $
*
*
*
......@@ -46,12 +46,12 @@ namespace castor {
/**
* Constructor
*/
MsgSvc(const std::string name);
MsgSvc(const std::string name) throw();
/**
* Destructor
*/
virtual ~MsgSvc();
virtual ~MsgSvc() throw();
/**
* Get the service id
......
......@@ -74,6 +74,7 @@ castor::client::BaseClient::~BaseClient() throw() {
//------------------------------------------------------------------------------
void castor::client::BaseClient::run(int argc, char** argv)
throw() {
initLog("Client");
try {
// parses the command line
if (!parseInput(argc, argv)) {
......
......@@ -140,7 +140,8 @@ const unsigned int castor::db::ora::OraCnvSvc::REPTYPE() {
// getConnection
// -----------------------------------------------------------------------
oracle::occi::Connection* castor::db::ora::OraCnvSvc::getConnection()
throw (oracle::occi::SQLException) {
throw (oracle::occi::SQLException,
castor::exception::Exception) {
// Quick answer if connection available
if (0 != m_connection) return m_connection;
// Else try to build one
......@@ -151,7 +152,7 @@ oracle::occi::Connection* castor::db::ora::OraCnvSvc::getConnection()
if (0 == m_connection) {
m_connection =
m_environment->createConnection(m_user, m_passwd, m_dbName);
clog() << " Created new Oracle connection : "
clog() << "Created new Oracle connection : "
<< std::ios::hex << m_connection
<< std::ios::dec << std::endl;
//oracle::occi::Statement* stmt = m_connection->createStatement
......
......@@ -87,7 +87,8 @@ namespace castor {
* @exception SQLException thrown by ORACLE
*/
oracle::occi::Connection* getConnection()
throw (oracle::occi::SQLException);
throw (oracle::occi::SQLException,
castor::exception::Exception);
/**
* deletes the connection to the database
......
......@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* @(#)$RCSfile: logbuf.cpp,v $ $Revision: 1.2 $ $Release$ $Date: 2004/06/16 14:43:54 $ $Author: sponcec3 $
* @(#)$RCSfile: logbuf.cpp,v $ $Revision: 1.3 $ $Release$ $Date: 2004/07/07 16:01:07 $ $Author: sponcec3 $
*
*
*
......@@ -26,33 +26,3 @@
// Include Files
#include "castor/logbuf.h"
#include <time.h>
#include <sstream>
#include <iomanip>
#include <Cthread_api.h>
//-----------------------------------------------------------------------------
// getTimeStamp
//-----------------------------------------------------------------------------
std::string castor::logbuf::getTimeStamp() {
struct tm tmstruc, *tm;
time_t current_time;
(void) time (&current_time);
(void) localtime_r (&current_time, &tmstruc);
tm = &tmstruc;
std::ostringstream buf;
buf << std::setw(2) << tm->tm_mon+1
<< "/" << tm->tm_mday
<< " " << tm->tm_hour
<< ":" << tm->tm_min
<< ":" << tm->tm_sec;
#ifdef THREAD_SAFE
buf << " " << Cthread_self() << " ";
#else
buf << " 0 ";
#endif
return buf.str();
}
......@@ -17,69 +17,140 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* @(#)$RCSfile: logbuf.h,v $ $Revision: 1.1 $ $Release$ $Date: 2004/05/28 09:40:26 $ $Author: sponcec3 $
* @(#)$RCSfile: logbuf.h,v $ $Revision: 1.2 $ $Release$ $Date: 2004/07/07 16:01:08 $ $Author: sponcec3 $
*
*
*
*
* @author Sebastien Ponce
*****************************************************************************/
#ifndef CASTOR_LOGBUF_H
#ifndef CASTOR_LOGBUF_H
#define CASTOR_LOGBUF_H 1
// Include Files
#include <iostream>
#include <fstream>
#include <dlf_api.h>
#include "Cuuid.h"
#include <sstream>
#include <string>
#include <serrno.h>
#include <iostream>
namespace castor {
class logbuf : public std::filebuf {
class logbuf : public std::stringbuf {
public:
/**
* Constructor
* The different possible level of output
*/
logbuf() : std::filebuf(), m_newline(true) {}
typedef enum _Level_ {
NIL = 0,
VERBOSE,
DEBUG,
INFO,
WARNING,
ERROR,
FATAL,
ALWAYS,
NUM_LEVELS
} Level;
public:
/**
* output of n characters in one go
* Constructor
*/
virtual std::streamsize
xsputn(const char* __s, std::streamsize __n) {
if (m_newline) {
std::string prefix = getTimeStamp();
std::filebuf::xsputn(prefix.c_str(), prefix.size());
logbuf(std::string &name) :
std::stringbuf(std::ios_base::out),
m_curLevel(INFO) {
int e;
if ((e = dlf_init(name.c_str())) < 0) {
std::cerr << "Unable to initialize DLF :"
<< std::endl << sstrerror(e)
<< std::endl;
}
m_newline = (__s[__n-1] == '\n');
std::filebuf::xsputn(__s, __n);
}
/**
* set m_newline to true
*/
void setNewLine() { m_newline = true; }
/**
* set current output level
*/
void setLevel(logbuf::Level l) { m_curLevel = l; }
private:
public:
/**
* Build a prefix for logs containing the date, time
* and thread number
*/
std::string getTimeStamp();
/**
* Synchronizes the buffer with DLF
*/
virtual int sync() {
if (0 == str().size()) return 0;
// Write current message to DLF
Cuuid_t cuuid;
std::string msg = str();
// Compute DLF level for the message
int level;
switch (m_curLevel) {
case (VERBOSE) :
case (DEBUG) :
level = DLF_LVL_DEBUG;
break;
case (INFO) :
level = DLF_LVL_USAGE;
break;
case (WARNING) :
level = DLF_LVL_WARNING;
break;
case (ERROR) :
level = DLF_LVL_ERROR;
break;
case (FATAL) :
level = DLF_LVL_ALERT;
break;
case (ALWAYS) :
level = DLF_LVL_EMERGENCY;
break;
}
// Take care of long messages
if (str().size() <= DLF_MAXSTRVALLEN) {
dlf_write(cuuid, m_curLevel, 0, 0, 1,
"MESSAGE", DLF_MSG_PARAM_STR, msg.c_str());
} else {
// Message too long, cut it into pieces
const char* longmsg = msg.c_str();
int size = msg.size();
char buffer[DLF_MAXSTRVALLEN+1];
strncpy(buffer, longmsg, DLF_MAXSTRVALLEN);
buffer[DLF_MAXSTRVALLEN] = 0;
dlf_write(cuuid, level, 0, 0, 1,
"MESSAGE", DLF_MSG_PARAM_STR, buffer);
int index = DLF_MAXSTRVALLEN;
while (index < size) {
int bitLength = DLF_MAXSTRVALLEN;
if (size - index < DLF_MAXSTRVALLEN) {
bitLength = size - index;
}
strncpy(buffer, longmsg, bitLength);
buffer[bitLength] = 0;
dlf_write(cuuid, level, 0, 0, 1,
"CONTINUATION", DLF_MSG_PARAM_STR, buffer);
index = index + bitLength;
}
}
// Erase buffer
str("");
return 0;
}
private:
/**
* remember whether we are at a new line
*/
bool m_newline;
/**
* The current level of output for the stream.
* Next calls to << will use this level
*/
logbuf::Level m_curLevel;
};
} // End of namespace Castor
......
......@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* @(#)$RCSfile: logstream.cpp,v $ $Revision: 1.2 $ $Release$ $Date: 2004/06/08 08:48:48 $ $Author: sponcec3 $
* @(#)$RCSfile: logstream.cpp,v $ $Revision: 1.3 $ $Release$ $Date: 2004/07/07 16:01:08 $ $Author: sponcec3 $
*
*
*
......@@ -29,7 +29,7 @@
#define MANIPULATORIMPL(T) \
castor::logstream& castor::T(castor::logstream& s) { \
s.setLevel(castor::logstream::T); \
s.setLevel(castor::logbuf::T); \
return s; \
}
......
......@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* @(#)$RCSfile: logstream.h,v $ $Revision: 1.3 $ $Release$ $Date: 2004/06/08 08:48:48 $ $Author: sponcec3 $
* @(#)$RCSfile: logstream.h,v $ $Revision: 1.4 $ $Release$ $Date: 2004/07/07 16:01:08 $ $Author: sponcec3 $
*
*
*
......@@ -35,26 +35,22 @@
#include "osdep.h"
#include "castor/logbuf.h"
#define OPERATOR(T) \
logstream& operator<< (T var) { \
if (m_minLevel <= m_curLevel) { \
*((std::ostream*)this) << var; \
} \
return *this; \
#define OPERATOR(T) \
logstream& operator<< (T var) { \
*((std::ostream*)this) << var; \
return *this; \
}
#define OPERATORINT(T) \
logstream& operator<< (T var) { \
if (m_minLevel <= m_curLevel) { \
if (m_isIP) { \
m_isIP = false; \
printIP(var); \
} else if (m_isTimeStamp) { \
m_isTimeStamp = false; \
printTimeStamp(var); \
} else { \
this->std::ostream::operator<<(var); \
} \
if (m_isIP) { \
m_isIP = false; \
printIP(var); \
} else if (m_isTimeStamp) { \
m_isTimeStamp = false; \
printTimeStamp(var); \
} else { \
this->std::ostream::operator<<(var); \
} \
return *this; \
}
......@@ -64,43 +60,21 @@
namespace castor {
class logstream : virtual public std::ostream {
public:
/**
* The different possible level of output
*/
typedef enum _Level_ {
NIL = 0,
VERBOSE,
DEBUG,
INFO,
WARNING,
ERROR,
FATAL,
ALWAYS,
NUM_LEVELS
} Level;
public:
/**
* constructor
*/
explicit logstream(const char* p, Level l = INFO) :
explicit logstream(std::string name) :
std::ostream(0),
m_logbuf(),
m_minLevel(l),
m_curLevel(INFO),
m_logbuf(name),
m_isIP(false),
m_isTimeStamp(false) {
// Deal with the buffer
this->init(&m_logbuf);
if (!m_logbuf.open(p, std::ios::app | std::ios_base::out)) {
this->setstate(ios_base::failbit);
}
}
}
/**
* @brief Close the file.
*
......@@ -108,14 +82,12 @@ namespace castor {
* fails, @c failbit is set in the stream's error state.
*/
void close() {
if (!m_logbuf.close()) {
this->setstate(ios_base::failbit);
}
m_logbuf.sync();
}
public:
/**
* Set of operators of this stream
* Set of overwritten operators of this stream
*/
OPERATOR(char);
OPERATOR(unsigned char);
......@@ -147,15 +119,14 @@ namespace castor {
*/
logstream& operator<< (std::ostream& (&f)(std::ostream&)) {
if (&f == (std::ostream& (&)(std::ostream&))std::endl)
m_logbuf.setNewLine();
f(*this);
m_logbuf.sync();
return *this;
}
/**
* set current output level
*/
void setLevel(Level l) { m_curLevel = l; }
void setLevel(logbuf::Level l) { m_logbuf.setLevel(l); }
/**
* set isIp
......@@ -202,18 +173,6 @@ namespace castor {
*/
castor::logbuf m_logbuf;
/**
* The current minimum level of output for the stream
* everything under it will not be output