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 "TraceCollector_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 * This class replaces LocalTraceCollector, which is to use outside SALOME,
56 * guarantees a unique object instance of the class (singleton thread safe)
57 * a separate thread for loop to print traces is launched.
58 * \param typeTrace 0=standard out, 1=file(/tmp/tracetest.log), 2=CORBA log
59 * If typeTrace=0, checks environment for "SALOME_trace". Test values in
60 * the following order:
61 * - "local" standard out
62 * - "with_logger" CORBA log
63 * - anything else is kept as a file name
65 // ============================================================================
67 SALOMETraceCollector* SALOMETraceCollector::instance(CORBA::ORB_ptr theOrb,
70 if (_singleton == 0) // no need of lock when singleton already exists
73 ret = pthread_mutex_lock(&_singletonMutex); // acquire lock to be alone
74 if (_singleton == 0) // another thread may have got
75 { // the lock after the first test
76 _singleton = new SALOMETraceCollector();
78 _fileName = "/tmp/tracetest.log";
81 if (typeTrace) // caller sets a value different from default=0
83 else // check environment
85 char* traceKind = getenv("SALOME_trace");
86 //cout<<"SALOME_trace="<<traceKind<<endl;
89 if (strcmp(traceKind,"local")==0) _toFile=0;
90 else if (strcmp(traceKind,"with_logger")==0) _toFile=2;
94 _fileName = traceKind;
98 //cout <<"_toFile: "<<_toFile<<" _fileName: "<<_fileName<<endl;
100 pthread_t traceThread;
102 int re2 = pthread_create(&traceThread, NULL,
103 SALOMETraceCollector::run, (void *)bid);
105 ret = pthread_mutex_unlock(&_singletonMutex); // release lock
110 // ============================================================================
112 * In a separate thread, loop to print traces.
113 * Mutex garantees intialisation on instance method is done and only one run
114 * allowed (double check ...)
115 * Loop until there is no more buffer to print,
116 * and no ask for end from destructor.
117 * Get a buffer. If type = ABORT then exit application with message.
119 // ============================================================================
121 void* SALOMETraceCollector::run(void *bid)
124 int ret = pthread_mutex_lock(&_singletonMutex); // acquire lock to be alone
125 if (! _threadId) // only one run
128 _threadId = pthread_self();
130 else cout << "----- Comment est-ce possible de passer la ? -------" <<endl;
131 ret = pthread_mutex_unlock(&_singletonMutex); // release lock
135 _threadId = pthread_self();
136 LocalTraceBufferPool* myTraceBuffer = LocalTraceBufferPool::instance();
137 LocalTrace_TraceInfo myTrace;
139 // if trace in file requested, opens a file with append mode
140 // so, several processes can share the same file
141 // if CORBA collection requested, wait for Logger server readiness
144 SALOME_Logger::Logger_var m_pInterfaceLogger;
145 CORBA::Object_var obj;
149 case 1 : // --- trace to file
151 const char *fileName = _fileName.c_str();
152 traceFile.open(fileName, ios::out | ios::app);
155 cerr << "impossible to open trace file "<< fileName << endl;
160 case 2 : // --- trace collection via CORBA
161 obj = TraceCollector_WaitForServerReadiness(_orb,"Logger");
162 if (!CORBA::is_nil(obj))
163 m_pInterfaceLogger = SALOME_Logger::Logger::_narrow(obj);
164 if (CORBA::is_nil(m_pInterfaceLogger))
166 cerr << "Logger server not found ! Abort" << endl;
172 CORBA::String_var LogMsg =
173 CORBA::string_dup("\n---Init logger trace---\n");
174 m_pInterfaceLogger->putMessage(LogMsg);
175 //cout << " Logger server found" << endl;
178 case 0 : ; // --- trace to standard output
179 default : // --- on standard output, too
183 // Loop until there is no more buffer to print,
184 // and no ask for end from destructor.
186 while ((!_threadToClose) || myTraceBuffer->toCollect() )
188 int fullBuf = myTraceBuffer->retrieve(myTrace);
189 if (myTrace.traceType == ABORT_MESS)
193 case 2 : // --- trace collection via CORBA
195 stringstream abortMessage("");
196 abortMessage << "INTERRUPTION from thread "
197 << myTrace.threadId << " : " << myTrace.trace;
198 CORBA::String_var LogMsg =
199 CORBA::string_dup(abortMessage.str().c_str());
200 m_pInterfaceLogger->putMessage(LogMsg);
204 case 1 : // --- trace to file
205 traceFile << "INTERRUPTION from thread " << myTrace.threadId
206 << " : " << myTrace.trace;
209 case 0 : // --- trace to standard output
210 default : // --- on standard output, too
212 cerr << "INTERRUPTION from thread " << myTrace.threadId
213 << " : " << myTrace.trace;
223 case 2 : // --- trace collection via CORBA
225 stringstream aMessage("");
226 aMessage << "th. " << myTrace.threadId
227 << " " << myTrace.trace;
228 CORBA::String_var LogMsg =
229 CORBA::string_dup(aMessage.str().c_str());
230 m_pInterfaceLogger->putMessage(LogMsg);
233 case 1 : // --- trace to file
234 traceFile << "th. " << myTrace.threadId
235 << " " << myTrace.trace;
237 case 0 : // --- trace to standard output
238 default : // --- on standard output, too
239 cout << "th. " << myTrace.threadId << " " << myTrace.trace;
245 if (_toFile==1) traceFile.close();
250 // ============================================================================
252 * Destructor: wait until printing thread ends (SALOMETraceCollector::run)
254 // ============================================================================
256 SALOMETraceCollector:: ~SALOMETraceCollector()
258 LocalTraceBufferPool* myTraceBuffer = LocalTraceBufferPool::instance();
260 myTraceBuffer->insert(NORMAL_MESS,"end of trace "); //needed to wake up thread
263 int ret = pthread_join(_threadId, NULL);
264 if (ret) cout << "error close SALOMETraceCollector : "<< ret << endl;
265 else cout << "SALOMETraceCollector destruction OK" << endl;
267 delete myTraceBuffer;
270 // ============================================================================
272 * Constructor: no need of LocalTraceBufferPool object initialization here,
273 * thread safe singleton used in LocalTraceBufferPool::instance()
275 // ============================================================================
277 SALOMETraceCollector::SALOMETraceCollector()