Line data Source code
1 : // Snap Websites Server -- read /proc/meminfo
2 : // Copyright (c) 2018-2019 Made to Order Software Corp. All Rights Reserved
3 : //
4 : // https://snapwebsites.org/
5 : // contact@m2osw.com
6 : //
7 : // This program is free software; you can redistribute it and/or modify
8 : // it under the terms of the GNU General Public License as published by
9 : // the Free Software Foundation; either version 2 of the License, or
10 : // (at your option) any later version.
11 : //
12 : // This program is distributed in the hope that it will be useful,
13 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : // GNU General Public License for more details.
16 : //
17 : // You should have received a copy of the GNU General Public License
18 : // along with this program; if not, write to the Free Software
19 : // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 :
21 : // self
22 : //
23 : #include "snapwebsites/meminfo.h"
24 :
25 :
26 : // snapwebsites lib
27 : //
28 : #include "snapwebsites/log.h"
29 :
30 :
31 : // snapdev lib
32 : //
33 : #include <snapdev/tokenize_string.h>
34 :
35 :
36 : // C++ lib
37 : //
38 : #include <algorithm>
39 : #include <fstream>
40 : #include <iostream>
41 : #include <map>
42 :
43 :
44 : // last include
45 : //
46 : #include <snapdev/poison.h>
47 :
48 :
49 :
50 :
51 : namespace snap
52 : {
53 :
54 :
55 : /** \brief Test whether this meminfo_t structure is considered valid.
56 : *
57 : * A valid meminfo_t structure is one that was returned by get_meminfo()
58 : * after reading the /proc/meminfo file without encountering any errors.
59 : *
60 : * An invalid meminfo_t structure is one that was just initialized.
61 : *
62 : * \return true if the structure is considered valid.
63 : */
64 0 : bool meminfo_t::is_valid() const
65 : {
66 : // we could test more but just that one should be enough
67 0 : return f_mem_total != 0;
68 : }
69 :
70 :
71 0 : meminfo_t get_meminfo()
72 : {
73 : // IMPORTANT NOTE:
74 : // We keep this as a static inside the get_meminfo() because
75 : // it is a slow initialization that we can avoid 99.9% of the
76 : // time (i.e. only functions that need to call get_meminfo()
77 : // will ever initialize that map)
78 : //
79 : // note that all the values are uint64_t which is why we can
80 : // use just one single map
81 : //
82 : typedef uint64_t meminfo_t::* offset_t;
83 : static std::map<std::string const, offset_t const> const name_to_offset =
84 : {
85 : { "memtotal", &meminfo_t::f_mem_total },
86 : { "memfree", &meminfo_t::f_mem_free },
87 : { "memavailable", &meminfo_t::f_mem_available },
88 : { "buffers", &meminfo_t::f_buffers },
89 : { "cached", &meminfo_t::f_cached },
90 : { "swapcached", &meminfo_t::f_swap_cached },
91 : { "active", &meminfo_t::f_active },
92 : { "inactive", &meminfo_t::f_inactive },
93 : { "active(anon)", &meminfo_t::f_active_anon },
94 : { "inactive(anon)", &meminfo_t::f_inactive_anon },
95 : { "active(file)", &meminfo_t::f_active_file },
96 : { "inactive(file)", &meminfo_t::f_inactive_file },
97 : { "unevictable", &meminfo_t::f_unevictable },
98 : { "mlocked", &meminfo_t::f_mlocked },
99 : { "swaptotal", &meminfo_t::f_swap_total },
100 : { "swapfree", &meminfo_t::f_swap_free },
101 : { "dirty", &meminfo_t::f_dirty },
102 : { "writeback", &meminfo_t::f_writeback },
103 : { "anonpages", &meminfo_t::f_anon_pages },
104 : { "mapped", &meminfo_t::f_mapped },
105 : { "shmem", &meminfo_t::f_shmem },
106 : { "slab", &meminfo_t::f_slab },
107 : { "sreclaimable", &meminfo_t::f_sreclaimable },
108 : { "sunreclaim", &meminfo_t::f_sunreclaim },
109 : { "kernelstack", &meminfo_t::f_kernel_stack },
110 : { "pagetables", &meminfo_t::f_page_tables },
111 : { "nfs_unstable", &meminfo_t::f_nfs_unstable },
112 : { "bounce", &meminfo_t::f_bounce },
113 : { "writebacktmp", &meminfo_t::f_writeback_tmp },
114 : { "commitlimit", &meminfo_t::f_commit_limit },
115 : { "committed_as", &meminfo_t::f_committed_as },
116 : { "vmalloctotal", &meminfo_t::f_vmalloc_total },
117 : { "vmallocused", &meminfo_t::f_vmalloc_used },
118 : { "vmallocchunk", &meminfo_t::f_vmalloc_chunk },
119 : { "hardwarecorrupted", &meminfo_t::f_hardware_corrupted },
120 : { "anonhugepages", &meminfo_t::f_anon_huge_pages },
121 : { "cmatotal", &meminfo_t::f_cma_total },
122 : { "cmafree", &meminfo_t::f_cma_free },
123 : { "hugepages_total", &meminfo_t::f_huge_pages_total },
124 : { "hugepages_free", &meminfo_t::f_huge_pages_free },
125 : { "hugepages_rsvd", &meminfo_t::f_huge_pages_rsvd },
126 : { "hugepages_surp", &meminfo_t::f_huge_pages_surp },
127 : { "hugepagesize", &meminfo_t::f_huge_page_size },
128 : { "directmap4k", &meminfo_t::f_direct_map4k },
129 : { "directmap2m", &meminfo_t::f_direct_map2m },
130 : { "directmap1g", &meminfo_t::f_direct_map1g }
131 0 : };
132 :
133 0 : std::ifstream in;
134 0 : in.open("/proc/meminfo");
135 0 : if(!in.is_open())
136 : {
137 0 : return meminfo_t();
138 : }
139 :
140 0 : meminfo_t info;
141 : for(;;)
142 : {
143 : char buf[256];
144 0 : in.getline(buf, sizeof(buf));
145 0 : if(!in)
146 : {
147 0 : if(in.eof())
148 : {
149 0 : break;
150 : }
151 :
152 : // other errors and we return an "invalid" structure
153 : //
154 0 : return meminfo_t();
155 : }
156 0 : std::string line(buf);
157 0 : std::vector<std::string> tokens;
158 0 : size_t const size(tokenize_string(tokens, line, " \t", true, ":"));
159 0 : if(size >= 2)
160 : {
161 : // name / value [ / "kB"]
162 : //
163 0 : std::transform(tokens[0].begin(), tokens[0].end(), tokens[0].begin(), ::tolower);
164 0 : auto it(name_to_offset.find(tokens[0]));
165 0 : if(it != name_to_offset.end())
166 : {
167 : // it exists, save it in our structure
168 : //
169 0 : offset_t const o(it->second);
170 0 : info.*o = std::stoll(tokens[1]);
171 0 : if(size >= 3)
172 : {
173 0 : if(tokens[2] == "kB")
174 : {
175 : // assuming that "kB" means 1,000 bytes
176 : // transform to byte size so we don't have to guess
177 : // what it could possibly be outside of here
178 : //
179 0 : info.*o *= 1000;
180 : }
181 : }
182 : }
183 : else
184 : {
185 0 : SNAP_LOG_TRACE("unknown value in /proc/meminfo: \"")
186 0 : (line)
187 0 : ("\", meminfo.cpp() may need some updating.");
188 : }
189 : }
190 0 : }
191 :
192 0 : return info;
193 : }
194 :
195 :
196 6 : } // snap namespace
197 : // vim: ts=4 sw=4 et
|