1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
|
// -*- C++ -*-
//
// Package: Services
// Class : ProcInfoFetcher
//
// Implementation:
// [Notes on implementation]
//
// Original Author: Chris Jones
// Created: Sun May 6 11:14:31 CDT 2012
//
// system include files
// user include files
#include <cstring>
#include <cassert>
#include <iostream>
#ifdef __linux__
#include <malloc.h>
#endif
#include <sstream>
//#include <stdio.h>
#include <string>
#include <fcntl.h>
#include <unistd.h>
#include "FWCore/Services/plugins/ProcInfoFetcher.h"
#include "FWCore/Utilities/interface/EDMException.h"
#include "FWCore/Utilities/interface/get_underlying_safe.h"
#include "FWCore/MessageLogger/interface/MessageLogger.h"
//
// constants, enums and typedefs
//
//
// static data member definitions
//
namespace {
struct linux_proc {
int pid; // %d
std::string comm;
char state; // %c
int ppid; // %d
int pgrp; // %d
int session; // %d
int tty; // %d
int tpgid; // %d
unsigned int flags; // %u [before linux 2.6 %lu]
unsigned long minflt; // %lu
unsigned long cminflt; // %lu
unsigned long majflt; // %lu
unsigned long cmajflt; // %lu
unsigned long utime; // %lu
unsigned long stime; // %lu
long cutime; // %ld
long cstime; // %ld
long priority; // %ld
long nice; // %ld
long num_threads; // %ld
long itrealvalue; // %ld
unsigned long long starttime; // %llu [before linux 2.6 %d]
unsigned long vsize; // %lu
long rss; // %ld
unsigned long rlim; // %lu
unsigned long startcode; // %lu
unsigned long endcode; // %lu
unsigned long startstack; // %lu
unsigned long kstkesp; // %lu
unsigned long kstkeip; // %lu
unsigned long signal; // %lu
unsigned long blocked; // %lu
unsigned long sigignore; // %lu
unsigned long sigcatch; // %lu
unsigned long wchan; // %lu
};
class Fetcher {
public:
friend Fetcher& operator>>(Fetcher&, int&);
friend Fetcher& operator>>(Fetcher&, long&);
friend Fetcher& operator>>(Fetcher&, unsigned int&);
friend Fetcher& operator>>(Fetcher&, unsigned long&);
friend Fetcher& operator>>(Fetcher&, unsigned long long&);
friend Fetcher& operator>>(Fetcher&, char&);
friend Fetcher& operator>>(Fetcher&, std::string&);
explicit Fetcher(char* buffer) : buffer_(buffer), save_(nullptr), delims_(" \t\n\f\v\r") {}
private:
int getInt() {
const char* t = getItem();
//std::cout <<"int '"<<t <<"'"<<std::endl;
return std::stoi(t);
}
long getLong() {
const char* t = getItem();
//std::cout <<"long '"<<t <<"'"<<std::endl;
return std::stol(t);
}
unsigned int getUInt() {
const char* t = getItem();
//std::cout <<"uint '"<<t <<"'"<<std::endl;
return std::stoul(t);
}
unsigned long getULong() {
const char* t = getItem();
//std::cout <<"ulong '"<<t <<"'"<<std::endl;
return std::stoul(t);
}
unsigned long long getULongLong() {
const char* t = getItem();
//std::cout <<"ulong '"<<t <<"'"<<std::endl;
return std::stoull(t);
}
char getChar() { return *getItem(); }
std::string getString() { return std::string(getItem()); }
char* getItem() {
char* item = strtok_r(buffer_, delims_, &save());
assert(item);
buffer_ = nullptr; // Null for subsequent strtok_r calls.
return item;
}
char const* save() const { return get_underlying_safe(save_); }
char*& save() { return get_underlying_safe(save_); }
edm::propagate_const<char*> buffer_;
edm::propagate_const<char*> save_;
char const* const delims_;
};
Fetcher& operator>>(Fetcher& iFetch, int& oValue) {
oValue = iFetch.getInt();
return iFetch;
}
Fetcher& operator>>(Fetcher& iFetch, long& oValue) {
oValue = iFetch.getLong();
return iFetch;
}
Fetcher& operator>>(Fetcher& iFetch, unsigned int& oValue) {
oValue = iFetch.getUInt();
return iFetch;
}
Fetcher& operator>>(Fetcher& iFetch, unsigned long& oValue) {
oValue = iFetch.getULong();
return iFetch;
}
Fetcher& operator>>(Fetcher& iFetch, unsigned long long& oValue) {
oValue = iFetch.getULongLong();
return iFetch;
}
Fetcher& operator>>(Fetcher& iFetch, char& oValue) {
oValue = iFetch.getChar();
return iFetch;
}
Fetcher& operator>>(Fetcher& iFetch, std::string& oValue) {
oValue = iFetch.getString();
return iFetch;
}
} // namespace
namespace edm {
namespace service {
ProcInfoFetcher::ProcInfoFetcher() : pg_size_(sysconf(_SC_PAGESIZE)) {
#ifdef __linux__
std::ostringstream ost;
ost << "/proc/" << getpid() << "/stat";
if ((fd_ = open(ost.str().c_str(), O_RDONLY)) < 0) {
throw Exception(errors::Configuration) << "Failed to open " << ost.str() << std::endl;
}
#endif
}
ProcInfoFetcher::~ProcInfoFetcher() {
#ifdef LINUX
close(fd_);
#endif
}
ProcInfo ProcInfoFetcher::fetch() const {
ProcInfo ret;
#ifdef __linux__
double pr_size = 0.0, pr_rssize = 0.0;
linux_proc pinfo;
int cnt;
lseek(fd_, 0, SEEK_SET);
if ((cnt = read(fd_, buf_, sizeof(buf_) - 1)) < 0) {
perror("Read of Proc file failed:");
return ProcInfo();
}
if (cnt > 0) {
buf_[cnt] = '\0';
try {
Fetcher fetcher(buf_);
fetcher >> pinfo.pid >> pinfo.comm >> pinfo.state >> pinfo.ppid >> pinfo.pgrp >> pinfo.session >> pinfo.tty >>
pinfo.tpgid >> pinfo.flags >> pinfo.minflt >> pinfo.cminflt >> pinfo.majflt >> pinfo.cmajflt >>
pinfo.utime >> pinfo.stime >> pinfo.cutime >> pinfo.cstime >> pinfo.priority >> pinfo.nice >>
pinfo.num_threads >> pinfo.itrealvalue >> pinfo.starttime >> pinfo.vsize >> pinfo.rss >> pinfo.rlim >>
pinfo.startcode >> pinfo.endcode >> pinfo.startstack >> pinfo.kstkesp >> pinfo.kstkeip >> pinfo.signal >>
pinfo.blocked >> pinfo.sigignore >> pinfo.sigcatch >> pinfo.wchan;
} catch (const std::exception& iE) {
LogWarning("ProcInfoFetcher") << "Parsing of Prof file failed:" << iE.what() << std::endl;
return ProcInfo();
}
// resident set size in pages
pr_size = (double)pinfo.vsize;
pr_rssize = (double)pinfo.rss;
ret.vsize = pr_size / (1024.0 * 1024.0);
ret.rss = (pr_rssize * pg_size_) / (1024.0 * 1024.0);
}
#else
ret.vsize = 0;
ret.rss = 0;
#endif
return ret;
}
} // namespace service
} // namespace edm
|