first batch of license fixes (boring)
[oweals/gnunet.git] / src / testbed / gnunet-service-testbed_meminfo.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2008--2013 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      Affero General Public License for more details.
14 */
15
16 #include "platform.h"
17 #include "gnunet_util_lib.h"
18
19 /*
20  * File for parsing top-level /proc entities.
21  * Copyright Copyright (C) 1992-1998 by Michael K. Johnson, johnsonm@redhat.com
22  * Copyright 1998-2003 Albert Cahalan
23  * June 2003, Fabian Frederick, disk and slab info
24  *
25  * This library is free software; you can redistribute it and/or
26  * modify it under the terms of the GNU Lesser General Public
27  * License as published by the Free Software Foundation; either
28  * version 2.1 of the License, or (at your option) any later version.
29  *
30  * This library is distributed in the hope that it will be useful,
31  * but WITHOUT ANY WARRANTY; without even the implied warranty of
32  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
33  * Lesser General Public License for more details.
34  *
35  * You should have received a copy of the GNU Lesser General Public
36  * License along with this library; if not, write to the Free Software
37  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
38  */
39
40 #define BAD_OPEN_MESSAGE                                        \
41 "Error: /proc must be mounted\n"                                \
42 "  To mount /proc at boot you need an /etc/fstab line like:\n"  \
43 "      proc   /proc   proc    defaults\n"                       \
44 "  In the meantime, run \"mount proc /proc -t proc\"\n"
45
46 #define STAT_FILE    "/proc/stat"
47 //static int stat_fd = -1;
48 #define UPTIME_FILE  "/proc/uptime"
49 //static int uptime_fd = -1;
50 #define LOADAVG_FILE "/proc/loadavg"
51 //static int loadavg_fd = -1;
52 #define MEMINFO_FILE "/proc/meminfo"
53 static int meminfo_fd = -1;
54 #define VMINFO_FILE "/proc/vmstat"
55 //static int vminfo_fd = -1;
56
57 // As of 2.6.24 /proc/meminfo seems to need 888 on 64-bit,
58 // and would need 1258 if the obsolete fields were there.
59 static char buf[2048];
60
61 /* This macro opens filename only if necessary and seeks to 0 so
62  * that successive calls to the functions are more efficient.
63  * It also reads the current contents of the file into the global buf.
64  */
65 #define FILE_TO_BUF(filename, fd) do{                           \
66     static int local_n;                                         \
67     if (fd == -1 && (fd = open(filename, O_RDONLY)) == -1) {    \
68         fputs(BAD_OPEN_MESSAGE, stderr);                        \
69         fflush(NULL);                                           \
70         _exit(102);                                             \
71     }                                                           \
72     lseek(fd, 0L, SEEK_SET);                                    \
73     if ((local_n = read(fd, buf, sizeof buf - 1)) < 0) {        \
74         perror(filename);                                       \
75         fflush(NULL);                                           \
76         _exit(103);                                             \
77     }                                                           \
78     buf[local_n] = '\0';                                        \
79 }while(0)
80
81
82 /***********************************************************************/
83 /*
84  * Copyright 1999 by Albert Cahalan; all rights reserved.
85  * This file may be used subject to the terms and conditions of the
86  * GNU Library General Public License Version 2, or any later version
87  * at your option, as published by the Free Software Foundation.
88  * This program is distributed in the hope that it will be useful,
89  * but WITHOUT ANY WARRANTY; without even the implied warranty of
90  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
91  * GNU Library General Public License for more details.
92  */
93
94 typedef struct mem_table_struct {
95   const char *name;     /* memory type name */
96   unsigned long *slot; /* slot in return struct */
97 } mem_table_struct;
98
99 static int compare_mem_table_structs(const void *a, const void *b){
100   return strcmp(((const mem_table_struct*)a)->name,((const mem_table_struct*)b)->name);
101 }
102
103 /* example data, following junk, with comments added:
104  *
105  * MemTotal:        61768 kB    old
106  * MemFree:          1436 kB    old
107  * MemShared:           0 kB    old (now always zero; not calculated)
108  * Buffers:          1312 kB    old
109  * Cached:          20932 kB    old
110  * Active:          12464 kB    new
111  * Inact_dirty:      7772 kB    new
112  * Inact_clean:      2008 kB    new
113  * Inact_target:        0 kB    new
114  * Inact_laundry:       0 kB    new, and might be missing too
115  * HighTotal:           0 kB
116  * HighFree:            0 kB
117  * LowTotal:        61768 kB
118  * LowFree:          1436 kB
119  * SwapTotal:      122580 kB    old
120  * SwapFree:        60352 kB    old
121  * Inactive:        20420 kB    2.5.41+
122  * Dirty:               0 kB    2.5.41+
123  * Writeback:           0 kB    2.5.41+
124  * Mapped:           9792 kB    2.5.41+
125  * Slab:             4564 kB    2.5.41+
126  * Committed_AS:     8440 kB    2.5.41+
127  * PageTables:        304 kB    2.5.41+
128  * ReverseMaps:      5738       2.5.41+
129  * SwapCached:          0 kB    2.5.??+
130  * HugePages_Total:   220       2.5.??+
131  * HugePages_Free:    138       2.5.??+
132  * Hugepagesize:     4096 kB    2.5.??+
133  */
134
135 /* obsolete */
136 unsigned long kb_main_shared;
137 /* old but still kicking -- the important stuff */
138 unsigned long kb_main_buffers;
139 unsigned long kb_main_cached;
140 unsigned long kb_main_free;
141 unsigned long kb_main_total;
142 unsigned long kb_swap_free;
143 unsigned long kb_swap_total;
144 /* recently introduced */
145 unsigned long kb_high_free;
146 unsigned long kb_high_total;
147 unsigned long kb_low_free;
148 unsigned long kb_low_total;
149 /* 2.4.xx era */
150 unsigned long kb_active;
151 unsigned long kb_inact_laundry;
152 unsigned long kb_inact_dirty;
153 unsigned long kb_inact_clean;
154 unsigned long kb_inact_target;
155 unsigned long kb_swap_cached;  /* late 2.4 and 2.6+ only */
156 /* derived values */
157 unsigned long kb_swap_used;
158 unsigned long kb_main_used;
159 /* 2.5.41+ */
160 unsigned long kb_writeback;
161 unsigned long kb_slab;
162 unsigned long nr_reversemaps;
163 unsigned long kb_committed_as;
164 unsigned long kb_dirty;
165 unsigned long kb_inactive;
166 unsigned long kb_mapped;
167 unsigned long kb_pagetables;
168 // seen on a 2.6.x kernel:
169 static unsigned long kb_vmalloc_chunk;
170 static unsigned long kb_vmalloc_total;
171 static unsigned long kb_vmalloc_used;
172 // seen on 2.6.24-rc6-git12
173 static unsigned long kb_anon_pages;
174 static unsigned long kb_bounce;
175 static unsigned long kb_commit_limit;
176 static unsigned long kb_nfs_unstable;
177 static unsigned long kb_swap_reclaimable;
178 static unsigned long kb_swap_unreclaimable;
179
180 void meminfo(void){
181   char namebuf[16]; /* big enough to hold any row name */
182   mem_table_struct findme = { namebuf, NULL};
183   mem_table_struct *found;
184   char *head;
185   char *tail;
186   static const mem_table_struct mem_table[] = {
187   {"Active",       &kb_active},       // important
188   {"AnonPages",    &kb_anon_pages},
189   {"Bounce",       &kb_bounce},
190   {"Buffers",      &kb_main_buffers}, // important
191   {"Cached",       &kb_main_cached},  // important
192   {"CommitLimit",  &kb_commit_limit},
193   {"Committed_AS", &kb_committed_as},
194   {"Dirty",        &kb_dirty},        // kB version of vmstat nr_dirty
195   {"HighFree",     &kb_high_free},
196   {"HighTotal",    &kb_high_total},
197   {"Inact_clean",  &kb_inact_clean},
198   {"Inact_dirty",  &kb_inact_dirty},
199   {"Inact_laundry",&kb_inact_laundry},
200   {"Inact_target", &kb_inact_target},
201   {"Inactive",     &kb_inactive},     // important
202   {"LowFree",      &kb_low_free},
203   {"LowTotal",     &kb_low_total},
204   {"Mapped",       &kb_mapped},       // kB version of vmstat nr_mapped
205   {"MemFree",      &kb_main_free},    // important
206   {"MemShared",    &kb_main_shared},  // important, but now gone!
207   {"MemTotal",     &kb_main_total},   // important
208   {"NFS_Unstable", &kb_nfs_unstable},
209   {"PageTables",   &kb_pagetables},   // kB version of vmstat nr_page_table_pages
210   {"ReverseMaps",  &nr_reversemaps},  // same as vmstat nr_page_table_pages
211   {"SReclaimable", &kb_swap_reclaimable}, // "swap reclaimable" (dentry and inode structures)
212   {"SUnreclaim",   &kb_swap_unreclaimable},
213   {"Slab",         &kb_slab},         // kB version of vmstat nr_slab
214   {"SwapCached",   &kb_swap_cached},
215   {"SwapFree",     &kb_swap_free},    // important
216   {"SwapTotal",    &kb_swap_total},   // important
217   {"VmallocChunk", &kb_vmalloc_chunk},
218   {"VmallocTotal", &kb_vmalloc_total},
219   {"VmallocUsed",  &kb_vmalloc_used},
220   {"Writeback",    &kb_writeback},    // kB version of vmstat nr_writeback
221   };
222   const int mem_table_count = sizeof(mem_table)/sizeof(mem_table_struct);
223
224   FILE_TO_BUF(MEMINFO_FILE,meminfo_fd);
225
226   kb_inactive = ~0UL;
227
228   head = buf;
229   for(;;){
230     tail = strchr(head, ':');
231     if(!tail) break;
232     *tail = '\0';
233     if(strlen(head) >= sizeof(namebuf)){
234       head = tail+1;
235       goto nextline;
236     }
237     strcpy(namebuf,head);
238     found = bsearch(&findme, mem_table, mem_table_count,
239         sizeof(mem_table_struct), compare_mem_table_structs
240     );
241     head = tail+1;
242     if(!found) goto nextline;
243     *(found->slot) = (unsigned long)strtoull(head,&tail,10);
244 nextline:
245     tail = strchr(head, '\n');
246     if(!tail) break;
247     head = tail+1;
248   }
249   if(!kb_low_total){  /* low==main except with large-memory support */
250     kb_low_total = kb_main_total;
251     kb_low_free  = kb_main_free;
252   }
253   if(kb_inactive==~0UL){
254     kb_inactive = kb_inact_dirty + kb_inact_clean + kb_inact_laundry;
255   }
256   kb_swap_used = kb_swap_total - kb_swap_free;
257   kb_main_used = kb_main_total - kb_main_free;
258 }