#include "LocalTraceBufferPool.hxx"
#include "utilities.h"
+// In case of truncated message, end of trace contains "...\n\0"
+#define TRUNCATED_MESSAGE "...\n"
+#define MAXMESS_LENGTH MAX_TRACE_LENGTH-5
+
using namespace std;
LocalTraceBufferPool* LocalTraceBufferPool::_singleton = 0;
strncpy(_myBuffer[myInsertPos%TRACE_BUFFER_SIZE].trace,
msg,
- MAX_TRACE_LENGTH-1); // last char always 0 even if msg too long
- _myBuffer[myInsertPos%TRACE_BUFFER_SIZE].threadId = pthread_self(); // thread id
+ MAXMESS_LENGTH); // last chars always "...\n\0" if msg too long
+ _myBuffer[myInsertPos%TRACE_BUFFER_SIZE].threadId =pthread_self();//thread id
_myBuffer[myInsertPos%TRACE_BUFFER_SIZE].traceType = traceType;
_myBuffer[myInsertPos%TRACE_BUFFER_SIZE].position = myMessageNumber;
// increment the free buffer semaphore
// (if previously 0, awake one of the threads waiting to put a trace, if any)
- // there is no way to preserve the order of waiting threads if several threads
- // are waiting to put a trace: the waken up thread is not necessarily the
- // first thread to wait.
+ // there is no way to preserve the order of waiting threads if several
+ // threads are waiting to put a trace: the waken up thread is not
+ // necessarily the first thread to wait.
ret = sem_post(&_freeBufferSemaphore);
LocalTraceBufferPool::LocalTraceBufferPool()
{
- cout << "LocalTraceBufferPool::LocalTraceBufferPool()" << endl;
+ //cout << "LocalTraceBufferPool::LocalTraceBufferPool()" << endl;
_insertPos = ULONG_MAX; // first increment will give 0
_retrievePos = ULONG_MAX;
_position=0; // first message will have number = 1
memset(_myBuffer, 0, sizeof(_myBuffer)); // to guarantee end of strings = 0
+ for (int i=0; i<TRACE_BUFFER_SIZE; i++)
+ strcpy(&(_myBuffer[i].trace[MAXMESS_LENGTH]),TRUNCATED_MESSAGE);
int ret;
ret=sem_init(&_freeBufferSemaphore, 0, TRACE_BUFFER_SIZE); // all buffer free
if (ret!=0) IMMEDIATE_ABORT(ret);
// $Header$
#include <iostream>
+#include <sstream>
#include <fstream>
+#include <cstdlib>
+#include <CORBA.h>
+
+using namespace std;
#include "LocalTraceCollector.hxx"
+#include "LocalTrace_WaitForServerReadiness.hxx"
+//#include "SALOME_Log.hxx"
+#include <SALOMEconfig.h>
+#include CORBA_CLIENT_HEADER(Logger)
-using namespace std;
+// Class attributes initialisation, for class method LocalTraceCollector::run
LocalTraceCollector* LocalTraceCollector::_singleton = 0;
pthread_mutex_t LocalTraceCollector::_singletonMutex;
int LocalTraceCollector::_threadToClose = 0;
-pthread_t LocalTraceCollector::_threadId = 0;
-int LocalTraceCollector::_toFile = 0; // public, set by user
+pthread_t LocalTraceCollector::_threadId = 0; // used to control single run
+int LocalTraceCollector::_toFile = 0;
+std::string LocalTraceCollector::_fileName = "";
+CORBA::ORB_ptr LocalTraceCollector::_orb = 0;
// ============================================================================
/*!
* guarantees a unique object instance of the class (singleton thread safe)
* a separate thread for loop to print traces is launched.
+ * \param typeTrace 0=standard out, 1=file(/tmp/tracetest.log), 2=CORBA log
+ * If typeTrace=0, checks environment for "SALOME_trace". Test values in
+ * the following order:
+ * - "local" standard out
+ * - "with_logger" CORBA log
+ * - anything else is kept as a file name
*/
// ============================================================================
-LocalTraceCollector* LocalTraceCollector::instance()
+LocalTraceCollector* LocalTraceCollector::instance(CORBA::ORB_ptr theOrb,
+ int typeTrace)
{
if (_singleton == 0) // no need of lock when singleton already exists
{
ret = pthread_mutex_lock(&_singletonMutex); // acquire lock to be alone
if (_singleton == 0) // another thread may have got
{ // the lock after the first test
- _singleton = new LocalTraceCollector();
+ _singleton = new LocalTraceCollector();
+
+ _fileName = "/tmp/tracetest.log";
+ _toFile=0;
+ _orb = theOrb;
+ if (typeTrace) // caller sets a value different from default=0
+ _toFile = typeTrace;
+ else // check environment
+ {
+ char* traceKind = getenv("SALOME_trace");
+ //cout<<"SALOME_trace="<<traceKind<<endl;
+ if (traceKind)
+ {
+ if (strcmp(traceKind,"local")==0) _toFile=0;
+ else if (strcmp(traceKind,"with_logger")==0) _toFile=2;
+ else
+ {
+ _toFile=1;
+ _fileName = traceKind;
+ }
+ }
+ }
+ //cout <<"_toFile: "<<_toFile<<" _fileName: "<<_fileName<<endl;
+
pthread_t traceThread;
int bid;
- int ret = pthread_create(&traceThread, NULL,
+ int re2 = pthread_create(&traceThread, NULL,
LocalTraceCollector::run, (void *)bid);
}
ret = pthread_mutex_unlock(&_singletonMutex); // release lock
// ============================================================================
/*!
* In a separate thread, loop to print traces.
+ * Mutex garantees intialisation on instance method is done and only one run
+ * allowed (double check ...)
* Loop until there is no more buffer to print,
* and no ask for end from destructor.
* Get a buffer. If type = ABORT then exit application with message.
void* LocalTraceCollector::run(void *bid)
{
+ int isOKtoRun = 0;
+ int ret = pthread_mutex_lock(&_singletonMutex); // acquire lock to be alone
if (! _threadId) // only one run
+ {
+ isOKtoRun = 1;
+ _threadId = pthread_self();
+ }
+ else cout << "----- Comment est-ce possible de passer la ? -------" <<endl;
+ ret = pthread_mutex_unlock(&_singletonMutex); // release lock
+
+ if (isOKtoRun)
{
_threadId = pthread_self();
LocalTraceBufferPool* myTraceBuffer = LocalTraceBufferPool::instance();
// if trace in file requested, opens a file with append mode
// so, several processes can share the same file
+ // if CORBA collection requested, wait for Logger server readiness
ofstream traceFile;
- if (_toFile)
+ SALOME_Logger::Logger_var m_pInterfaceLogger;
+ CORBA::Object_var obj;
+
+ switch (_toFile)
{
- const char *fileName = "/tmp/tracetest.log";
- traceFile.open(fileName, ios::out | ios::app);
- if (!traceFile)
+ case 1 : // --- trace to file
+ {
+ const char *fileName = _fileName.c_str();
+ traceFile.open(fileName, ios::out | ios::app);
+ if (!traceFile)
+ {
+ cerr << "impossible to open trace file "<< fileName << endl;
+ exit (1);
+ }
+ }
+ break;
+ case 2 : // --- trace collection via CORBA
+ obj = LocalTrace_WaitForServerReadiness(_orb,"Logger");
+ if (!CORBA::is_nil(obj))
+ m_pInterfaceLogger = SALOME_Logger::Logger::_narrow(obj);
+ if (CORBA::is_nil(m_pInterfaceLogger))
{
- cerr << "impossible to open trace file "<< fileName << endl;
- exit (1);
+ cerr << "Logger server not found ! Abort" << endl;
+ cerr << flush ;
+ exit(1);
+ }
+ else
+ {
+ CORBA::String_var LogMsg =
+ CORBA::string_dup("\n---Init logger trace---\n");
+ m_pInterfaceLogger->putMessage(LogMsg);
+ //cout << " Logger server found" << endl;
}
+ break;
+ case 0 : ; // --- trace to standard output
+ default : // --- on standard output, too
+ break;
}
// Loop until there is no more buffer to print,
int fullBuf = myTraceBuffer->retrieve(myTrace);
if (myTrace.traceType == ABORT_MESS)
{
- cout << flush ;
- cerr << "INTERRUPTION from thread " << myTrace.threadId
- << " : " << myTrace.trace;
- cerr << flush ;
- exit(1);
+ switch (_toFile)
+ {
+ case 2 : // --- trace collection via CORBA
+ {
+ stringstream abortMessage("");
+ abortMessage << "INTERRUPTION from thread "
+ << myTrace.threadId << " : " << myTrace.trace;
+ CORBA::String_var LogMsg =
+ CORBA::string_dup(abortMessage.str().c_str());
+ m_pInterfaceLogger->putMessage(LogMsg);
+ exit(1);
+ }
+ break;
+ case 1 : // --- trace to file
+ traceFile << "INTERRUPTION from thread " << myTrace.threadId
+ << " : " << myTrace.trace;
+ traceFile.close();
+ // no break here !
+ case 0 : // --- trace to standard output
+ default : // --- on standard output, too
+ cout << flush ;
+ cerr << "INTERRUPTION from thread " << myTrace.threadId
+ << " : " << myTrace.trace;
+ cerr << flush ;
+ exit(1);
+ break;
+ }
}
else
{
- if (_toFile)
- traceFile << myTrace.position << " thread " << myTrace.threadId
- << " full " << fullBuf <<" " << myTrace.trace;
- else
- cout << " th. " << myTrace.threadId
- << " " << fullBuf <<" " << myTrace.trace;
+ switch (_toFile)
+ {
+ case 2 : // --- trace collection via CORBA
+ {
+ stringstream aMessage("");
+ aMessage << "th. " << myTrace.threadId
+ << " " << myTrace.trace;
+ CORBA::String_var LogMsg =
+ CORBA::string_dup(aMessage.str().c_str());
+ m_pInterfaceLogger->putMessage(LogMsg);
+ }
+ break;
+ case 1 : // --- trace to file
+ traceFile << "th. " << myTrace.threadId
+ << " " << myTrace.trace;
+ break;
+ case 0 : // --- trace to standard output
+ default : // --- on standard output, too
+ cout << "th. " << myTrace.threadId << " " << myTrace.trace;
+ break;
+ }
}
}
- if (_toFile) traceFile.close();
+ if (_toFile==1) traceFile.close();
}
pthread_exit(NULL);
- //return 0; // just for warning
}
// ============================================================================
// ============================================================================
/*!
- * Constructor: need of LocalTraceBufferPool object initialization here,
- * before creation of thread that access LocalTraceBufferPool: if done after,
- * simutaneous call to LocalTraceBufferPool::instance() from different
- * threads may lead to multiple instances (instance method not mutex protected)
+ * Constructor: no need of LocalTraceBufferPool object initialization here,
+ * thread safe singleton used in LocalTraceBufferPool::instance()
*/
// ============================================================================
LocalTraceCollector::LocalTraceCollector()
{
_threadId=0;
- LocalTraceBufferPool *myTraceBuffer = LocalTraceBufferPool::instance();
}
#ifndef _LOCALTRACECOLLECTOR_HXX_
#define _LOCALTRACECOLLECTOR_HXX_
+#include <string>
+#include <CORBA.h>
#include "LocalTraceBufferPool.hxx"
class LocalTraceCollector
{
public:
- static LocalTraceCollector* instance();
+ static LocalTraceCollector* instance(CORBA::ORB_ptr theOrb, int typeTrace=0);
static void *run(void *bid);
~LocalTraceCollector();
- static int _threadToClose;
- static int _toFile;
protected:
LocalTraceCollector();
private:
+ static int _threadToClose;
+ static int _toFile;
static LocalTraceCollector* _singleton;
static pthread_mutex_t _singletonMutex;
static pthread_t _threadId;
+ static std::string _fileName;
+ static CORBA::ORB_ptr _orb;
};
#endif
--- /dev/null
+// Copyright (C) 2004 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
+//
+//
+//
+// File : LocalTrace_WaitForServerReadiness.cxx
+// Author : Paul RASCLE (EDF)
+// Module : KERNEL
+// $Header$
+
+#include "LocalTrace_WaitForServerReadiness.hxx"
+#include <iostream>
+#include <ctime>
+
+using namespace std;
+
+// ============================================================================
+/*!
+ * Wait until a server is registered in naming service.
+ * \param serverName name of the server to find.
+ * When SALOME_NamingService is available,
+ * use NamingService_WaitForServerReadiness instead.
+ * This function is needed when macro MESSAGE used by SALOME_NamingService
+ * is not available (inside LocalTrace methods, for instance !).
+ * Direct access to CORBA Name Service. Look for serverName at Name service
+ * Root without extensions.
+ */
+// ============================================================================
+
+CORBA::Object_ptr LocalTrace_WaitForServerReadiness(CORBA::ORB_ptr orb,
+ string serverName)
+{
+ long TIMESleep = 250000000;
+ int NumberOfTries = 40;
+
+ timespec ts_req;
+ ts_req.tv_nsec=TIMESleep;
+ ts_req.tv_sec=0;
+ timespec ts_rem;
+ ts_rem.tv_nsec=0;
+ ts_rem.tv_sec=0;
+
+ CORBA::Object_var obj;
+
+ try
+ {
+ // NB. You can't use SALOME_NamingService class because
+ // it uses MESSAGE macro
+ // Otherwise, you will get segmentation fault.
+
+ CosNaming::NamingContext_var inc;
+ CosNaming::Name name;
+ name.length(1);
+ name[0].id = CORBA::string_dup(serverName.c_str());
+ CORBA::Object_var theObj;
+
+ for (int itry=0; itry < NumberOfTries; itry++)
+ {
+ try
+ {
+ if(!CORBA::is_nil(orb))
+ theObj = orb->resolve_initial_references("NameService");
+ if (!CORBA::is_nil(theObj))
+ inc = CosNaming::NamingContext::_narrow(theObj);
+ }
+ catch( CORBA::COMM_FAILURE& )
+ {
+ cout << "LocalTrace_WaitForServerReadiness: "
+ << "CORBA::COMM_FAILURE: "
+ << "Unable to contact the Naming Service" << endl;
+ }
+ catch(...)
+ {
+ cout << "LocalTrace_WaitForServerReadiness: "
+ << "Unknown exception dealing with Naming Service" << endl;
+ }
+
+ if(!CORBA::is_nil(inc))
+ {
+ obj = inc->resolve(name);
+ if (!CORBA::is_nil(obj))
+ {
+ cout << "LocalTrace_WaitForServerReadiness: "
+ << serverName << " found in CORBA Name Service" << endl;
+ break;
+ }
+ }
+ int a = nanosleep(&ts_req,&ts_rem);
+ cout << "LocalTrace_WaitForServerReadiness: retry look for"
+ << serverName << endl;
+ }
+ }
+ catch (const CosNaming::NamingContext::NotFound&)
+ {
+ cout << "Caught exception: Naming Service can't found Logger";
+ }
+ catch (CORBA::COMM_FAILURE&)
+ {
+ cout << "Caught CORBA::SystemException CommFailure.";
+ }
+ catch (CORBA::SystemException&)
+ {
+ cout << "Caught CORBA::SystemException.";
+ }
+ catch (CORBA::Exception&)
+ {
+ cout << "Caught CORBA::Exception.";
+ }
+ catch (...)
+ {
+ cout << "Caught unknown exception.";
+ }
+ return obj._retn();
+}
+
--- /dev/null
+// Copyright (C) 2004 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
+//
+//
+//
+// File : LocalTrace_WaitForServerReadiness.hxx
+// Author : Paul RASCLE (EDF)
+// Module : KERNEL
+// $Header$
+
+#ifndef _LOCALTRACE_WAITFORSERVERREADINESS_HXX_
+#define _LOCALTRACE_WAITFORSERVERREADINESS_HXX_
+
+#include <CORBA.h>
+#include <string>
+
+CORBA::Object_ptr LocalTrace_WaitForServerReadiness(CORBA::ORB_ptr theOrb,
+ std::string serverName);
+
+#endif
# header files
EXPORT_HEADERS= utilities.h \
LocalTraceBufferPool.hxx \
- LocalTraceCollector.hxx
+ LocalTraceCollector.hxx \
+ LocalTrace_WaitForServerReadiness.hxx
EXPORT_PYSCRIPTS =
LIB = libSALOMELocalTrace.la
LIB_SRC = LocalTraceCollector.cxx \
- LocalTraceBufferPool.cxx
+ LocalTraceBufferPool.cxx \
+ LocalTrace_WaitForServerReadiness.cxx
+LIB_CLIENT_IDL = Logger.idl
LDFLAGS+=
@CONCLUDE@
+++ /dev/null
-// SALOME_LocalTrace : log on local machine
-//
-// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
-// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License.
-//
-// This library 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
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-//
-// See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
-//
-//
-//
-// File : SALOME_Log.hxx
-// Author : Vasily Rusyaev, Paul RASCLE, EDF
-// Module : KERNEL
-// $Header$
-
-#include <string>
-#include <iostream>
-
-#include "SALOME_Log.hxx"
-using namespace std;
-
-SALOME_Log* SALOME_Log::_singleton = 0;
-
-// log line size: if too short, log line is truncated, without crash...
-char SALOME_LogStr[1024];
-
-SALOME_Log::SALOME_Log(): ostrstream(SALOME_LogStr,sizeof(SALOME_LogStr))
-{
-}
-
-SALOME_Log::~SALOME_Log()
-{
-}
-
-SALOME_Log* SALOME_Log::Instance()
-{
- if (_singleton == 0) _singleton = new SALOME_Log();
- return _singleton;
-}
-
-void SALOME_Log::putMessage(std::ostream& msg)
-{
- cout << std::flush;
- cerr <<str() << std::flush;
- rdbuf()->freeze(false);
- seekp(0);
-}
-
-
+++ /dev/null
-// SALOME Utils : general SALOME's definitions and tools
-//
-// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
-// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License.
-//
-// This library 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
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-//
-// See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
-//
-//
-//
-// File : SALOME_Log.hxx
-// Author : Vasily Rusyaev (OCN), Paul RASCLE (EDF)
-// Module : KERNEL
-// $Header$
-
-#ifndef _SALOME_LOG_HXX_
-#define _SALOME_LOG_HXX_
-
-//these declarations for files don't using OCC includes (for example HDF)
-# ifdef WNT
-
-# ifndef Standard_EXPORT
-# define Standard_EXPORT __declspec( dllexport )
-// For global variables :
-# define Standard_EXPORTEXTERN __declspec( dllexport ) extern
-# define Standard_EXPORTEXTERNC extern "C" __declspec( dllexport )
-# endif /* Standard_EXPORT */
-
-# ifndef Standard_IMPORT
-# define Standard_IMPORT __declspec( dllimport ) extern
-# define Standard_IMPORTC extern "C" __declspec( dllimport )
-# endif /* Standard_IMPORT */
-
-# else /* WNT */
-
-# ifndef Standard_EXPORT
-# define Standard_EXPORT
-// For global variables :
-# define Standard_EXPORTEXTERN extern
-# define Standard_EXPORTEXTERNC extern "C"
-# endif /* Standard_EXPORT */
-
-# ifndef Standard_IMPORT
-# define Standard_IMPORT extern
-# define Standard_IMPORTC extern "C"
-# endif /* Standard_IMPORT */
-
-# endif /* WNT */
-
-
-
-#include <iostream>
-#include <strstream>
-
-using namespace std;
-
-class SALOME_Log : public ostrstream
-{
-private:
- static SALOME_Log* _singleton;
-protected:
- //disable creation of instances: force use static SALOME_Log& Instance()
- SALOME_Log();
-public:
- virtual ~SALOME_Log();
- static Standard_EXPORT SALOME_Log* Instance();
- Standard_EXPORT void putMessage(std::ostream& msg);
-};
-
-#define SLog SALOME_Log::Instance()
-
-#endif