Defining the interfaces to add various regions to snapshot
[c11tester.git] / snapshot-interface.cc
1 #define MYBINARYNAME "model"
2 #define MYLIBRARYNAME "libmodel.so"
3 #define MYALLOCNAME  "libmymemory.so"
4 #define PROCNAME      "/proc/*/maps"
5 #define REPLACEPOS              6
6 #define PAGESIZE 4096
7 #include "snapshot-interface.h"
8 #include <iostream>
9 #include <fstream>
10 #include <unistd.h>
11 #include <sys/types.h>
12 #include <sstream>
13 #include <cstring>
14 #include <cassert>
15 typedef std::basic_stringstream< char, std::char_traits< char >, MyAlloc< char > > MyStringStream;
16 std::vector< MyString, MyAlloc< MyString> > splitString( MyString input, char delim ){
17         std::vector< MyString, MyAlloc< MyString > > splits;
18         MyStringStream ss( input );     
19         MyString item;
20         while( std::getline( ss, item, delim ) ){
21                 splits.push_back( item );       
22         }
23         return splits;
24 }
25
26 bool checkPermissions( MyString permStr ){
27         return permStr.find("w") != MyString::npos;
28 }
29 static void takeSegmentSnapshot( const MyString & lineText ){
30     std::vector< MyString, MyAlloc< MyString > > firstSplit = splitString( lineText, ' ' );
31     if( checkPermissions( firstSplit[ 1 ] ) ){
32         std::vector< MyString, MyAlloc< MyString > > secondSplit = splitString( firstSplit[ 0 ], '-' );    
33         size_t val1 = 0, val2 = 0;
34                 sscanf( secondSplit[ 0 ].c_str(), "%zx", &val1 );
35                 sscanf( secondSplit[ 1 ].c_str(), "%zx", &val2 );
36                 size_t len = ( val2 - val1 ) / PAGESIZE;    
37         if( 0 != len ){
38             addMemoryRegionToSnapShot( ( void * )val1, len );        
39         }
40     }
41 }
42 void snapshot_utils::SnapshotGlobalSegments(){
43         MyString fn = PROCNAME;
44         static char sProcessSize[ 12 ] = { 0 };
45         std::pair< const char *, bool > dataSect[ 3 ];
46         dataSect[ 0 ] = std::make_pair( MYBINARYNAME, false );
47         dataSect[ 1 ] = std::make_pair( MYLIBRARYNAME, false );
48         dataSect[ 2 ] = std::make_pair( MYALLOCNAME, false );
49         static pid_t sProcID = 0;
50         if( 0 == sProcID ) {
51                 sProcID = getpid();     
52                 sprintf( sProcessSize, "%d", sProcID );
53         }
54         fn.replace( REPLACEPOS, 1, sProcessSize );
55         std::ifstream procName( fn.c_str() );
56         if( procName.is_open() ){
57                 MyString line;
58                 while( procName.good() ){
59                         getline( procName, line );
60                         int i  = 0;
61                         for( i = 0; i < 3; ++i ){
62                                 if( MyString::npos != line.find( dataSect[ i ].first ) ) break;                 
63                         }
64                         if( i >= 3 || dataSect[ i ].second == true ) continue;
65                         dataSect[ i ].second = true;
66                         if( !procName.good() )return;
67                         getline( procName, line );
68                         takeSegmentSnapshot( line );    
69                 }       
70         }
71 }
72
73 //class definition of snapshotTree.....
74 //static definitions
75 namespace snapshot_utils{
76         snapshotTree * snapshotTree::msCurrentScope = 0;
77         BackTrackingParents_t snapshotTree::msRecordedParents;
78         SnapshotToStateMap_t snapshotTree::msSnapshottedStates;
79         SnapshotEdgeMap_t  snapshotTree::msSnapshotEdgesMap;
80         unsigned int snapshotTree::msTimeCounter = 0;
81     void snapshotTree::EnsureRelevantRegionsSnapshotted(){
82         SnapshotGlobalSegments();
83         AddUserHeapToSnapshot();
84     }
85         //declaration of constructor....
86         snapshotTree::snapshotTree(){
87         EnsureRelevantRegionsSnapshotted();
88         }
89         
90         snapshotTree::~snapshotTree(){
91                 if( this == msCurrentScope ){
92                         msCurrentScope = 0;                     
93                 }       
94         }
95         
96         //static function definition
97         snapshotTree * snapshotTree::ReturnCurrentScope(){
98                 return msCurrentScope;  
99         }
100
101         MyString SerializeThreadSteps( const ThreadStepMap_t & theMap ){
102                 MyString newStr;
103                 char tempArray[ 2048 ] = { 0 };
104                 char * ptr = tempArray;
105                 for( ThreadStepMap_t::const_iterator myIter = theMap.begin(); myIter != theMap.end(); ++myIter ){
106                         sprintf( ptr, "%d:%d#", myIter->first, myIter->second );
107                         newStr += ptr;
108                         ptr += strlen( ptr );   
109                                 
110                 }
111                 return newStr;
112         }
113         //public function definiton
114         /*
115                 @funct: TakeStep( thrd_t current, thrd_t whoseNext ) 
116                 @return: bool
117                 @Desc: this function takes a series of steps creating
118                                                 new tree elements and setting the current scope. This function returns true if the step just taken leads to the parent of
119                                                 an unexplored back tracking point...
120         */
121         void snapshotTree::AddThreadStep( ThreadStepMap_t & theMap, thrd_t which ){
122                         if( theMap.find( which ) != theMap.end() ){
123                                 ++theMap[ which ];
124                                 return;                 
125                         }
126                         theMap[ which ] = 1; //implicit thread creation....
127         }
128         bool snapshotTree::operator<( const snapshotTree & rhs ) const{
129                         return this->mTimeStamp < rhs.mTimeStamp;
130         }
131         bool snapshotTreeComp::operator()( const std::pair< const snapshotTree*, snapshot_id > & lhs, const std::pair< const snapshotTree*, snapshot_id > & rhs ){
132                 return *(lhs.first) < *(rhs.first);     
133         }
134         std::pair< MyString, bool > snapshotTree::TakeStep( thrd_t which, thrd_t whoseNext ){
135                         assert( msCurrentScope == this );
136                         std::pair< MyString, bool > retVal;
137                         ThreadStepMap_t temp = mThreadStepsTaken;
138                         AddThreadStep( temp, which );
139                         MyString serialized = SerializeThreadSteps( mThreadStepsTaken ); //is it necessary to cache this with the class....?
140                         retVal.first = serialized;
141                         if( msSnapshotEdgesMap.find( serialized ) != msSnapshotEdgesMap.end() ){
142                                 msCurrentScope = msSnapshotEdgesMap[ serialized ];      
143                         }
144                         snapshotTree * newNode = new snapshotTree();
145                         newNode->mThreadStepsTaken = temp;
146                         newNode->mpParent = this;
147                         this->mChildren.push_back( newNode );
148                         newNode->mNextStepTaker = whoseNext; //dont know if this will be used yet....
149                         newNode->mTimeStamp = msTimeCounter++;
150                         msCurrentScope = newNode;
151                         
152                         //is it an actual backtracking parent....
153                         retVal.second = msRecordedParents.find( msCurrentScope ) != msRecordedParents.end();
154                         return retVal;
155         }
156
157         /*
158                 @funct: BacktrackingPointSet()
159                 @Return: NONE
160                 @DESC: This sets up the internal states necessary in future should we take a snapshot or something...
161         */
162         void snapshotTree::BacktrackingPointSet(){
163                 assert( msCurrentScope == this );
164                 msRecordedParents.insert( msCurrentScope->mpParent );
165         } 
166
167         /*
168                 @funct: ReturnEarliestSnapshotID( MyString key )
169                 @DESC: For any key, return the snapshot id which is the latest but earlier than the transition defined by the current key....
170         */
171         snapshot_id snapshotTree::ReturnEarliestSnapshotID( MyString key ){
172                 //first return a snapshotTree *
173                 if( msSnapshotEdgesMap.find( key ) == msSnapshotEdgesMap.end() )return -1;
174                 //snapshotTree * theNode = msSnapshotEdgesMap[ key ];
175                 
176                 //do we have a greatest snapshot id that is lesser than the current id...
177                 return -1;
178                 
179         }
180 };