1 // Copyright (C) 2004 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License.
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
22 // File : LocalTraceCollector.cxx
23 // Author : Paul RASCLE (EDF)
35 #include "SALOMETraceCollector.hxx"
36 #include "LocalTrace_WaitForServerReadiness.hxx"
37 //#include "SALOME_Log.hxx"
38 #include <SALOMEconfig.h>
39 #include CORBA_CLIENT_HEADER(Logger)
41 // Class attributes initialisation, for class method SALOMETraceCollector::run
43 SALOMETraceCollector* SALOMETraceCollector::_singleton = 0;
44 pthread_mutex_t SALOMETraceCollector::_singletonMutex;
45 int SALOMETraceCollector::_threadToClose = 0;
46 pthread_t SALOMETraceCollector::_threadId = 0; // used to control single run
47 int SALOMETraceCollector::_toFile = 0;
48 std::string SALOMETraceCollector::_fileName = "";
49 CORBA::ORB_ptr SALOMETraceCollector::_orb = 0;
51 // ============================================================================
53 * guarantees a unique object instance of the class (singleton thread safe)
54 * a separate thread for loop to print traces is launched.
55 * \param typeTrace 0=standard out, 1=file(/tmp/tracetest.log), 2=CORBA log
56 * If typeTrace=0, checks environment for "SALOME_trace". Test values in
57 * the following order:
58 * - "local" standard out
59 * - "with_logger" CORBA log
60 * - anything else is kept as a file name
62 // ============================================================================
64 SALOMETraceCollector* SALOMETraceCollector::instance(CORBA::ORB_ptr theOrb,
67 if (_singleton == 0) // no need of lock when singleton already exists
70 ret = pthread_mutex_lock(&_singletonMutex); // acquire lock to be alone
71 if (_singleton == 0) // another thread may have got
72 { // the lock after the first test
73 _singleton = new SALOMETraceCollector();
75 _fileName = "/tmp/tracetest.log";
78 if (typeTrace) // caller sets a value different from default=0
80 else // check environment
82 char* traceKind = getenv("SALOME_trace");
83 //cout<<"SALOME_trace="<<traceKind<<endl;
86 if (strcmp(traceKind,"local")==0) _toFile=0;
87 else if (strcmp(traceKind,"with_logger")==0) _toFile=2;
91 _fileName = traceKind;
95 //cout <<"_toFile: "<<_toFile<<" _fileName: "<<_fileName<<endl;
97 pthread_t traceThread;
99 int re2 = pthread_create(&traceThread, NULL,
100 SALOMETraceCollector::run, (void *)bid);
102 ret = pthread_mutex_unlock(&_singletonMutex); // release lock
107 // ============================================================================
109 * In a separate thread, loop to print traces.
110 * Mutex garantees intialisation on instance method is done and only one run
111 * allowed (double check ...)
112 * Loop until there is no more buffer to print,
113 * and no ask for end from destructor.
114 * Get a buffer. If type = ABORT then exit application with message.
116 // ============================================================================
118 void* SALOMETraceCollector::run(void *bid)
121 int ret = pthread_mutex_lock(&_singletonMutex); // acquire lock to be alone
122 if (! _threadId) // only one run
125 _threadId = pthread_self();
127 else cout << "----- Comment est-ce possible de passer la ? -------" <<endl;
128 ret = pthread_mutex_unlock(&_singletonMutex); // release lock
132 _threadId = pthread_self();
133 LocalTraceBufferPool* myTraceBuffer = LocalTraceBufferPool::instance();
134 LocalTrace_TraceInfo myTrace;
136 // if trace in file requested, opens a file with append mode
137 // so, several processes can share the same file
138 // if CORBA collection requested, wait for Logger server readiness
141 SALOME_Logger::Logger_var m_pInterfaceLogger;
142 CORBA::Object_var obj;
146 case 1 : // --- trace to file
148 const char *fileName = _fileName.c_str();
149 traceFile.open(fileName, ios::out | ios::app);
152 cerr << "impossible to open trace file "<< fileName << endl;
157 case 2 : // --- trace collection via CORBA
158 obj = LocalTrace_WaitForServerReadiness(_orb,"Logger");
159 if (!CORBA::is_nil(obj))
160 m_pInterfaceLogger = SALOME_Logger::Logger::_narrow(obj);
161 if (CORBA::is_nil(m_pInterfaceLogger))
163 cerr << "Logger server not found ! Abort" << endl;
169 CORBA::String_var LogMsg =
170 CORBA::string_dup("\n---Init logger trace---\n");
171 m_pInterfaceLogger->putMessage(LogMsg);
172 //cout << " Logger server found" << endl;
175 case 0 : ; // --- trace to standard output
176 default : // --- on standard output, too
180 // Loop until there is no more buffer to print,
181 // and no ask for end from destructor.
183 while ((!_threadToClose) || myTraceBuffer->toCollect() )
185 int fullBuf = myTraceBuffer->retrieve(myTrace);
186 if (myTrace.traceType == ABORT_MESS)
190 case 2 : // --- trace collection via CORBA
192 stringstream abortMessage("");
193 abortMessage << "INTERRUPTION from thread "
194 << myTrace.threadId << " : " << myTrace.trace;
195 CORBA::String_var LogMsg =
196 CORBA::string_dup(abortMessage.str().c_str());
197 m_pInterfaceLogger->putMessage(LogMsg);
201 case 1 : // --- trace to file
202 traceFile << "INTERRUPTION from thread " << myTrace.threadId
203 << " : " << myTrace.trace;
206 case 0 : // --- trace to standard output
207 default : // --- on standard output, too
209 cerr << "INTERRUPTION from thread " << myTrace.threadId
210 << " : " << myTrace.trace;
220 case 2 : // --- trace collection via CORBA
222 stringstream aMessage("");
223 aMessage << "th. " << myTrace.threadId
224 << " " << myTrace.trace;
225 CORBA::String_var LogMsg =
226 CORBA::string_dup(aMessage.str().c_str());
227 m_pInterfaceLogger->putMessage(LogMsg);
230 case 1 : // --- trace to file
231 traceFile << "th. " << myTrace.threadId
232 << " " << myTrace.trace;
234 case 0 : // --- trace to standard output
235 default : // --- on standard output, too
236 cout << "th. " << myTrace.threadId << " " << myTrace.trace;
242 if (_toFile==1) traceFile.close();
247 // ============================================================================
249 * Destructor: wait until printing thread ends (SALOMETraceCollector::run)
251 // ============================================================================
253 SALOMETraceCollector:: ~SALOMETraceCollector()
255 LocalTraceBufferPool* myTraceBuffer = LocalTraceBufferPool::instance();
257 myTraceBuffer->insert(NORMAL_MESS,"end of trace "); //needed to wake up thread
260 int ret = pthread_join(_threadId, NULL);
261 if (ret) cout << "error close SALOMETraceCollector : "<< ret << endl;
262 else cout << "SALOMETraceCollector destruction OK" << endl;
264 delete myTraceBuffer;
267 // ============================================================================
269 * Constructor: no need of LocalTraceBufferPool object initialization here,
270 * thread safe singleton used in LocalTraceBufferPool::instance()
272 // ============================================================================
274 SALOMETraceCollector::SALOMETraceCollector()