1 /*
2  * Copyright (c) 2005-2007 Harm Schotanus
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  *    - Redistributions of source code must retain the above copyright
10  *      notice, this list of conditions and the following disclaimer.
11  *    - Redistributions in binary form must reproduce the above
12  *      copyright notice, this list of conditions and the following
13  *      disclaimer in the documentation and/or other materials provided
14  *      with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  *
29  */
30 
31 /*
32  * Get current memory statistics in bytes; reports them back in symon_buf as
33  *
34  * real active : real total : free : [swap used : swap total]
35  */
36 
37 #include <errno.h>
38 #include <fcntl.h>
39 #include <inttypes.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <unistd.h>
43 
44 #include "error.h"
45 #include "conf.h"
46 #include "symon.h"
47 #include "xmalloc.h"
48 
49 #define ktob(size) ((size) << 10)
50 
51 /* Globals for this module all start with me_ */
52 static void *me_buf = NULL;
53 static u_int64_t me_size = 0;
54 static u_int64_t me_maxsize = 0;
55 static u_int64_t me_stats[5];
56 
57 void
init_mem(struct stream * st)58 init_mem(struct stream *st)
59 {
60     if (me_buf == NULL) {
61         me_maxsize = SYMON_MAX_OBJSIZE;
62         me_buf = xmalloc(me_maxsize);
63     }
64 
65     info("started module mem(%.200s)", st->arg);
66 }
67 
68 void
gets_mem()69 gets_mem()
70 {
71    int fd;
72    if ((fd = open("/proc/meminfo", O_RDONLY)) < 0) {
73         warning("cannot access /proc/meminfo: %.200s", strerror(errno));
74    }
75 
76    bzero(me_buf, me_maxsize);
77    me_size = read(fd, me_buf, me_maxsize);
78    close(fd);
79 
80    if (me_size == me_maxsize) {
81         /* buffer is too small to hold all memory data */
82         me_maxsize += SYMON_MAX_OBJSIZE;
83         if (me_maxsize > SYMON_MAX_OBJSIZE * SYMON_MAX_DOBJECTS) {
84             fatal("%s:%d: dynamic object limit (%d) exceeded for cp data",
85                 __FILE__, __LINE__, SYMON_MAX_OBJSIZE * SYMON_MAX_DOBJECTS);
86         }
87         me_buf = xrealloc(me_buf, me_maxsize);
88         gets_mem();
89         return;
90     }
91 
92    if (me_size == -1) {
93        warning("could not read if statistics from /proc/meminfo: %.200s", strerror(errno));
94    }
95 }
96 
97 u_int64_t
mem_getitem(char * name)98 mem_getitem(char *name)
99 {
100     u_int64_t stat;
101     char *line;
102 
103     if (me_size <= 0) {
104         return 0;
105     }
106 
107     if ((line = strstr(me_buf, name)) == NULL) {
108         warning("could not find %s in /proc/meminfo", name);
109         return 0;
110     }
111 
112     line += strlen(name);
113     if (1 < sscanf(line, ": %" SCNu64 " Kb", &stat)) {
114         warning("could not parse memory statistics");
115         return 0;
116     } else {
117         return stat;
118     }
119 }
120 
121 int
get_mem(char * symon_buf,int maxlen,struct stream * st)122 get_mem(char *symon_buf, int maxlen, struct stream *st)
123 {
124     me_stats[0] = ktob(mem_getitem("Active"));
125     me_stats[1] = ktob(mem_getitem("MemTotal"));
126     me_stats[2] = ktob(mem_getitem("MemFree"));
127     me_stats[1] -= me_stats[2];
128     me_stats[3] = ktob(mem_getitem("SwapFree"));
129     me_stats[4] = ktob(mem_getitem("SwapTotal"));
130 
131     me_stats[3] = me_stats[4] - me_stats[3];
132 
133     return snpack(symon_buf, maxlen, st->arg, MT_MEM2,
134                   me_stats[0], me_stats[1], me_stats[2],
135                   me_stats[3], me_stats[4]);
136 }
137