/**************************************************************************** ****************************************************************************/ /**************************************************************************** * readVTF.cc * * Author: Ryan K. Harris & Wyatt Spear * * readVTF is the module which utilizes the "vtf3.h" of Vampir to read * in VTF files, parse them, and pull out the desired trace info. Then * the binarytree data structure module is called into which we store the * information. Each distinct(unique) cpu is stored as a node, * sorted by it's unique CPUID #. Within each CPU node is a private member * tree which stores all functions run on that cpu as nodes on a * 'function' tree. * * Large portions of this code is taken from Stephan Seidl ****************************************************************************/ #include "readVTF.h" #include int debug = 0; /* Define user handler code for the user handlers declared in header */ /**************************************************************************** MyDowntoHandler -- this is the newer equivalent to an exchangetype == 1. ****************************************************************************/ int readVTF::MyDowntoHandler(void *ccbvoid, double time, int statetoken, unsigned int cpuid, int scltoken) { readVTF* this_readVTF_obj = (readVTF*)ccbvoid; if(this_readVTF_obj->lastcall != -1) { cout << "DANGER! 1\n"; } this_readVTF_obj->sampstatetoken = statetoken; this_readVTF_obj->sampcpupid = cpuid; this_readVTF_obj->sampscltoken = scltoken; this_readVTF_obj->samptime = time; this_readVTF_obj->sampindex = 0; this_readVTF_obj->lastcall = 0; if(this_readVTF_obj->globmets == 0) { this_readVTF_obj->DowntoBatch(this_readVTF_obj); this_readVTF_obj->sampindex = -1; this_readVTF_obj->lastcall = -1; } return(1); } /**************************************************************************** DowntoBatch -- Records collected time and sample data as per exchangetype == 1. ****************************************************************************/ int readVTF::DowntoBatch(void *ccbvoid) { /* The following line must be executed in order to gain access to the member var's, i.e. 'this_readVTF_obj.some_counter_var' where some_counter_var would be in the private section of the class definition. */ readVTF* this_readVTF_obj = (readVTF*)ccbvoid; double time = this_readVTF_obj->samptime; int statetoken = this_readVTF_obj->sampstatetoken; unsigned int cpuid = this_readVTF_obj->sampcpupid; //int scltoken = this_readVTF_obj->sampscltoken; int nummets = this_readVTF_obj->globmets; /* The following 'exchangetype' var is declared to make this handler compatable (able to use) the current implementation of the stack class. */ int exchangetype = 1; double timeStamp = time; double startingTime = this_readVTF_obj->startTime; double endingTime = this_readVTF_obj->endTime; if(this_readVTF_obj->clockPeriod != 0) { timeStamp = timeStamp * this_readVTF_obj->clockPeriod; } /* Convert to microSeconds == 10E-6. */ timeStamp = timeStamp * 1000000; /*cout << "DT. TS: " << timeStamp << " "; for(int i = 0; i < nummets; i++) { cout << " M" << i << ": " << this_readVTF_obj->sampholder[i]; } cout << endl;*/ /* If threaded, handle different. */ if(this_readVTF_obj->threadNumArrayDim) { int cpuID; int threadID; cpuID = (cpuid << 16) >> 16; threadID = cpuid >> 16; //cout << cpuid << " " << cpuID << " " << threadID << endl; /* Check that the desired function, and group exist in the appropriate lookUpTrees; otherwise, insert in an attempt at traceRecord correction. */ node * a_FuncNode = this_readVTF_obj->functionLookUp->getFuncNode(statetoken); if(a_FuncNode == 0) { string the_statename; the_statename = "UNDEFINED_FUNCTION"; this_readVTF_obj->functionLookUp->insert( this_readVTF_obj->nextToken, statetoken, &the_statename, &the_statename); this_readVTF_obj->nextToken = this_readVTF_obj->nextToken + 5; a_FuncNode = this_readVTF_obj->functionLookUp->getFuncNode(statetoken); }//if int group = (*a_FuncNode).getGroupID(); node * a_GroupNode = this_readVTF_obj->activityLookUp->getFuncNode(group); if(a_GroupNode == 0) { string the_activityname; the_activityname = "UNDEFINED_GROUP"; this_readVTF_obj->activityLookUp->insert( group, group, &the_activityname, &the_activityname); }//if a_FuncNode = this_readVTF_obj->functionLookUp->getFuncNode(statetoken); group = (*a_FuncNode).getGroupID(); string the_statename; the_statename = *(a_FuncNode->getFunctionName()); /* Get the groupName (activityname) from the activityLookUp tree. */ a_GroupNode = this_readVTF_obj->activityLookUp->getFuncNode(group); string the_activityname; /* The following function makes use of the 'getFunctionName()' method, but keep in mind that we have stored the activity (group)name there in this tree. */ the_activityname = *(a_GroupNode->getFunctionName()); /* Now attempt to insert the new 'cpu' node and 'function' nodes into the cpu_tree and associated private funcTree of that 'cpu' node. */ this_readVTF_obj->cpu_tree->insert( cpuID, group, statetoken, &the_statename, &the_activityname, threadID, startingTime, endingTime); /* Now knowing that it exists. */ nodeC* a_CPUnode = this_readVTF_obj->cpu_tree->getCPUNode(cpuID); nodeC * a_thread = a_CPUnode->threadTree->getCPUNode(threadID); /* Now increment the 'function' node within this 'thread' nodes subTree. */ /* Now happens inside 'stack' structures. a_thread->incFuncCount(statetoken); */ a_thread->push(statetoken, timeStamp, this_readVTF_obj->sampholder, nummets, exchangetype); return(1); }//if threaded else { /* Check that the desired function, and group exist in the appropriate lookUpTrees; otherwise, insert in an attempt at traceRecord correction. */ node * a_FuncNode = this_readVTF_obj->functionLookUp->getFuncNode(statetoken); if(a_FuncNode == 0) { string the_statename; the_statename = "UNDEFINED_FUNCTION"; this_readVTF_obj->functionLookUp->insert( this_readVTF_obj->nextToken, statetoken, &the_statename, &the_statename); this_readVTF_obj->nextToken = this_readVTF_obj->nextToken + 5; a_FuncNode = this_readVTF_obj->functionLookUp->getFuncNode(statetoken); }//if int group = (*a_FuncNode).getGroupID(); node * a_GroupNode = this_readVTF_obj->activityLookUp->getFuncNode(group); if(a_GroupNode == 0) { string the_activityname; the_activityname = "UNDEFINED_GROUP"; this_readVTF_obj->activityLookUp->insert( group, group, &the_activityname, &the_activityname); }//if a_FuncNode = this_readVTF_obj->functionLookUp->getFuncNode(statetoken); group = (*a_FuncNode).getGroupID(); string the_statename; the_statename = *(a_FuncNode->getFunctionName()); /* Get the groupName (activityname) from the activityLookUp tree. */ a_GroupNode = this_readVTF_obj->activityLookUp->getFuncNode(group); string the_activityname; /* The following function makes use of the 'getFunctionName()' method, but keep in mind that we have stored the activity (group)name there in this tree. */ the_activityname = *(a_GroupNode->getFunctionName()); /* Now attempt to insert the new 'cpu' node and 'function' nodes into the cpu_tree and associated private funcTree of that 'cpu' node. */ this_readVTF_obj->cpu_tree->insert( cpuid, group, statetoken, &the_statename, &the_activityname, startingTime, endingTime); nodeC* a_CPUnode = this_readVTF_obj->cpu_tree->getCPUNode(cpuid); (*a_CPUnode).push(statetoken, timeStamp, this_readVTF_obj->sampholder, nummets, exchangetype); return(1); }//else (not threaded) return(1); }//MyDowntoHandler /**************************************************************************** MyUpfromHandler -- this is the newer equivalent to an exchangetype == 2. The difference between this function and Upto is that Upfrom expects the token (functionID) of the function being left, so I pass a special exchangetype == 5 to tell 'stack' how to handle. ****************************************************************************/ int readVTF::MyUpfromHandler(void *ccbvoid, double time, int statetoken, unsigned int cpuid, int scltoken) { readVTF* this_readVTF_obj = (readVTF*)ccbvoid; if(this_readVTF_obj->lastcall != -1) { cout << "DANGER! 1\n"; } this_readVTF_obj->sampstatetoken = statetoken; this_readVTF_obj->sampcpupid = cpuid; this_readVTF_obj->sampscltoken = scltoken; this_readVTF_obj->samptime = time; this_readVTF_obj->sampindex = 0; this_readVTF_obj->lastcall = 1; if(this_readVTF_obj->globmets == 0) { this_readVTF_obj->UpfromBatch(this_readVTF_obj); this_readVTF_obj->sampindex = -1; this_readVTF_obj->lastcall = -1; } return(1); } /**************************************************************************** UpFromBatch -- Records collected time and sample data as per upFrom. ****************************************************************************/ int readVTF::UpfromBatch(void *ccbvoid) { /* The following line must be executed in order to gain access to the member var's, i.e. 'this_readVTF_obj.some_counter_var' where some_counter_var would be in the private section of the class definition. */ readVTF* this_readVTF_obj = (readVTF*)ccbvoid; double time = this_readVTF_obj->samptime; int statetoken = this_readVTF_obj->sampstatetoken; unsigned int cpuid = this_readVTF_obj->sampcpupid; //int scltoken = this_readVTF_obj->sampscltoken; int nummets = this_readVTF_obj->globmets; /* The following 'exchangetype' var is declared to make this handler compatable (able to use) the current implementation of the stack class.*/ int exchangetype = 5; double timeStamp = time; double startingTime = this_readVTF_obj->startTime; double endingTime = this_readVTF_obj->endTime; if(this_readVTF_obj->clockPeriod != 0) { timeStamp = timeStamp * this_readVTF_obj->clockPeriod; } /* Convert to microSeconds == 10E-6. */ timeStamp = timeStamp * 1000000; /*cout << "UF. TS: " << timeStamp << " "; for(int i = 0; i < nummets; i++) { cout << " M" << i << ": " << this_readVTF_obj->sampholder[i]; } cout << endl;*/ /* If threaded, handle different. */ if(this_readVTF_obj->threadNumArrayDim) { int cpuID; int threadID; cpuID = (cpuid << 16) >> 16; threadID = cpuid >> 16; //cout << cpuid << " " << cpuID << " " << threadID << endl; /* Check that the desired function, and group exist in the appropriate lookUpTrees; otherwise, insert in an attempt at traceRecord correction. */ node * a_FuncNode = this_readVTF_obj->functionLookUp->getFuncNode(statetoken); if(a_FuncNode == 0) { string the_statename; the_statename = "UNDEFINED_FUNCTION"; this_readVTF_obj->functionLookUp->insert( this_readVTF_obj->nextToken, statetoken, &the_statename, &the_statename); this_readVTF_obj->nextToken = this_readVTF_obj->nextToken + 5; a_FuncNode = this_readVTF_obj->functionLookUp->getFuncNode(statetoken); }//if int group = (*a_FuncNode).getGroupID(); node * a_GroupNode = this_readVTF_obj->activityLookUp->getFuncNode(group); if(a_GroupNode == 0) { string the_activityname; the_activityname = "UNDEFINED_GROUP"; this_readVTF_obj->activityLookUp->insert( group, group, &the_activityname, &the_activityname); }//if /* Get the thread(threadID) from the cpu(cpuID). */ /* It is remotely possible that we might be dealing with a horribly constructed traceFile, and that neither the CPU nor the threadNode were ever created, so we include if-statements to check here. */ nodeC * a_CPUnode = this_readVTF_obj->cpu_tree->getCPUNode(cpuID); if(a_CPUnode == 0) { /* Doesn't exist, insert it. */ int group = (*a_FuncNode).getGroupID(); string the_statename; the_statename = *(a_FuncNode->getFunctionName()); string the_activityname; the_activityname = *(a_GroupNode->getFunctionName()); this_readVTF_obj->cpu_tree->insert( cpuID, group, statetoken, &the_statename, &the_activityname, threadID, startingTime, endingTime); a_CPUnode = this_readVTF_obj->cpu_tree->getCPUNode(cpuID); }//if nodeC * a_thread = a_CPUnode->threadTree->getCPUNode(threadID); a_thread->push(statetoken, timeStamp, this_readVTF_obj->sampholder, nummets, exchangetype); return(1); }//if threaded else { /* Check that the desired function, and group exist in the appropriate lookUpTrees; otherwise, insert in an attempt at traceRecord correction. */ node * a_FuncNode = this_readVTF_obj->functionLookUp->getFuncNode(statetoken); if(a_FuncNode == 0) { string the_statename; the_statename = "UNDEFINED_FUNCTION"; this_readVTF_obj->functionLookUp->insert( this_readVTF_obj->nextToken, statetoken, &the_statename, &the_statename); this_readVTF_obj->nextToken = this_readVTF_obj->nextToken + 5; a_FuncNode = this_readVTF_obj->functionLookUp->getFuncNode(statetoken); }//if int group = (*a_FuncNode).getGroupID(); node * a_GroupNode = this_readVTF_obj->activityLookUp->getFuncNode(group); if(a_GroupNode == 0) { string the_activityname; the_activityname = "UNDEFINED_GROUP"; this_readVTF_obj->activityLookUp->insert( group, group, &the_activityname, &the_activityname); }//if /* Now push node onto this cpu's internal stack. The stack is designed to handle everything within it's structure and methods, it has access to the other data structures internal to this 'cpu' node. */ nodeC * a_CPUnode = this_readVTF_obj->cpu_tree->getCPUNode(cpuid); if(a_CPUnode == 0) { /* Doesn't exist, insert it. */ int group = (*a_FuncNode).getGroupID(); string the_statename; the_statename = *(a_FuncNode->getFunctionName()); string the_activityname; the_activityname = *(a_GroupNode->getFunctionName()); this_readVTF_obj->cpu_tree->insert( cpuid, group, statetoken, &the_statename, &the_activityname, startingTime, endingTime); }//if (*a_CPUnode).push(statetoken, timeStamp, this_readVTF_obj->sampholder, nummets, exchangetype); return(1); }//else (not threaded) return(1); }//MyUpfromHandler /**************************************************************************** MyUptoHandler -- this is the newer equivalent to an exchangetype == 2. The difference between this function and Upfrom is that Upto expects the token(functionID) of the target function. ****************************************************************************/ int readVTF::MyUptoHandler(void *ccbvoid, double time, int statetoken, unsigned int cpuid, int scltoken) { readVTF* this_readVTF_obj = (readVTF*)ccbvoid; if(this_readVTF_obj->lastcall != -1) { cout << "DANGER! 1\n"; } this_readVTF_obj->sampstatetoken = statetoken; this_readVTF_obj->sampcpupid = cpuid; this_readVTF_obj->sampscltoken = scltoken; this_readVTF_obj->samptime = time; this_readVTF_obj->sampindex = 0; this_readVTF_obj->lastcall = 2; if(this_readVTF_obj->globmets == 0) { this_readVTF_obj->UptoBatch(this_readVTF_obj); this_readVTF_obj->sampindex = -1; this_readVTF_obj->lastcall = -1; } return(1); } /**************************************************************************** UptoBatch -- Records collected time and sample data as per Upto ****************************************************************************/ int readVTF::UptoBatch(void *ccbvoid) { /* The following line must be executed in order to gain access to the member var's, i.e. 'this_readVTF_obj.some_counter_var' where some_counter_var would be in the private section of the class definition. */ readVTF* this_readVTF_obj = (readVTF*)ccbvoid; double time = this_readVTF_obj->samptime; int statetoken = this_readVTF_obj->sampstatetoken; unsigned int cpuid = this_readVTF_obj->sampcpupid; //int scltoken = this_readVTF_obj->sampscltoken; int nummets = this_readVTF_obj->globmets; /* The following 'exchangetype' var is declared to make this handler compatable (able to use) the current implementation of the stack class. */ int exchangetype = 2; double timeStamp = time; double startingTime = this_readVTF_obj->startTime; double endingTime = this_readVTF_obj->endTime; if(this_readVTF_obj->clockPeriod != 0) { timeStamp = timeStamp * this_readVTF_obj->clockPeriod; } /* Convert to microSeconds == 10E-6. */ timeStamp = timeStamp * 1000000; /*cout << "UT. TS: " << timeStamp << " "; for(int i = 0; i < nummets; i++) { cout << " M" << i << ": " << this_readVTF_obj->sampholder[i]; } cout << endl;*/ /* If threaded, handle different. */ if(this_readVTF_obj->threadNumArrayDim) { int cpuID; int threadID; cpuID = (cpuid << 16) >> 16; threadID = cpuid >> 16; //cout << cpuid << " " << cpuID << " " << threadID << endl; /* Check that the desired function, and group exist in the appropriate lookUpTrees; otherwise, insert in an attempt at traceRecord correction. */ node * a_FuncNode = this_readVTF_obj->functionLookUp->getFuncNode(statetoken); if(a_FuncNode == 0) { string the_statename; the_statename = "UNDEFINED_FUNCTION"; this_readVTF_obj->functionLookUp->insert( this_readVTF_obj->nextToken, statetoken, &the_statename, &the_statename); this_readVTF_obj->nextToken = this_readVTF_obj->nextToken + 5; a_FuncNode = this_readVTF_obj->functionLookUp->getFuncNode(statetoken); }//if int group = (*a_FuncNode).getGroupID(); node * a_GroupNode = this_readVTF_obj->activityLookUp->getFuncNode(group); if(a_GroupNode == 0) { string the_activityname; the_activityname = "UNDEFINED_GROUP"; this_readVTF_obj->activityLookUp->insert( group, group, &the_activityname, &the_activityname); }//if /* Get the thread(threadID) from the cpu(cpuID). */ /* It is remotely possible that we might be dealing with a horribly constructed traceFile, and that neither the CPU nor the threadNode were ever created, so we include if-statements to check here. */ nodeC * a_CPUnode = this_readVTF_obj->cpu_tree->getCPUNode(cpuID); if(a_CPUnode == 0) { /* Doesn't exist, insert it. */ int group = (*a_FuncNode).getGroupID(); string the_statename; the_statename = *(a_FuncNode->getFunctionName()); string the_activityname; the_activityname = *(a_GroupNode->getFunctionName()); this_readVTF_obj->cpu_tree->insert( cpuID, group, statetoken, &the_statename, &the_activityname, threadID, startingTime, endingTime); a_CPUnode = this_readVTF_obj->cpu_tree->getCPUNode(cpuID); }//if nodeC * a_thread = a_CPUnode->threadTree->getCPUNode(threadID); a_thread->push(statetoken, timeStamp, this_readVTF_obj->sampholder, nummets, exchangetype); return(1); }//if threaded else { /* Check that the desired function, and group exist in the appropriate lookUpTrees; otherwise, insert in an attempt at traceRecord correction. */ node * a_FuncNode = this_readVTF_obj->functionLookUp->getFuncNode(statetoken); if(a_FuncNode == 0) { string the_statename; the_statename = "UNDEFINED_FUNCTION"; this_readVTF_obj->functionLookUp->insert( this_readVTF_obj->nextToken, statetoken, &the_statename, &the_statename); this_readVTF_obj->nextToken = this_readVTF_obj->nextToken + 5; a_FuncNode = this_readVTF_obj->functionLookUp->getFuncNode(statetoken); }//if int group = (*a_FuncNode).getGroupID(); node * a_GroupNode = this_readVTF_obj->activityLookUp->getFuncNode(group); if(a_GroupNode == 0) { string the_activityname; the_activityname = "UNDEFINED_GROUP"; this_readVTF_obj->activityLookUp->insert( group, group, &the_activityname, &the_activityname); }//if /* Now push node onto this cpu's internal stack. The stack is designed to handle everything within it's structure and methods, it has access to the other data structures internal to this 'cpu' node. */ nodeC * a_CPUnode = this_readVTF_obj->cpu_tree->getCPUNode(cpuid); if(a_CPUnode == 0) { /* Doesn't exist, insert it. */ int group = (*a_FuncNode).getGroupID(); string the_statename; the_statename = *(a_FuncNode->getFunctionName()); string the_activityname; the_activityname = *(a_GroupNode->getFunctionName()); this_readVTF_obj->cpu_tree->insert( cpuid, group, statetoken, &the_statename, &the_activityname, startingTime, endingTime); }//if (*a_CPUnode).push(statetoken, timeStamp, this_readVTF_obj->sampholder, nummets, exchangetype); return(1); }//else (not threaded) return(1); }//MyUptoHandler /**************************************************************************** MyExchangeHandler - Collective handler for all exchange types. Not yet compatable with user defined metric data ****************************************************************************/ int readVTF::MyExchangeHandler(void *ccbvoid, double time, unsigned int cpuid, int exchangetype, int statetoken, int job, int scltoken) { readVTF* this_readVTF_obj = (readVTF*)ccbvoid; int nummets = this_readVTF_obj->globmets; double timeStamp = time; double startingTime = this_readVTF_obj->startTime; double endingTime = this_readVTF_obj->endTime; if(this_readVTF_obj->clockPeriod != 0) { timeStamp = timeStamp * this_readVTF_obj->clockPeriod; } /* Convert to microSeconds == 10E-6. */ timeStamp = timeStamp * 1000000; /* cout << "*****EXCHANGE*****\n"; cout << "time: " << time << "\n"; cout << "cpuid: " << cpuid << "\n"; cout << "exchangetype: " << exchangetype << "\n"; cout << "statetoken: " << statetoken << "\n"; cout << "job: " << job << "\n"; cout << "scltoken: " << scltoken << "\n"; */ /* I want to keep track of how many times each function is called and increment their individual counters respectively. */ //FOR DEBUGGING /* if(cpuid == 38) { cerr << "cpuID: " << cpuid << "\n"; cerr << "functionID: " << statetoken << "\n"; cerr << "exchange event: type: " << exchangetype << "\n"; cerr << "timeStamp: " << time << "\n"; } */ /* If threaded, handle different. */ if(this_readVTF_obj->threadNumArrayDim) { int cpuID; int threadID; cpuID = (cpuid << 16) >> 16; threadID = cpuid >> 16; /* Check that the desired function, and group exist in the appropriate lookUpTrees; otherwise, insert in an attempt at traceRecord correction. */ node * a_FuncNode = this_readVTF_obj->functionLookUp->getFuncNode(statetoken); if(a_FuncNode == 0) { string the_statename; the_statename = "UNDEFINED_FUNCTION"; this_readVTF_obj->functionLookUp->insert( this_readVTF_obj->nextToken, statetoken, &the_statename, &the_statename); this_readVTF_obj->nextToken = this_readVTF_obj->nextToken + 5; a_FuncNode = this_readVTF_obj->functionLookUp->getFuncNode(statetoken); }//if int group = (*a_FuncNode).getGroupID(); node * a_GroupNode = this_readVTF_obj->activityLookUp->getFuncNode(group); if(a_GroupNode == 0) { string the_activityname; the_activityname = "UNDEFINED_GROUP"; this_readVTF_obj->activityLookUp->insert( group, group, &the_activityname, &the_activityname); }//if if(exchangetype == 2) { /* Get the thread(threadID) from the cpu(cpuID). */ /* It is remotely possible that we might be dealing with a horribly constructed traceFile, and that neither the CPU nor the threadNode were ever created, so we include if-statements to check here. */ nodeC * a_CPUnode = this_readVTF_obj->cpu_tree->getCPUNode(cpuID); if(a_CPUnode == 0) { /* Doesn't exist, insert it. */ int group = (*a_FuncNode).getGroupID(); string the_statename; the_statename = *(a_FuncNode->getFunctionName()); string the_activityname; the_activityname = *(a_GroupNode->getFunctionName()); this_readVTF_obj->cpu_tree->insert( cpuID, group, statetoken, &the_statename, &the_activityname, threadID, startingTime, endingTime); a_CPUnode = this_readVTF_obj->cpu_tree->getCPUNode(cpuID); }//if nodeC * a_thread = a_CPUnode->threadTree->getCPUNode(threadID); a_thread->push(statetoken, timeStamp, this_readVTF_obj->sampholder, nummets, exchangetype); }//exchangetype == 2 if(exchangetype == 1) { a_FuncNode = this_readVTF_obj->functionLookUp->getFuncNode(statetoken); int group = (*a_FuncNode).getGroupID(); string the_statename; the_statename = *(a_FuncNode->getFunctionName()); /* Get the groupName (activityname) from the activityLookUp tree. */ a_GroupNode = this_readVTF_obj->activityLookUp->getFuncNode(group); string the_activityname; /* The following function makes use of the 'getFunctionName()' method, but keep in mind that we have stored the activity (group)name there in this tree. */ the_activityname = *(a_GroupNode->getFunctionName()); /* Now attempt to insert the new 'cpu' node and 'function' nodes into the cpu_tree and associated private funcTree of that 'cpu' node. */ this_readVTF_obj->cpu_tree->insert( cpuID, group, statetoken, &the_statename, &the_activityname, threadID, startingTime, endingTime); /* Now knowing that it exists. */ nodeC* a_CPUnode = this_readVTF_obj->cpu_tree->getCPUNode(cpuID); nodeC * a_thread = a_CPUnode->threadTree->getCPUNode(threadID); /* Now increment the 'function' node within this 'thread' nodes subTree. */ /* Now happens inside 'stack' structures. a_thread->incFuncCount(statetoken); */ a_thread->push(statetoken, timeStamp, this_readVTF_obj->sampholder, nummets, exchangetype); }//exchangetype == 1 return(1); }//if threaded else { /* Check that the desired function, and group exist in the appropriate lookUpTrees; otherwise, insert in an attempt at traceRecord correction. */ node * a_FuncNode = this_readVTF_obj->functionLookUp->getFuncNode(statetoken); if(a_FuncNode == 0) { string the_statename; the_statename = "UNDEFINED_FUNCTION"; this_readVTF_obj->functionLookUp->insert( this_readVTF_obj->nextToken, statetoken, &the_statename, &the_statename); this_readVTF_obj->nextToken = this_readVTF_obj->nextToken + 5; a_FuncNode = this_readVTF_obj->functionLookUp->getFuncNode(statetoken); }//if int group = (*a_FuncNode).getGroupID(); node * a_GroupNode = this_readVTF_obj->activityLookUp->getFuncNode(group); if(a_GroupNode == 0) { string the_activityname; the_activityname = "UNDEFINED_GROUP"; this_readVTF_obj->activityLookUp->insert( group, group, &the_activityname, &the_activityname); }//if if(exchangetype == 2) { /* Now push node onto this cpu's internal stack. The stack is designed to handle everything within it's structure and methods, it has access to the other data structures internal to this 'cpu' node. */ nodeC * a_CPUnode = this_readVTF_obj->cpu_tree->getCPUNode(cpuid); if(a_CPUnode == 0) { /* Doesn't exist, insert it. */ int group = (*a_FuncNode).getGroupID(); string the_statename; the_statename = *(a_FuncNode->getFunctionName()); string the_activityname; the_activityname = *(a_GroupNode->getFunctionName()); this_readVTF_obj->cpu_tree->insert( cpuid, group, statetoken, &the_statename, &the_activityname, startingTime, endingTime); }//if (*a_CPUnode).push(statetoken, timeStamp, this_readVTF_obj->sampholder, nummets, exchangetype); } if(exchangetype == 1) { /* When I encounter an exchange, I want to: (i) try inserting this 'cpu' node into the cpu_tree if it isn't already. (ii) insert the 'function' node into this 'cpu' nodes internal funcTree. (iii) increment that internal 'function' nodes call_counter by 1. This is actually easy because of the structures and functionality I have already built in. All we need to do is call: this_readVTF_obj->cpu_tree->insert() and pass in the appropriate parameters, then the insert method does all of the work for us. It checks whether the 'cpu' node already exists in the tree, if no, it creates is. If yes, it moves right on and trys to insert the 'function' node into the 'cpu' nodes internal funcTree. If it already exists, it simply returns. The last thing we need to do here is increment the 'function' nodes call_counter, I have not designed insert() to do this for us, although that would be easy enough if it seems appropriate later. The way we get the 'function' node information: remember, we have a seperate binary tree sitting in this readVTF object which is built entirely out of 'function' nodes, but it contains all of the 'function' nodes in the VTF; therefore, it is a 'look up tree'. I use the 'statetoken' parameter which is passed to my 'Exchange' handler to pull the appropriate function out of the look up tree, then I pull: groupID, and function name from it. I pass the info to the cpu_tree->insert() method. */ a_FuncNode = this_readVTF_obj->functionLookUp->getFuncNode(statetoken); int group = (*a_FuncNode).getGroupID(); string the_statename; the_statename = *(a_FuncNode->getFunctionName()); /* Get the groupName (activityname) from the activityLookUp tree. */ a_GroupNode = this_readVTF_obj->activityLookUp->getFuncNode(group); string the_activityname; /* The following function makes use of the 'getFunctionName()' method, but keep in mind that we have stored the activity (group)name there in this tree. */ the_activityname = *(a_GroupNode->getFunctionName()); /* Now attempt to insert the new 'cpu' node and 'function' nodes into the cpu_tree and associated private funcTree of that 'cpu' node. */ this_readVTF_obj->cpu_tree->insert( cpuid, group, statetoken, &the_statename, &the_activityname, startingTime, endingTime); nodeC* a_CPUnode = this_readVTF_obj->cpu_tree->getCPUNode(cpuid); /* Now increment the 'function' node within this 'cpu' nodes subTree. */ /* Actually incrementing the functions now takes place inside of the 'stack' structures based on the interval implementation. (*a_CPUnode).incFuncCount(statetoken); */ (*a_CPUnode).push(statetoken, timeStamp, this_readVTF_obj->sampholder, nummets, exchangetype); }//if return(1); }//else (not threaded) }//MyExchangeHandler /**************************************************************************** MyDefactHandler -- Processes activity definitions ****************************************************************************/ int readVTF::MyDefactHandler(void *ccbvoid, int activitytoken, const char *activityname) { readVTF* this_readVTF_obj = (readVTF*)ccbvoid; /* cout << "*****ACTIVITY*****\n"; cout << "activitytoken: " << activitytoken << "\n"; cout << "activityname: " << activityname << "\n"; */ /* Doesn't really do anything usefull, just filler. */ //int the_size = this_readVTF_obj->cpu_tree->size(); /* OK, I'm going to reuse the binarytree structure in conjunction with the node class ( 'function' nodes) to store the activities for look up. But the binary tree class requires that each function's statetoken which we pass in be unique, therefore we will pass in the activitytoken for both activitytoken and statetoken, which is fine, as we don't plan to reference the statetoken when using the activityLookUp tree. */ string the_activityname(activityname); this_readVTF_obj->nextToken = activitytoken + 1000; this_readVTF_obj->activityLookUp->insert( activitytoken, activitytoken, &the_activityname, &the_activityname); return(1); }//MyDefactHandler /**************************************************************************** MyDefstateHandler -- Processes state definitions ****************************************************************************/ int readVTF::MyDefstateHandler(void *ccbvoid, int activitytoken, int statetoken, const char *statename, int scltoken) { readVTF* this_readVTF_obj = (readVTF*)ccbvoid; /* cout << "*****STATE*****\n"; cout << "activitytoken: " << activitytoken << "\n"; cout << "statetoken: " << statetoken << "\n"; cout << "statename: " << statename << "\n"; cout << "scltoken: " << scltoken << "\n"; */ /* Pull the desired info from the trace, call binarytree::insert(), passing it the info. It will in turn, create a new node storing the function info into our 'functionLookUp' tree. */ string the_statename(statename); if(statetoken > this_readVTF_obj->maxstate) this_readVTF_obj->maxstate = statetoken; this_readVTF_obj->functionLookUp->insert( activitytoken, statetoken, &the_statename, &the_statename); return(1); }//MyDefstateHandler /**************************************************************************** MyDefthreadnumsHandler -- Processes thread number definitions ****************************************************************************/ int readVTF::MyDefthreadnumsHandler(void *ccbvoid, int threadnumarraydim, const int * threadnumarray) { /* The following line must be executed in order to gain access to the member var's, i.e. 'this_readVTF_obj.some_counter_var' where some_counter_var would be in the private section of the class definition. */ readVTF* this_readVTF_obj = (readVTF*)ccbvoid; /* All we're gonna do with this right now is count the # of thread records we come accross. */ this_readVTF_obj->threadNumArrayDim = threadnumarraydim; //this_readVTF_obj->threadNumArray = threadnumarray; return(1); }//MyDefthreadnumsHandler /**************************************************************************** MyCPUGrpHandler -- Processes cpu group definitions. Used for thread identification ****************************************************************************/ int readVTF::MyCPUGrpHandler(void *ccbvoid, unsigned int cpugrpid, int cpuorcpugrpidarraydim, const unsigned int *cpuorcpugrpidarray, const char *cpugrpname) { readVTF* this_readVTF_obj = (readVTF*)ccbvoid; string grpname = cpugrpname; /*All known relevant group definitions are either "TAU sample group name" which is the default, or of the form "Node X" where X is the CPU#. In case "Node" thread difinitions are found, this will record the associated threads for future use*/ if(grpname.substr(0,5) == "Node " || grpname == "TAU sample group name") { int curgroups = this_readVTF_obj->ngroups; this_readVTF_obj->ngroups++; int i; int * temp = new int[this_readVTF_obj->ngroups]; for(i = 0; ithreadlist[i]; } //delete[] this_readVTF_obj->threadlist; this_readVTF_obj->threadlist = new int[this_readVTF_obj->ngroups]; for(i = 0; ithreadlist[i] = temp[i]; } delete[] temp; this_readVTF_obj->threadlist[this_readVTF_obj->ngroups-1]=cpuorcpugrpidarraydim; } //this_readVTF_obj->threadNumArrayDim = threadnumarraydim; //this_readVTF_obj->threadNumArray = threadnumarray; return(1); }//MyCPUGrpHandler /**************************************************************************** MyDefclkperiodHandler -- Processes clock period definition ****************************************************************************/ int readVTF::MyDefclkperiodHandler(void *ccbvoid, double clkperiod) { readVTF * this_readVTF_obj = (readVTF*)ccbvoid; this_readVTF_obj->clockPeriod = clkperiod; return(1); }//MyDefclkperiodHandler /**************************************************************************** MyDeftimeoffsetHandler -- Processes time offset definition ****************************************************************************/ int readVTF::MyDeftimeoffsetHandler(void * ccbvoid, double timeoffset) { readVTF * this_readVTF_obj = (readVTF*)ccbvoid; this_readVTF_obj->timeOffset = timeoffset; return(1); }//MyDeftimeoffsetHandler /**************************************************************************** MyUnrecognizableHandler -- Processes unrecognizable entries ****************************************************************************/ int readVTF::MyUnrecognizableHandler(void * ccbvoid, double lastvalidtime, int numberofunrecognizablechars, int typeofunrecognizablerecord, const char * unrecognizablerecord) { //readVTF * this_readVTF_obj = (readVTF*)ccbvoid; string unrecon(unrecognizablerecord); cerr << "\nUn-recognizable Record Found:\n"; cerr << unrecon << "\n"; cerr << "Record Type: " << typeofunrecognizablerecord << "\n\n"; return(1); }//MyUnrecognizableHandler /**************************************************************************** MyCPUNameHandler -- Processes CPU Name definitions ****************************************************************************/ int readVTF::MyCPUNameHandler(void *fcb, unsigned int cpuid, const char *cpuname) { //cout << cpuid << " " << cpuname << endl; return(1); } /**************************************************************************** MyDefsampHandler -- Processes sample definitions ****************************************************************************/ int readVTF::MyDefsampHandler(void * ccbvoid, int sampletoken, int sampleclasstoken, int iscpugrpsamp, unsigned int cpuorcpugrpid, int valuetype, const void *valuebounds, int dodifferentiation, int datarephint, const char *samplename, const char *sampleunit) { readVTF* this_readVTF_obj = (readVTF*)ccbvoid; string the_samplename(samplename); if(dodifferentiation == 0) { int test = sampletoken; if(test <= this_readVTF_obj->maxstate) { test += this_readVTF_obj->maxstate+1; } //This metric is not associated with other functions. Insert it into the function tree // When this sample type is found the sample data will be added to the totals for the relevant cpu_node this_readVTF_obj->functionLookUp->insert( test, test, &the_samplename, &the_samplename); this_readVTF_obj->usermets++;//Update the number of user define metrics. //cout << "A 0 metric! " << sampletoken << " "<< the_samplename << endl; }//if else//A global differentiable metric { if(valuetype != 1) { cout << "WARNING: Sample Data Type Not Unsigned Long Long" << endl; } this_readVTF_obj->globmets++;//The number of such metrics defined delete[] this_readVTF_obj->sampholder;//Remove the old sample holder this_readVTF_obj->sampholder = new unsigned long long[this_readVTF_obj->globmets];//And create a resized one //Create an array of the names of the metrics used //(each metric type will be in its own folders/files under this name) //Add the new metric's name to the resized array on top of the previously encountered names string * temp = new string[this_readVTF_obj->globmets]; int i; for(i = 0; i<(this_readVTF_obj->globmets-1); i++) { temp[i] = this_readVTF_obj->sampnames[i]; } delete[] this_readVTF_obj->sampnames; this_readVTF_obj->sampnames = new string[this_readVTF_obj->globmets]; for(i = 0; i<(this_readVTF_obj->globmets-1); i++) { this_readVTF_obj->sampnames[i] = temp[i]; } this_readVTF_obj->sampnames[this_readVTF_obj->globmets-1]=the_samplename; delete[] temp; } return(1); }//MyDefsampHandler /**************************************************************************** MySampHandler -- Processes sample data ****************************************************************************/ int readVTF::MySampHandler(void * ccbvoid, double time, unsigned int cpuorcpugrpid, int samplearraydim, const int *sampletokenarray, const int *samplevaluetypearray, const void *samplevaluearray) { readVTF* this_readVTF_obj = (readVTF*)ccbvoid; //For every item associated with this sample set do the following for(int i = 0; imaxstate) { test += this_readVTF_obj->maxstate+1; } //Get the function node associated with the sample token node * a_SampNode = this_readVTF_obj->functionLookUp->getFuncNode(test);//sampletokenarray[i]); //If the token has no node in the function look up tree... if(a_SampNode == 0) { //It has to be a function-associated (differentiable) metric. //If there are no such metrics defined we have an error... an undefined sample token if(this_readVTF_obj->globmets == 0) { cout << "ERROR! Metric mismatch!" << endl; } //Otherwise place this sample's value in the sample holder array this_readVTF_obj->sampholder[this_readVTF_obj->sampindex]=(((unsigned long long *)samplevaluearray)[i]); //And increment the array's current index this_readVTF_obj->sampindex++; //printf("value=0x%x\n", ((unsigned long *)samplevaluearray)[i]); //cout << this_readVTF_obj->sampholder[this_readVTF_obj->sampindex-1] << " " << ((unsigned long long *)samplevaluearray)[i] << " " << samplevaluetypearray[i] << " " << sampletokenarray[i] << endl; //Place the newest metric data in the array //If the array is full we have the time and all metric data for the event //Run the most recently encountered call with the time/metric tuple if(this_readVTF_obj->sampindex >= this_readVTF_obj->globmets) { if(this_readVTF_obj->lastcall == 0) { this_readVTF_obj->DowntoBatch(this_readVTF_obj); } else if(this_readVTF_obj->lastcall == 1) { this_readVTF_obj->UpfromBatch(this_readVTF_obj); } else if(this_readVTF_obj->lastcall == 2) { this_readVTF_obj->UptoBatch(this_readVTF_obj); } else { cout << "ERROR! Lastcall not set!" << endl; } this_readVTF_obj->sampindex = -1; this_readVTF_obj->lastcall = -1; } }//if else//If the sample is found in the tree this is a user defined metric. Update the counters { double startingTime = this_readVTF_obj->startTime; double endingTime = this_readVTF_obj->endTime; if((startingTime == -1) || (time >= startingTime && time <= endingTime)) /*|| (startingTime == -1 && time <= endingTime) || (endingTime == -1 && time >= startingTime))*/ { //Get the cpu tree node associated with this metric nodeC * a_CPUnode = this_readVTF_obj->cpu_tree->getCPUNode(cpuorcpugrpid); if(a_CPUnode == 0) return 1; //cout << sampletokenarray[i] << " " << a_SampNode->getFunctionName() << endl; a_CPUnode->insert(sampletokenarray[i],sampletokenarray[i], a_SampNode->getFunctionName(), a_SampNode->getFunctionName());//Make sure this sample token is in the right place if(samplevaluetypearray[i] == VTF3_VALUETYPE_UINT) { unsigned long long thedata = ((unsigned long long *)samplevaluearray)[i]; //cout << thedata << endl; a_CPUnode->incSampStat(sampletokenarray[i],(double)thedata);//Increment the sample node with the data }//Convert the data else if(samplevaluetypearray[i] == VTF3_VALUETYPE_FLOAT) { double thedata = (((double *)samplevaluearray)[i]); //cout << thedata << endl; a_CPUnode->incSampStat(sampletokenarray[i],thedata);//Increment the sample node with the data } a_SampNode->incCount();//Increment the sample node's count }//if }//else }//for return(1); }//MySampHandler /**************************************************************************** readfile -- Read the tracefile for translation ****************************************************************************/ void readVTF::readfile(void) { #ifdef DEBUG cout << "Begin READ... \n"; #endif /* DEBUG */ /* Initialize Vampir functionality */ (void)VTF3_InitTables(); /* How many different record types exist */ numrec_types = VTF3_GetRecTypeArrayDim(); /* Allocate three arrays for: record type magic numbers, handler function pointers, first args to handler functions. */ recordtypes = (int*)malloc((size_t) numrec_types * sizeof(int)); handlers = (VTF3_handler_t*)malloc((size_t) numrec_types * sizeof(VTF3_handler_t)); firsthandlerargs = (void**)malloc((size_t) numrec_types * sizeof(void*)); /* Verify we didn't run out of memory */ if(recordtypes == 0 || handlers == 0 || firsthandlerargs == 0) { cout << "no more memory\n"; return; }//if /* Get record type magic numbers into the appropriate array */ (void)VTF3_GetRecTypeArray(recordtypes); /* Store predefined copy handler function pointers in my array */ (void)VTF3_GetCopyHandlerArray(handlers); /* Replace the default handlers with a pointer to our own set of user defined record handlers for the desired group of records/events. */ for(int i = 0; i < numrec_types; ++i) { if(recordtypes[i] == VTF3_RECTYPE_DOWNTO) { handlers[i] = (VTF3_handler_t)MyDowntoHandler; /* the following assignment is not arbitrary, we must pass in a copy of the instantiated class we are working within. This is because we have created the user record handlers as class member functions, but they are declared static in their prototypes. This causes errors when we try to directly grab hold of member vars.*/ firsthandlerargs[i] = this; continue; }//if if(recordtypes[i] == VTF3_RECTYPE_UPFROM) { handlers[i] = (VTF3_handler_t)MyUpfromHandler; firsthandlerargs[i] = this; continue; }//if if(recordtypes[i] == VTF3_RECTYPE_UPTO) { handlers[i] = (VTF3_handler_t)MyUptoHandler; firsthandlerargs[i] = this; continue; }//if if(recordtypes[i] == VTF3_RECTYPE_EXCHANGE) { handlers[i] = (VTF3_handler_t)MyExchangeHandler; firsthandlerargs[i] = this; continue; }//if if(recordtypes[i] == VTF3_RECTYPE_DEFACT) { handlers[i] = (VTF3_handler_t)MyDefactHandler; firsthandlerargs[i] = this; continue; }//if if(recordtypes[i] == VTF3_RECTYPE_DEFSTATE) { handlers[i] = (VTF3_handler_t)MyDefstateHandler; firsthandlerargs[i] = this; continue; }//if if(recordtypes[i] == VTF3_RECTYPE_DEFTHREADNUMS) { handlers[i] = (VTF3_handler_t)MyDefthreadnumsHandler; firsthandlerargs[i] = this; continue; }//if if(recordtypes[i] == VTF3_RECTYPE_DEFCLKPERIOD) { handlers[i] = (VTF3_handler_t)MyDefclkperiodHandler; firsthandlerargs[i] = this; continue; }//IF if(recordtypes[i] == VTF3_RECTYPE_DEFTIMEOFFSET) { handlers[i] = (VTF3_handler_t)MyDeftimeoffsetHandler; firsthandlerargs[i] = this; continue; }//if if(recordtypes[i] == VTF3_RECTYPE_UNRECOGNIZABLE) { handlers[i] = (VTF3_handler_t)MyUnrecognizableHandler; firsthandlerargs[i] = this; continue; }//if //NEW!!! if(recordtypes[i] == VTF3_RECTYPE_DEFSAMP) { handlers[i] = (VTF3_handler_t)MyDefsampHandler; firsthandlerargs[i] = this; continue; }//if if(recordtypes[i] == VTF3_RECTYPE_SAMP) { handlers[i] = (VTF3_handler_t)MySampHandler; firsthandlerargs[i] = this; continue; }//if if(recordtypes[i] == VTF3_RECTYPE_DEFCPUGRP) { handlers[i] = (VTF3_handler_t)MyCPUGrpHandler; firsthandlerargs[i] = this; continue; } //if if(recordtypes[i] == VTF3_RECTYPE_DEFCPUNAME) { handlers[i] = (VTF3_handler_t)MyCPUNameHandler; firsthandlerargs[i] = this; continue; } //if /* All other records: Install 0 as the handler for all others, reset firsthandlerargs to 0. */ handlers[i] = 0; firsthandlerargs[i] = 0; }//for /* Open the input file */ ccb.fcbin = VTF3_OpenFileInput( filename.c_str(), handlers, firsthandlerargs, substituteupfrom = 0); /* Check for failure while opening */ if(ccb.fcbin == 0) { cout << "Couldn't open " << filename << "\n"; return; }//if /* else, get file format */ else { fileformat = VTF3_QueryFormat(ccb.fcbin); //cout << "fileformat is: " << fileformat << "\n"; }//else do { bytesread = VTF3_ReadFileInput(ccb.fcbin); totalbytesread += bytesread; } while(bytesread != 0); /* cout << "total bytes read = " << totalbytesread << "\n"; cout << "size of tree is: " << cpu_tree->size() << "\n"; cpu_tree->printTree((*cpu_tree).getRootC()); cout << "# of threadRecords: " << threadRecordCount << "\n"; */ /* Need to open the appropriate outFiles, named according to the n,c,t scheme (node, context, thread), write the associated info to that file, close that file, move on to the next. When creating the 'profile.@.@.@' type files we're not concerned with overwriting previous 'profile' files of similar names. It's perfectly fine if we completely rewrite the profiles each time. */ int * threadA = 0; int * cpuA = 0; int threadrun = 0; if(ngroups > 1)//If we have more groups than the 'global listing' there are threads { //Create an array with one space for each thread //The total number of threads is provided by the last group definition threadrun = threadlist[ngroups-1]; cpuA = new int[threadrun]; threadA = new int[threadrun]; int counter = 0; for(int i = 0;iwriteTree((*cpu_tree).getRootC(), &destPath, usermets, &runname, -1, threadrun, threadA, cpuA); if(readSuccess == 0) { #ifdef DEBUG cout << "...completed READ\n"; #endif /* DEBUG */ } else if(readSuccess > 0) { cout << "READ failed\n"; } else { cout << "error in READ\n"; } } else { //Create the folder for 'get time of day'. Print the tree data. All traces will have this metric string multi = (string)"MULTI_"; string dash = (string)"_"; string runname = multi + dash + ((string)"GET_TIME_OF_DAY"); string syscom = (string)"mkdir " + destPath + runname; system(syscom.c_str()); string modpath = destPath + (string)"/"+ runname; runname = dash+multi+((string)"GET_TIME_OF_DAY"); int readSuccess = cpu_tree->writeTree((*cpu_tree).getRootC(), &modpath, usermets, &runname, -1, threadrun, threadA, cpuA); if(readSuccess == 0) { #ifdef DEBUG cout << "...completed READ\n"; #endif /* DEBUG */ } else if(readSuccess > 0) { cout << "READ failed\n"; } else { cout << "error in READ\n"; } //For every other global metric (if any) create a directory and print the tree data. for(int i = 0; iwriteTree((*cpu_tree).getRootC(), &modpath, usermets, &runname, i, threadrun, threadA, cpuA); if(readSuccess == 0) { #ifdef DEBUG cout << "...completed READ\n"; #endif /*DEBUG*/ } else if(readSuccess > 0) { cout << "READ failed\n"; } else { cout << "error in READ\n"; } }//for }//else /* The following calls are for timestamp error detection. */ int totalOutOrder = cpu_tree->countOutOrder((*cpu_tree).getRootC()); int totalRepeats = cpu_tree->countRepeats((*cpu_tree).getRootC()); if(debug) { cout << "totalOutOrder: " << totalOutOrder << "\n"; cout << "totalRepeats: " << totalRepeats << "\n"; }//if /* Free up any allocated memory */ (void)free(recordtypes); (void)free(handlers); (void)free(firsthandlerargs); delete[] threadlist; delete[] sampholder; delete[] sampnames; /* Close all devices before leaving */ (void)VTF3_Close(ccb.fcbin); return; }//readfile()