LCOV - code coverage report
Current view: top level - snapwebsites - meminfo.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1 32 3.1 %
Date: 2019-12-15 17:13:15 Functions: 2 4 50.0 %
Legend: Lines: hit not hit

          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

Generated by: LCOV version 1.13