]> SALOME platform Git repositories - modules/kernel.git/blob - src/SALOMELocalTrace/LocalTraceCollector.cxx
Salome HOME
PR: mergefrom_BR_CCRT_11Nov04
[modules/kernel.git] / src / SALOMELocalTrace / LocalTraceCollector.cxx
1 //  Copyright (C) 2004  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
3 // 
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. 
8 // 
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. 
13 // 
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 
17 // 
18 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
19 //
20 //
21 //
22 //  File   : LocalTraceCollector.cxx
23 //  Author : Paul RASCLE (EDF)
24 //  Module : KERNEL
25 //  $Header$
26
27 #include <iostream>
28 #include <sstream>
29 #include <fstream>
30 #include <cstdlib>
31 #include <CORBA.h>
32
33 using namespace std;
34
35 #include "LocalTraceCollector.hxx"
36 #include "LocalTrace_WaitForServerReadiness.hxx"
37 //#include "SALOME_Log.hxx"
38 #include <SALOMEconfig.h>
39 #include CORBA_CLIENT_HEADER(Logger)
40
41 // Class attributes initialisation, for class method LocalTraceCollector::run
42
43 LocalTraceCollector* LocalTraceCollector::_singleton = 0;
44 pthread_mutex_t LocalTraceCollector::_singletonMutex;
45 int LocalTraceCollector::_threadToClose = 0;
46 pthread_t LocalTraceCollector::_threadId = 0; // used to control single run
47 int LocalTraceCollector::_toFile = 0;
48 std::string LocalTraceCollector::_fileName = "";
49 CORBA::ORB_ptr LocalTraceCollector::_orb = 0;
50
51 // ============================================================================
52 /*!
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
61  */
62 // ============================================================================
63
64 LocalTraceCollector* LocalTraceCollector::instance(CORBA::ORB_ptr theOrb,
65                                                    int typeTrace)
66 {
67   if (_singleton == 0) // no need of lock when singleton already exists
68     {
69       int ret;
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 LocalTraceCollector();
74
75           _fileName = "/tmp/tracetest.log";
76           _toFile=0;
77           _orb = theOrb;
78           if (typeTrace)       // caller sets a value different from default=0
79             _toFile = typeTrace; 
80           else                 // check environment
81             {
82               char* traceKind = getenv("SALOME_trace");
83               //cout<<"SALOME_trace="<<traceKind<<endl;
84               if (traceKind)
85                 {
86                   if (strcmp(traceKind,"local")==0) _toFile=0;
87                   else if (strcmp(traceKind,"with_logger")==0) _toFile=2;
88                   else
89                     {
90                       _toFile=1;
91                       _fileName = traceKind;
92                     }       
93                 }
94             }
95           //cout <<"_toFile: "<<_toFile<<" _fileName: "<<_fileName<<endl;
96
97           pthread_t traceThread;
98           int bid;
99           int re2 = pthread_create(&traceThread, NULL,
100                                    LocalTraceCollector::run, (void *)bid);
101         }
102       ret = pthread_mutex_unlock(&_singletonMutex); // release lock
103     }
104   return _singleton;
105 }
106
107 // ============================================================================
108 /*!
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.
115  */
116 // ============================================================================
117
118 void* LocalTraceCollector::run(void *bid)
119 {
120   int isOKtoRun = 0;
121   int ret = pthread_mutex_lock(&_singletonMutex); // acquire lock to be alone
122   if (! _threadId)  // only one run
123     {
124       isOKtoRun = 1;
125       _threadId = pthread_self();
126     }
127   else cout << "----- Comment est-ce possible de passer la ? -------" <<endl;
128   ret = pthread_mutex_unlock(&_singletonMutex); // release lock
129
130   if (isOKtoRun)
131     { 
132       _threadId = pthread_self();
133       LocalTraceBufferPool* myTraceBuffer = LocalTraceBufferPool::instance();
134       LocalTrace_TraceInfo myTrace;
135
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
139
140       ofstream traceFile;
141       SALOME_Logger::Logger_var m_pInterfaceLogger;
142       CORBA::Object_var obj;
143
144       switch (_toFile)
145         {
146         case 1 :  // --- trace to file
147           {
148             const char *fileName = _fileName.c_str();
149             traceFile.open(fileName, ios::out | ios::app);
150             if (!traceFile)
151               {
152                 cerr << "impossible to open trace file "<< fileName << endl;
153                 exit (1);
154               }
155           }
156           break;
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))
162             {
163               cerr << "Logger server not found ! Abort" << endl;
164               cerr << flush ; 
165               exit(1);
166             } 
167           else
168             {
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;
173             }
174           break;
175         case 0 : ; // --- trace to standard output
176         default :  // --- on standard output, too
177           break;
178         }
179
180       // Loop until there is no more buffer to print,
181       // and no ask for end from destructor.
182
183       while ((!_threadToClose) || myTraceBuffer->toCollect() )
184         {
185           int fullBuf = myTraceBuffer->retrieve(myTrace);
186           if (myTrace.traceType == ABORT_MESS)
187             {
188               switch (_toFile)
189                 {
190                 case 2 :  // --- trace collection via CORBA
191                   {
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);
198                     exit(1);
199                   }
200                   break;
201                 case 1 :  // --- trace to file
202                   traceFile << "INTERRUPTION from thread " << myTrace.threadId
203                             << " : " <<  myTrace.trace;
204                   traceFile.close();
205                   // no break here !
206                 case 0 :  // --- trace to standard output
207                 default : // --- on standard output, too
208                   cout << flush ;
209                   cerr << "INTERRUPTION from thread " << myTrace.threadId
210                        << " : " <<  myTrace.trace;
211                   cerr << flush ; 
212                   exit(1);     
213                   break;
214                 }
215             }
216           else
217             {
218               switch (_toFile)
219                 {
220                 case 2 :  // --- trace collection via CORBA
221                   {
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);
228                   }
229                   break;
230                 case 1 :  // --- trace to file
231                   traceFile << "th. " << myTrace.threadId
232                             << " " << myTrace.trace;
233                   break;
234                 case 0 :  // --- trace to standard output
235                 default : // --- on standard output, too
236                   cout << "th. " << myTrace.threadId << " " << myTrace.trace;
237                   break;
238                 }
239             }
240         }
241
242       if (_toFile==1) traceFile.close();
243     }
244   pthread_exit(NULL);
245 }
246
247 // ============================================================================
248 /*!
249  *  Destructor: wait until printing thread ends (LocalTraceCollector::run)
250  */
251 // ============================================================================
252
253 LocalTraceCollector:: ~LocalTraceCollector()
254 {
255   _threadToClose = 1;
256   if (_threadId)
257     {
258       int ret = pthread_join(_threadId, NULL);
259       if (ret) cout << "error close LocalTraceCollector : "<< ret << endl;
260       else cout << "LocalTraceCollector destruction OK" << endl;
261     }
262   LocalTraceBufferPool* myTraceBuffer = LocalTraceBufferPool::instance();
263   delete myTraceBuffer;
264 }
265
266 // ============================================================================
267 /*!
268  * Constructor: no need of LocalTraceBufferPool object initialization here,
269  * thread safe singleton used in LocalTraceBufferPool::instance()
270  */
271 // ============================================================================
272
273 LocalTraceCollector::LocalTraceCollector()
274 {
275   _threadId=0;
276 }
277
278