1 /*
2 Copyright 2005-2010 Jakub Kruszona-Zawadzki, Gemius SA, 2013-2014 EditShare, 2013-2015 Skytechnology sp. z o.o..
3
4 This file was part of MooseFS and is part of LizardFS.
5
6 LizardFS is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, version 3.
9
10 LizardFS is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with LizardFS If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "common/platform.h"
20 #include "master/chartsdata.h"
21
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <syslog.h>
28 #include <time.h>
29 #include <unistd.h>
30
31 #include "common/charts.h"
32 #include "common/event_loop.h"
33 #include "master/chunks.h"
34 #include "master/filesystem.h"
35 #include "master/filesystem_operations.h"
36 #include "master/matoclserv.h"
37
38 #if defined(LIZARDFS_HAVE_GETRUSAGE) && defined(LIZARDFS_HAVE_STRUCT_RUSAGE_RU_MAXRSS)
39 # include <sys/types.h>
40 # ifdef LIZARDFS_HAVE_SYS_RESOURCE_H
41 # include <sys/resource.h>
42 # endif
43 # ifdef LIZARDFS_HAVE_SYS_RUSAGE_H
44 # include <sys/rusage.h>
45 # endif
46 # ifndef RUSAGE_SELF
47 # define RUSAGE_SELF 0
48 # endif
49 # define MEMORY_USAGE 1
50 #endif
51
52 #if defined(LIZARDFS_HAVE_SETITIMER)
53 # include <sys/time.h>
54 # ifndef ITIMER_REAL
55 # define ITIMER_REAL 0
56 # endif
57 # ifndef ITIMER_VIRTUAL
58 # define ITIMER_VIRTUAL 1
59 # endif
60 # ifndef ITIMER_PROF
61 # define ITIMER_PROF 2
62 # endif
63 # define CPU_USAGE 1
64 #endif
65
66 #define CHARTS_FILENAME "stats.mfs"
67
68 #define CHARTS_UCPU 0
69 #define CHARTS_SCPU 1
70 #define CHARTS_DELCHUNK 2
71 #define CHARTS_REPLCHUNK 3
72 #define CHARTS_STATFS 4
73 #define CHARTS_GETATTR 5
74 #define CHARTS_SETATTR 6
75 #define CHARTS_LOOKUP 7
76 #define CHARTS_MKDIR 8
77 #define CHARTS_RMDIR 9
78 #define CHARTS_SYMLINK 10
79 #define CHARTS_READLINK 11
80 #define CHARTS_MKNOD 12
81 #define CHARTS_UNLINK 13
82 #define CHARTS_RENAME 14
83 #define CHARTS_LINK 15
84 #define CHARTS_READDIR 16
85 #define CHARTS_OPEN 17
86 #define CHARTS_READ 18
87 #define CHARTS_WRITE 19
88 #define CHARTS_MEMORY 20
89 #define CHARTS_PACKETSRCVD 21
90 #define CHARTS_PACKETSSENT 22
91 #define CHARTS_BYTESRCVD 23
92 #define CHARTS_BYTESSENT 24
93
94 #define CHARTS 25
95
96 /* name , join mode , percent , scale , multiplier , divisor */
97 #define STATDEFS { \
98 {"ucpu" ,CHARTS_MODE_ADD,1,CHARTS_SCALE_MICRO, 100,60}, \
99 {"scpu" ,CHARTS_MODE_ADD,1,CHARTS_SCALE_MICRO, 100,60}, \
100 {"delete" ,CHARTS_MODE_ADD,0,CHARTS_SCALE_NONE , 1, 1}, \
101 {"replicate" ,CHARTS_MODE_ADD,0,CHARTS_SCALE_NONE , 1, 1}, \
102 {"statfs" ,CHARTS_MODE_ADD,0,CHARTS_SCALE_NONE , 1, 1}, \
103 {"getattr" ,CHARTS_MODE_ADD,0,CHARTS_SCALE_NONE , 1, 1}, \
104 {"setattr" ,CHARTS_MODE_ADD,0,CHARTS_SCALE_NONE , 1, 1}, \
105 {"lookup" ,CHARTS_MODE_ADD,0,CHARTS_SCALE_NONE , 1, 1}, \
106 {"mkdir" ,CHARTS_MODE_ADD,0,CHARTS_SCALE_NONE , 1, 1}, \
107 {"rmdir" ,CHARTS_MODE_ADD,0,CHARTS_SCALE_NONE , 1, 1}, \
108 {"symlink" ,CHARTS_MODE_ADD,0,CHARTS_SCALE_NONE , 1, 1}, \
109 {"readlink" ,CHARTS_MODE_ADD,0,CHARTS_SCALE_NONE , 1, 1}, \
110 {"mknod" ,CHARTS_MODE_ADD,0,CHARTS_SCALE_NONE , 1, 1}, \
111 {"unlink" ,CHARTS_MODE_ADD,0,CHARTS_SCALE_NONE , 1, 1}, \
112 {"rename" ,CHARTS_MODE_ADD,0,CHARTS_SCALE_NONE , 1, 1}, \
113 {"link" ,CHARTS_MODE_ADD,0,CHARTS_SCALE_NONE , 1, 1}, \
114 {"readdir" ,CHARTS_MODE_ADD,0,CHARTS_SCALE_NONE , 1, 1}, \
115 {"open" ,CHARTS_MODE_ADD,0,CHARTS_SCALE_NONE , 1, 1}, \
116 {"read" ,CHARTS_MODE_ADD,0,CHARTS_SCALE_NONE , 1, 1}, \
117 {"write" ,CHARTS_MODE_ADD,0,CHARTS_SCALE_NONE , 1, 1}, \
118 {"memory" ,CHARTS_MODE_MAX,0,CHARTS_SCALE_NONE , 1, 1}, \
119 {"prcvd" ,CHARTS_MODE_ADD,0,CHARTS_SCALE_MILI ,1000,60}, \
120 {"psent" ,CHARTS_MODE_ADD,0,CHARTS_SCALE_MILI ,1000,60}, \
121 {"brcvd" ,CHARTS_MODE_ADD,0,CHARTS_SCALE_MILI ,8000,60}, \
122 {"bsent" ,CHARTS_MODE_ADD,0,CHARTS_SCALE_MILI ,8000,60}, \
123 {NULL ,0 ,0,0 , 0, 0} \
124 };
125
126 #define CALCDEFS { \
127 CHARTS_DEFS_END \
128 };
129
130 /* c1_def , c2_def , c3_def , join mode , percent , scale , multiplier , divisor */
131 #define ESTATDEFS { \
132 {CHARTS_DIRECT(CHARTS_UCPU) ,CHARTS_DIRECT(CHARTS_SCPU) ,CHARTS_NONE ,CHARTS_MODE_ADD,1,CHARTS_SCALE_MICRO, 100,60}, \
133 {CHARTS_NONE ,CHARTS_NONE ,CHARTS_NONE ,0 ,0,0 , 0, 0} \
134 };
135
136 static const uint32_t calcdefs[]=CALCDEFS
137 static const statdef statdefs[]=STATDEFS
138 static const estatdef estatdefs[]=ESTATDEFS
139
140 #ifdef CPU_USAGE
141 static struct itimerval it_set;
142 #endif
143
144 #ifdef MEMORY_USAGE
145 static uint64_t memusage;
chartsdata_memusage(void)146 uint64_t chartsdata_memusage(void) {
147 return memusage;
148 }
149 #else
chartsdata_memusage(void)150 uint64_t chartsdata_memusage(void) {
151 return 0;
152 }
153 #endif
154
chartsdata_refresh(void)155 void chartsdata_refresh(void) {
156 uint64_t data[CHARTS];
157 std::array<uint32_t, FsStats::Size> fsdata;
158 uint32_t i,del,repl; //,bin,bout,opr,opw,dbr,dbw,dopr,dopw,repl;
159 #ifdef CPU_USAGE
160 struct itimerval uc,pc;
161 uint32_t ucusec,pcusec;
162 #endif
163 #ifdef MEMORY_USAGE
164 struct rusage ru;
165 #endif
166
167 for (i=0 ; i<CHARTS ; i++) {
168 data[i]=CHARTS_NODATA;
169 }
170
171 #ifdef CPU_USAGE
172 // CPU usage
173 setitimer(ITIMER_VIRTUAL,&it_set,&uc); // user time
174 setitimer(ITIMER_PROF,&it_set,&pc); // user time + system time
175
176 if (uc.it_value.tv_sec<=999) { // on fucken linux timers can go backward !!!
177 uc.it_value.tv_sec = 999-uc.it_value.tv_sec;
178 uc.it_value.tv_usec = 999999-uc.it_value.tv_usec;
179 } else {
180 uc.it_value.tv_sec = 0;
181 uc.it_value.tv_usec = 0;
182 }
183 if (pc.it_value.tv_sec<=999) { // as abowe - who the hell has invented this stupid os !!!
184 pc.it_value.tv_sec = 999-pc.it_value.tv_sec;
185 pc.it_value.tv_usec = 999999-pc.it_value.tv_usec;
186 } else {
187 pc.it_value.tv_sec = 0;
188 uc.it_value.tv_usec = 0;
189 }
190
191 ucusec = uc.it_value.tv_sec*1000000U+uc.it_value.tv_usec;
192 pcusec = pc.it_value.tv_sec*1000000U+pc.it_value.tv_usec;
193
194 if (pcusec>ucusec) {
195 pcusec-=ucusec;
196 } else {
197 pcusec=0;
198 }
199 data[CHARTS_UCPU] = ucusec;
200 data[CHARTS_SCPU] = pcusec;
201 #endif
202
203 // memory usage
204 #ifdef MEMORY_USAGE
205 getrusage(RUSAGE_SELF,&ru);
206 # ifdef __APPLE__
207 memusage = ru.ru_maxrss;
208 # else
209 memusage = ru.ru_maxrss * UINT64_C(1024);
210 # endif
211 # ifdef __linux__
212 if (memusage==0) {
213 int fd = open("/proc/self/statm",O_RDONLY);
214 char statbuff[1000];
215 int l;
216 if (fd>=0) {
217 l = read(fd,statbuff,1000);
218 if (l<1000 && l>0) {
219 statbuff[l]=0;
220 memusage = strtoul(statbuff,NULL,10)*getpagesize();
221 }
222 close(fd);
223 }
224 }
225 # endif
226 if (memusage>0) {
227 data[CHARTS_MEMORY] = memusage;
228 }
229 #endif
230
231 chunk_stats(&del,&repl);
232 data[CHARTS_DELCHUNK]=del;
233 data[CHARTS_REPLCHUNK]=repl;
234 fs_retrieve_stats(fsdata);
235 for (i = 0 ; i < FsStats::Size; ++i) {
236 data[CHARTS_STATFS + i] = fsdata[i];
237 }
238 matoclserv_stats(data+CHARTS_PACKETSRCVD);
239
240 charts_add(data,eventloop_time()-60);
241 }
242
chartsdata_term(void)243 void chartsdata_term(void) {
244 chartsdata_refresh();
245 charts_store();
246 charts_term();
247 }
248
chartsdata_store(void)249 void chartsdata_store(void) {
250 charts_store();
251 }
252
chartsdata_init(void)253 int chartsdata_init (void) {
254 #ifdef CPU_USAGE
255 struct itimerval uc,pc;
256 #endif
257 #ifdef MEMORY_USAGE
258 struct rusage ru;
259 #endif
260
261 #ifdef CPU_USAGE
262 it_set.it_interval.tv_sec = 0;
263 it_set.it_interval.tv_usec = 0;
264 it_set.it_value.tv_sec = 999;
265 it_set.it_value.tv_usec = 999999;
266 setitimer(ITIMER_VIRTUAL,&it_set,&uc); // user time
267 setitimer(ITIMER_PROF,&it_set,&pc); // user time + system time
268 #endif
269 #ifdef MEMORY_USAGE
270 getrusage(RUSAGE_SELF,&ru);
271 # ifdef __APPLE__
272 memusage = ru.ru_maxrss;
273 # else
274 memusage = ru.ru_maxrss * 1024;
275 # endif
276 #endif
277
278 eventloop_timeregister(TIMEMODE_RUN_LATE,60,0,chartsdata_refresh);
279 eventloop_timeregister(TIMEMODE_RUN_LATE,3600,0,chartsdata_store);
280 eventloop_destructregister(chartsdata_term);
281 return charts_init(calcdefs,statdefs,estatdefs,CHARTS_FILENAME);
282 }
283