Fix bizarre "delete[] fNames", where fNames is a *static*
[charm.git] / src / conv-perf / traceCore.C
1
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <errno.h>
5 #include <string.h>
6 #include <assert.h>
7
8 #include "converse.h"
9 #include "traceCore.h"
10 #include "traceCoreCommon.h"
11
12 #include "converseEvents.h"     //TODO: remove this hack for REGISTER_CONVESE
13 #include "charmEvents.h"        //TODO: remove this hack for REGISTER_CHARM
14 #include "machineEvents.h"      // for machine events
15
16 CpvExtern(double, _traceCoreInitTime);
17 CpvExtern(char*, _traceCoreRoot);
18 CpvExtern(int, _traceCoreBufferSize);
19 CpvExtern(TraceCore*, _traceCore);
20 CpvStaticDeclare(int ,staticNumEntries);
21
22 /* Trace Timer */
23 #define  TRACE_CORE_TIMER   CmiWallTimer
24 inline double TraceCoreTimer() { return TRACE_CORE_TIMER() - CpvAccess(_traceCoreInitTime); }
25
26 /***************** Class TraceCore Definition *****************/
27 TraceCore::TraceCore(char** argv)
28 {
29         int binary = CmiGetArgFlag(argv,"+binary-trace");
30         traceLogger = new TraceLogger(CpvAccess(_traceCoreRoot), binary);
31         CpvInitialize(int ,staticNumEntries);
32         CpvAccess(staticNumEntries)=0;
33         if(CpvAccess(_traceCoreOn) == 0){
34                 traceCoreOn=0;
35                 return;
36         }
37         traceCoreOn=1;
38         //CmiPrintf("[%d]In TraceCore Constructor\n",CmiMyPe());
39         startPtc();
40         REGISTER_CONVERSE
41         REGISTER_CHARM
42         REGISTER_MACHINE
43         closePtc();
44 }
45
46 TraceCore::~TraceCore()
47 { if(traceLogger) delete traceLogger; }
48
49 void TraceCore::RegisterLanguage(int lID, char* ln)
50 {
51         //CmiPrintf("Register Language called for %s at %d \n",ln,lID);
52   if(traceCoreOn == 0){
53                 return;
54   }
55   traceLogger->RegisterLanguage(lID, ln);
56
57   // code for ptc file generation
58   if(maxlID < lID){
59         maxlID = lID;
60   }
61   lIDList[numLangs] = lID;
62   lNames[numLangs] = new char[strlen(ln)+1];
63   sprintf(lNames[numLangs],"%s",ln);
64   numLangs++;
65
66  }
67
68 struct TraceCoreEvent *insert_TraceCoreEvent(struct TraceCoreEvent *root,int eID){
69         struct TraceCoreEvent *p;
70         
71         if(root == NULL){
72                 p = (struct TraceCoreEvent *)malloc(sizeof(struct TraceCoreEvent));
73                 p->next = NULL;
74                 p->eID = eID;
75                 return p;
76         }
77         p = root;
78         while(p->next != NULL)
79                 p = p->next;
80         p->next = (struct TraceCoreEvent *)malloc(sizeof(struct TraceCoreEvent));
81         p->next->next = NULL;
82         p->next->eID = eID;
83         return root;
84 }
85
86
87 void print_TraceCoreEvent(FILE *fpPtc,struct TraceCoreEvent *root,char *lang){
88         struct TraceCoreEvent *p;
89         
90         p = root;
91         while(p!=NULL){
92                 fprintf(fpPtc,"%d %s%d ",p->eID,lang,p->eID);
93                 p = p->next;
94
95         }
96 }
97
98 //TODO: currently these are dummy definitions
99 void TraceCore::RegisterEvent(int lID, int eID)
100 {
101         //CmiPrintf("registering event (%d, %d)\n", lID, eID);
102         if(traceCoreOn == 0){
103                 return;
104         }
105         // code for ptc file generation
106         for(int i=0;i<numLangs;i++){
107                 if(lIDList[i] == lID){
108                         if(maxeID[i] < eID){
109                                 maxeID[i] = eID;
110                         }
111                         numEvents[i]++;
112                         eventLists[i] = insert_TraceCoreEvent(eventLists[i],eID);
113                         break;
114                 }
115         }
116 }
117
118 void TraceCore::startPtc(){
119         if(traceCoreOn ==0){
120                 return;
121         }
122         char *str = new char[strlen(CpvAccess(_traceCoreRoot))+strlen(".ptc")+1];
123         sprintf(str,"%s.ptc",CpvAccess(_traceCoreRoot));
124         fpPtc = fopen(str,"w");
125         if(fpPtc == NULL){
126                 CmiAbort("Can't generate Ptc file");
127         }
128         fprintf(fpPtc,"%d\n",CmiNumPes());
129         for(int i=0;i<MAX_NUM_LANGUAGES;i++){
130                 eventLists[i] = NULL;
131                 maxeID[i] = 0;
132                 numEvents[i] = 0;
133         }
134         maxlID = 0;
135         numLangs = 0;
136 }
137
138
139 void TraceCore::closePtc(){
140         if(traceCoreOn ==0){
141                 return;
142         }
143         fprintf(fpPtc,"%d %d ",maxlID,numLangs);
144         for(int i=0;i<numLangs;i++){
145                 fprintf(fpPtc,"%d %s ",lIDList[i],lNames[i]);
146         }
147         fprintf(fpPtc,"\n");
148         for(int i=0;i<numLangs;i++){
149                 fprintf(fpPtc,"%d %d %d ",lIDList[i],maxeID[i],numEvents[i]);
150                 print_TraceCoreEvent(fpPtc,eventLists[i],lNames[i]);
151                 fprintf(fpPtc,"\n");
152         }
153         fclose(fpPtc);
154 }
155
156
157
158
159 //TODO: only for compatibility with incomplete converse instrumentation
160 void TraceCore::LogEvent(int lID, int eID)
161
162         if(traceCoreOn == 0){
163                 return;
164         }
165         LogEvent(lID, eID, 0, NULL, 0, NULL); 
166 }
167
168 void TraceCore::LogEvent(int lID, int eID, int iLen, int* iData)
169
170         if(traceCoreOn == 0){
171                 return;
172         }
173         LogEvent(lID, eID, iLen, iData, 0, NULL); 
174 }
175
176 void TraceCore::LogEvent(int lID, int eID, int sLen, char* sData)
177
178         if(traceCoreOn == 0){
179                 return;
180         }
181         LogEvent(lID, eID, 0, NULL, sLen, sData); 
182 }
183
184 void TraceCore::LogEvent(int lID, int eID, int iLen, int* iData, int sLen, char* sData)
185 {
186         //CmiPrintf("lID: %d, eID: %d", lID, eID);
187         if(traceCoreOn == 0){
188                 return;
189         }
190         if(iData != NULL) {
191         //      CmiPrintf(" iData(%d): ",iLen);
192                 for(int i=0; i<iLen; i++) { //CmiPrintf("%d ", iData[i]);
193                 }
194         }
195         if(sData != NULL) {
196 //              CmiPrintf("sData: %s", sData);
197         }
198 //      CmiPrintf("\n");
199
200 #ifndef CMK_OPTIMIZE
201         traceLogger->add(lID, eID, TraceCoreTimer(), iLen, iData, sLen, sData);
202 #endif
203 }
204
205 /***************** Class TraceEntry Definition *****************/
206 TraceEntry::TraceEntry(TraceEntry& te)
207 {
208         languageID = te.languageID;
209         eventID    = te.eventID;
210         timestamp  = te.timestamp;
211         eLen       = te.eLen;
212         entity     = te.entity;
213         iLen       = te.iLen;
214         iData      = te.iData;
215         sLen       = te.sLen;
216         sData      = te.sData;
217 }
218
219 TraceEntry::~TraceEntry()
220 {
221         if(entity) delete [] entity;
222         if(iData)  delete [] iData;
223         if(sData)  delete [] sData;
224 }
225
226 void TraceEntry::write(FILE* fp, int prevLID, int prevSeek, int nextLID, int nextSeek)
227 {
228         //NOTE: no need to write languageID to file
229         if(prevLID == 0 && nextLID ==0)
230                 fprintf(fp, "%d %f %d %d ", eventID, timestamp, 0, 0);
231         else if(prevLID == 0 && nextLID !=0)
232                 fprintf(fp, "%d %f %d %d %d", eventID, timestamp, 0, nextLID, nextSeek);
233         else if(prevLID != 0 && nextLID ==0)
234                 fprintf(fp, "%d %f %d %d %d", eventID, timestamp, prevLID, prevSeek, 0);
235         else // if(prevLID != 0 && nextLID !=0)
236                 fprintf(fp, "%d %f %d %d %d %d", eventID, timestamp, prevLID, prevSeek, nextLID, nextSeek);
237
238         fprintf(fp, " %d", eLen);
239         if(eLen != 0) {
240           for(int i=0; i<eLen; i++) fprintf(fp, " %d", entity[i]);
241         }
242
243         fprintf(fp, " %d", iLen);
244         if(iLen != 0) {
245           for(int i=0; i<iLen; i++) fprintf(fp, " %d", iData[i]);
246         }
247
248         if(sLen !=0) fprintf(fp, " %s\n", sData);
249         else fprintf(fp, "\n");
250
251         // free memory
252 /*      if(entity) delete [] entity;
253         //entity = NULL;
254         if(iData)  delete [] iData;
255         //iData = NULL;
256         if(sData)  delete [] sData;*/
257         //sData=NULL;
258 }
259
260 /***************** Class TraceLogger Definition *****************/
261 TraceLogger::TraceLogger(char* program, int b):
262         numLangs(1), numEntries(0), lastWriteFlag(0), prevLID(0), prevSeek(0)
263 {
264   binary = b;
265 //  CmiPrintf("Size of the pool %d \n",CpvAccess(_traceCoreBufferSize));
266   pool = new TraceEntry[5*CpvAccess(_traceCoreBufferSize)];
267  // pool = new TraceEntry[500];
268   poolSize = CpvAccess(_traceCoreBufferSize);
269   
270   for (int lID=0;lID<MAX_NUM_LANGUAGES;lID++) {
271     lName[lID]=NULL;
272     fName[lID]=NULL;
273   }
274
275   pgm = new char[strlen(program)+1];
276   sprintf(pgm, "%s", program);
277   numEntries = 0;
278
279   //CmiPrintf("In TraceLogger Constructor %s %d",pgm,strlen(program)+1);
280   //initlogfiles();
281
282 }
283
284  void TraceLogger::initlogfiles(){
285         openLogFiles();
286         closeLogFiles();
287 }
288
289
290 TraceLogger::~TraceLogger()
291 {
292   if(binary)
293   { lastWriteFlag = 1; writeBinary(); }
294   else
295   { lastWriteFlag = 1; write(); }
296   for (int lID=0;lID<MAX_NUM_LANGUAGES;lID++) {
297     delete[] lName[lID];
298     delete[] fName[lID];
299   }
300 }
301
302 void TraceLogger::RegisterLanguage(int lID, char* ln)
303 {
304         numLangs++;
305
306         lName[lID] = new char[strlen(ln)+1];
307         sprintf(lName[lID], "%s", ln);
308
309         char pestr[10]; sprintf(pestr, "%d\0", CmiMyPe());
310         fName[lID] = new char[strlen(pgm)+1+strlen(pestr)+1+strlen(ln)+strlen(".log")+10];
311         sprintf(fName[lID], "%s.%s.%s.log", pgm, pestr, ln);
312
313         // my debug code - schak
314         //CmiPrintf("%s at %d in %d \n",fName[lID],lID,fName[lID]);
315         if(CpvAccess(_traceCoreOn) == 0){
316                 CmiPrintf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1_traceCoreOn = 0 in RegisterLanguage \n");
317                 return;
318         }
319         FILE* fp = NULL;
320         do
321         {
322         fp = fopen(fName[lID], "w");
323         } while (!fp && (errno == EINTR || errno == EMFILE));
324         if(!fp) {
325         CmiAbort("Cannot open Projector Trace File for writing ... \n");
326         }
327         if(!binary) {
328         fprintf(fp, "PROJECTOR-RECORD: %s.%s\n", pestr, lName[lID]);
329         }
330         //fclose(fp);
331         fptrs[lID] = fp;
332 }
333
334 void TraceLogger::verifyFptrs(){
335         
336   for(int i=1; i<numLangs; i++){
337                 if(!fptrs[i]){
338                         CmiPrintf("Null File Pointer Found after Open\n");
339                 }
340   }
341 }
342
343 void TraceLogger::write(void)
344 {
345         if(CpvAccess(_traceCoreOn) == 0){
346                 return;
347         }
348         //openLogFiles();
349         verifyFptrs();
350         int currLID=0, nextLID=0;
351         int pLID=0, nLID=0;
352         int currSeek=0, nextSeek=0;
353         int i;
354         for(i=0; i<CpvAccess(staticNumEntries)-1; i++) {
355                 currLID  = pool[i].languageID;
356                 FILE* fp = fptrs[currLID];
357                 if(fp ==  NULL)
358                         return;
359                 currSeek = ftell(fp);
360                 nextLID  = pool[i+1].languageID;
361                 nextSeek = ftell(fptrs[nextLID]);
362
363                 pLID = ((prevLID==currLID)?0:prevLID);
364                 nLID = ((nextLID==currLID)?0:nextLID);
365                 pool[i].write(fp, pLID, prevSeek, nLID, nextSeek);
366
367                 prevSeek = currSeek; prevLID = currLID;
368                 flushLogFiles();
369         }
370         if(lastWriteFlag==1) {
371                 currLID  = pool[i].languageID;
372                 FILE* fp = fptrs[currLID];
373                 if(fp == NULL)
374                         return;
375                 currSeek = ftell(fp);
376                 nextLID  = nextSeek = 0;
377
378                 pLID = ((prevLID==currLID)?0:prevLID);
379                 nLID = ((nextLID==currLID)?0:nextLID);
380                 pool[i].write(fp, pLID, prevSeek, nLID, nextSeek);
381                 closeLogFiles();
382         }
383
384         
385 }
386
387 //TODO
388 void TraceLogger::writeBinary(void) {};
389 //TODO
390 void TraceLogger::writeSts(void) {};
391
392 void TraceLogger::add(int lID, int eID, double timestamp, int iLen, int* iData, int sLen, char* sData)
393 {
394   
395   new (&pool[CpvAccess(staticNumEntries)]) TraceEntry(lID, eID, timestamp, iLen, iData, sLen, sData);
396   CpvAccess(staticNumEntries) = CpvAccess(staticNumEntries)+1;
397 if(CpvAccess(staticNumEntries)>= poolSize) {
398   //  if(numEntries>= poolSize) {
399     double writeTime = TraceCoreTimer();
400
401     if(binary) writeBinary();
402         else       write();
403
404         // move the last entry of pool to first position
405  /*   for(int i=0;i<numEntries;i++){
406             delete pool[i];
407     }*/
408     new (&pool[0]) TraceEntry(pool[CpvAccess(staticNumEntries-1)]);
409     //numEntries = 1;
410     CpvAccess(staticNumEntries)=1;
411         //TODO
412     //new (&pool[numEntries++]) TraceEntry(0, BEGIN_INTERRUPT, writeTime);
413     //new (&pool[numEntries++]) TraceEntry(0, END_INTERRUPT, TraceCoreTimer());
414   }
415 }
416
417 void TraceLogger::openLogFiles()
418 {
419   CmiPrintf("[%d]Entering openLogFile \n",CmiMyPe());
420   for(int i=1; i<numLangs; i++) {
421
422         FILE* fp = NULL;
423         do
424         {
425
426                         fp = fopen(fName[i], "a");
427
428         } while (!fp && (errno == EINTR || errno == EMFILE));
429         if(!fp) {
430         //      CmiPrintf("FILE NAME %s at %d \n",fName[i],i);
431                 CmiAbort("Cannot open Projector Trace File for writing ... \n");
432         }
433         CmiPrintf("[%d]Iteration %d : fp %d \n",CmiMyPe(),i,fp);
434         fptrs[i] = fp;
435
436         if(i == 1)
437                 assert(fptrs[1]);
438         else if(i == 2)
439         {
440                 assert(fptrs[1]);
441                 assert(fptrs[2]);
442         }
443         else if(i>= 3)
444         {
445                 assert(fptrs[1]);
446                 assert(fptrs[2]);
447                 assert(fptrs[3]);
448         }
449   }
450   CmiAssert(fptrs[1]);
451     CmiAssert(fptrs[2]);
452       CmiAssert(fptrs[3]);
453   CmiPrintf("[%d]In Open log files ........\n",CmiMyPe());
454   verifyFptrs();
455   CmiPrintf("[%d].....................\n",CmiMyPe());
456 }
457
458 void TraceLogger::closeLogFiles()
459 {
460   for(int i=1; i<numLangs; i++){
461                 if(fptrs[i])
462                         fclose(fptrs[i]);
463                 fptrs[i]=NULL;
464                 
465   }
466 }
467
468 void TraceLogger::flushLogFiles(){
469         for(int i=1;i<numLangs;i++){
470                 fflush(fptrs[i]);
471         }
472 }
473