1 /*=========================================================================
2  *
3  *  Copyright Insight Software Consortium
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18 #ifndef itkSmapsFileParser_hxx
19 #define itkSmapsFileParser_hxx
20 
21 #include "itkSmapsFileParser.h"
22 
23 #if defined( _WIN32 )
24 #include <io.h>
25 #include <process.h>
26 #else
27 #include <unistd.h>
28 #endif
29 
30 #include <fstream>   // std::ifstream
31 #include <numeric>   // std::accumulate
32 #include <algorithm> // std::find
33 
34 namespace itk
35 {
36 
37 template< typename TMapDataType >
38 bool
Update()39 MapFileParser< TMapDataType >::Update()
40 {
41   this->ReadFile(m_MapFilePath);
42   return m_MapFilePath.empty();
43 }
44 
45 template< typename TMapDataType >
46 typename MapFileParser< TMapDataType >::MemoryLoadType
47 MapFileParser< TMapDataType >
GetHeapUsage()48 ::GetHeapUsage()
49 {
50   if ( m_MapData.Empty() )
51     {
52     std::cerr << "Read a map file before quering memory usage";
53     }
54   return m_MapData.GetHeapUsage();
55 }
56 
57 template< typename TMapDataType >
58 typename MapFileParser< TMapDataType >::MemoryLoadType
59 MapFileParser< TMapDataType >
GetStackUsage()60 ::GetStackUsage()
61 {
62   if ( m_MapData.Empty() )
63     {
64     std::cerr << "Read a map file before quering memory usage";
65     }
66   return m_MapData.GetStackUsage();
67 }
68 
69 template< typename TMapDataType >
70 typename MapFileParser< TMapDataType >::MemoryLoadType
71 MapFileParser< TMapDataType >
GetTotalMemoryUsage()72 ::GetTotalMemoryUsage()
73 {
74   if ( m_MapData.Empty() )
75     {
76     std::cerr << "Read a map file before quering memory usage";
77     }
78   return m_MapData.GetTotalMemoryUsage();
79 }
80 
81 template< typename TMapDataType >
82 typename MapFileParser< TMapDataType >::MemoryLoadType
83 MapFileParser< TMapDataType >
GetMemoryUsage(const char * filter,const char * token)84 ::GetMemoryUsage(const char *filter, const char *token)
85 {
86   if ( m_MapData.Empty() )
87     {
88     std::cerr << "Read a map file before quering memory usage";
89     }
90   return m_MapData.GetMemoryUsage(filter, token);
91 }
92 
93 //---------------------------------
94 //      SmapsFileParser
95 //---------------------------------
96 
97 /* SmapsFileParser implementation */
98 template< typename TSmapsDataType >
ReadFile(const std::string & mapFileLocation)99 void SmapsFileParser< TSmapsDataType >::ReadFile(const std::string & mapFileLocation)
100 {
101   std::stringstream filename;
102 
103   filename << mapFileLocation;
104 
105   // if location is empty (default parameter), use the regular linux smaps file.
106   if ( filename.str().empty() )
107     {
108 #if defined( WIN32 ) || defined ( _WIN32 )
109     itkGenericExceptionMacro(<< "smaps files don't exist on Windows");
110 #else
111     int pid = getpid();
112     filename << "/proc/" << pid << "/smaps";
113 #endif
114     }
115 
116   // open the Smaps file
117   std::ifstream inputFile( filename.str().c_str() );
118 
119   // can't find or open the Smaps file
120   if ( inputFile.is_open() == false )
121     {
122     std::cerr << "The smaps file " << filename.str() << " could not be open";
123     return;
124     }
125 
126   try
127     {
128     //load the file
129     inputFile >> this->m_MapData;
130     }
131   catch ( ExceptionObject excp )
132     {
133     // propagate the exception
134     itkGenericExceptionMacro(<< "The smaps file " << filename.str() << " is an invalid file or contains errors");
135     }
136   this->m_MapFilePath = filename.str();
137 }
138 
139 /* VMapFileParser implementation */
140 template< typename TVMMapDataType >
ReadFile(const std::string & mapFileLocation)141 void VMMapFileParser< TVMMapDataType >::ReadFile(const std::string & mapFileLocation)
142 {
143   try
144     {
145     if ( !mapFileLocation.empty() )
146       {
147       // open the VMap file
148       std::ifstream inputFile( mapFileLocation.c_str() );
149       // can't find or open the VMap file
150       if ( inputFile.is_open() == false )
151         {
152         itkGenericExceptionMacro(<< "The VMap file " << mapFileLocation << " could not be open");
153         return;
154         }
155       //load the file
156       inputFile >> this->m_MapData;
157       this->m_MapFilePath = mapFileLocation;
158       }
159     else
160       {
161 #if defined( WIN32 ) || defined ( _WIN32 )
162       itkGenericExceptionMacro(<< "VMMap files don't exist on Windows");
163 #else
164       std::stringstream vmmapCommand;
165       vmmapCommand << "vmmap " << getpid();
166 
167       FILE *vmmapCommandOutput = nullptr;
168       if ( ( vmmapCommandOutput = popen(vmmapCommand.str().c_str(), "r") ) == nullptr )
169         {
170         itkGenericExceptionMacro(<< "Error using pmap. Can execute pmap command");
171         }
172 
173       // Not optimal solution: copy the output into an std::istream object.
174       std::stringstream vmmapFile;
175       char              buf[256];
176       while ( !feof(vmmapCommandOutput) )
177         {
178         fgets(buf, 256, vmmapCommandOutput);
179         vmmapFile << buf;
180         }
181 
182       fclose(vmmapCommandOutput);
183       //fill the data
184       vmmapFile >> this->m_MapData;
185       this->m_MapFilePath = "";
186 #endif
187       }
188     }
189   catch ( ExceptionObject excp )
190     {
191     // propagate the exception
192     itkGenericExceptionMacro(<< "The vmmap file is an invalid file or contains errors");
193     }
194 }
195 } //end namespace itk
196 
197 #endif //itkSmapsFileParser_hxx
198