Merge "add missing packages requires" into tizen
[profile/ivi/ico-uxf-homescreen.git] / lib / system-controller / CicoSCSysResourceMonitor.cpp
1 /*
2  * Copyright (c) 2013, TOYOTA MOTOR CORPORATION.
3  *
4  * This program is licensed under the terms and conditions of the
5  * Apache License, version 2.0.  The full text of the Apache License is at
6  * http://www.apache.org/licenses/LICENSE-2.0
7  *
8  */
9
10 #include <iostream>
11 #include <string>
12 #include <fstream>
13 #include <memory>
14 #include <cstdlib>
15 #include <cstring>
16 #include "CicoLog.h"
17 #include "CicoSCSysResourceMonitor.h"
18 using namespace std;
19 extern bool g_RC_LOG;
20
21 const char* rdTgtCPU = "/proc/stat";
22 const char sP1C = 'c';
23 const char sP2P = 'p';
24 const char sP3U = 'u';
25 const int nDmyCpuCnt = 17;   // CPU(16) + Total(1)
26
27 const double dCarryUp = 10000;
28
29 const char* rdTgtMEM = "/proc/meminfo";
30 const string rdMEMTag1 = "MemFree:";
31 const string rdMEMTag2 = "MemTotal:";
32
33 /**
34  * @brief Constructor
35  */
36 CicoSCSysResourceMonitor::CicoSCSysResourceMonitor()
37 {
38     ICO_TRA("start constructor");
39     m_CPUcnt = 0;
40     m_old = (stat_data_t*)0;
41     m_current = (stat_data_t*)0;
42     m_calc = (stat_data_t*)0;
43     m_totalMem = 0;
44     m_freeMem = 0;
45     m_usageFreeMem = -1;
46     m_allready = false;
47     ICO_TRA("end constructor");
48 }
49
50 /**
51  * @brief destructor
52  */
53 CicoSCSysResourceMonitor::~CicoSCSysResourceMonitor()
54 {
55     ICO_TRA("start destructor");
56     if ((stat_data_t*)0 != m_old) {
57         delete[] m_old;
58         m_old = (stat_data_t*)0;
59     }
60     if ((stat_data_t*)0 != m_current) {
61         delete[] m_current;
62         m_current = (stat_data_t*)0;
63     }
64     if ((stat_data_t*)0 != m_calc) {
65         delete[] m_calc;
66         m_calc = (stat_data_t*)0;
67     }
68     ICO_TRA("end destructor");
69 }
70
71 /**
72  * @brief system usage
73  * @param cpu core cpu position -1:all 0-n:cpu position
74  * @return cpu usage(return value/100 = 0.00 - 100.00%)
75  *         -1:get fail
76  */
77 int CicoSCSysResourceMonitor::getCPUtime(E_USAGETYPE e, int cpu) const
78 {
79     if (g_RC_LOG) ICO_TRA("start %d, %d", e, cpu);
80     if (false == isAllReady()) {
81         ICO_TRA("is no ready!");
82         return -1;
83     }
84     int n = cpu + 1;
85     if ((0 > n) || (m_CPUcnt <= n)) {
86         if (g_RC_LOG) ICO_TRA("end cpu count error %d, %d", n, m_CPUcnt);
87         return -1;
88     }
89     int r = -1;
90     switch(e) {
91     case E_user:       // 1) Time spent in user mode.
92         r = m_calc[n].user;
93         break;
94     case E_nice:       // 2) Time spent in user mode with low priority (nice).
95         r = m_calc[n].nice;
96         break;
97     case E_system:     // 3) Time spent in system mode.
98         r = m_calc[n].system;
99         break;
100     case E_idle:       // 4) Time spent in the idle task.
101         r = m_calc[n].idle;
102         break;
103     case E_iowait:     // 5) Time waiting for I/O to complete.
104         r = m_calc[n].iowait;
105         break;
106     case E_irq:        // 6) Time servicing interrupts.
107         r = m_calc[n].irq;
108         break;
109     case E_softirq:    // 7) Time servicing softirqs.
110         r = m_calc[n].softirq;
111         break;
112     case E_steal:      // 8) Time stolen
113         r = m_calc[n].steal;
114         break;
115     case E_guest:      // 9) Time Guest OS
116         r = m_calc[n].guest;
117         break;
118     case E_guest_nice: // 10) Time guest OS(nice)
119         r = m_calc[n].guest_nice;
120         break;
121     default:
122         break;
123     }
124     if (g_RC_LOG) ICO_TRA("end success ret(%d)", r);
125     return r;
126 }
127
128 /**
129  * @brief monitoring
130  */
131 void CicoSCSysResourceMonitor::monitoring()
132 {
133     if (g_RC_LOG) ICO_TRA("call getResource");
134     getResource();
135 }
136
137 /**
138  * @brief getResource
139  *        CPU usage and free memory size get
140  */
141 void CicoSCSysResourceMonitor::getResource()
142 {
143     if (g_RC_LOG) ICO_TRA("call get resource CPU,MEM");
144     getResourceCPU();
145     getResourceMEM();
146 }
147
148 /**
149  * @brief getResourceCPU
150  */
151 void CicoSCSysResourceMonitor::getResourceCPU()
152 {
153     if (0 == m_CPUcnt) {
154         m_CPUcnt = createCurrentCPU();
155         size_t sz = m_CPUcnt + 1;
156         if (0 == m_old) {
157             m_old = new stat_data_t[sz];
158         }
159         if (0 == m_calc) {
160             m_calc = new stat_data_t[sz];
161         }
162         ICO_DBG("cpu count is %d", m_CPUcnt);
163         return;
164     }
165     if (((stat_data_t*)0 == m_old) || ((stat_data_t*)0 == m_current) || 
166         ((stat_data_t*)0 == m_calc)) {
167         ICO_DBG("error none new area");
168         return;
169     }
170     // set old value
171     size_t sz = m_CPUcnt + 1;
172     memcpy(m_old, m_current, sizeof(stat_data_t)*sz);
173     // read current value
174     readCurrentCPU();
175     // calc CPU usage
176     for (size_t i=0; i < sz; i++) {
177         usageCalcCPU(m_old[i], m_current[i], m_calc[i]);
178     }
179     m_allready = true;
180     if (g_RC_LOG) ICO_TRA("calc");
181 }
182
183 /**
184  * @brief CPU usage first read
185  *        area allocation and read
186  *        CPU core count
187  * @return CPU core count
188  */
189 int CicoSCSysResourceMonitor::createCurrentCPU()
190 {
191     if (0 != m_current) {
192         ICO_TRA("ret(0) current is zero!");
193         return 0;
194     }
195     int cnt = 0;
196     stat_data_t tmp[nDmyCpuCnt];
197     memset(tmp, 0, sizeof(tmp));
198     cnt = readProcStatCPU(tmp, nDmyCpuCnt-1);
199     if (0 == cnt) {
200         ICO_TRA("ret(0) cnt is zero!");
201         return 0;
202     }
203     size_t sz = cnt + 1;
204     m_current = new stat_data_t[sz];
205     memcpy(m_current, tmp, sizeof(stat_data_t)*sz);
206     ICO_TRA("ret cpu core count(%d)", cnt);
207     return cnt;
208 }
209
210 /**
211  * @brief CPU usage read
212  */
213 void CicoSCSysResourceMonitor::readCurrentCPU()
214 {
215     readProcStatCPU(m_current, m_CPUcnt);
216 }
217
218 /**
219  * @brief read /proc/stat CPU information
220  * @param sdtp destination read value
221  * @param cpucnt CPU core count
222  * @return read CPU count
223  */
224 int CicoSCSysResourceMonitor::readProcStatCPU(stat_data_t* sdtp, const int cpucnt)
225 {
226     int r = 0;
227     int sztmp = cpucnt;
228     string tag;
229     ifstream ifs(rdTgtCPU);
230     while(ifs >> tag) {
231         int tgt=-1;
232         const char* tags = tag.c_str();
233         if ((sP1C == tags[0]) && (sP2P == tags[1]) && (sP3U == tags[2])) {
234             if ('\0' == tags[3]) { // "cpu"
235                 tgt = 0;
236             }
237             else { // "cpuX" X = 0 - 9
238                 if (0 != isdigit(tags[3])) {
239                     int tmp_tgt = atoi(&tags[3]);
240                     if ((0 <= tmp_tgt) && (tmp_tgt < cpucnt)) {
241                         tgt = tmp_tgt + 1;
242                     }
243                 }
244             }
245         }
246         if (-1 != tgt) {
247             // get now value
248             ifs >> sdtp[tgt].user;
249             ifs >> sdtp[tgt].nice;
250             ifs >> sdtp[tgt].system;
251             ifs >> sdtp[tgt].idle;
252             ifs >> sdtp[tgt].iowait;
253             ifs >> sdtp[tgt].irq;
254             ifs >> sdtp[tgt].softirq;
255             ifs >> sdtp[tgt].steal;
256             ifs >> sdtp[tgt].guest;
257             ifs >> sdtp[tgt].guest_nice;
258             if (0 != tgt) {
259                 sztmp--;
260                 r++;
261             }
262         }
263         if (0==sztmp) {
264             break;    // break of while
265         }
266     }
267     ifs.close();
268     if (g_RC_LOG) ICO_TRA("ret(%d)", r);
269     return r;
270 }
271
272 /**
273  * @brief CPU usage calc
274  * @param old previous value
275  * @param current value of this time
276  * @param calc distnation calculated value
277  * @return true:calc success false:calc fail
278  */
279 bool CicoSCSysResourceMonitor::usageCalcCPU(const stat_data_t& old,
280                                      const stat_data_t& current,
281                                      stat_data_t& calc)
282 {
283     if (g_RC_LOG) ICO_TRA("start");
284     double ttl = 0;
285     double duser = current.user - old.user;
286     ttl += duser;
287     double dnice = current.nice - old.nice;
288     ttl += dnice;
289     double dsystem = current.system - old.system;
290     ttl += dsystem;
291     double didle = current.idle - old.idle;
292     ttl += didle;
293     double diowait = current.iowait - old.iowait;
294     ttl += diowait;
295     double dirq = current.irq - old.irq;
296     ttl += dirq;
297     double dsoftirq = current.softirq - old.softirq;
298     ttl += dsoftirq;
299     double dsteal = current.steal - old.steal;
300     ttl += dsteal;
301     double dguest = current.guest - old.guest;
302     ttl += dguest;
303     double dguest_nice = current.guest_nice - old.guest_nice;
304     ttl += dguest_nice;
305     if (0 == ttl) { // must not be divided by ZERO
306         if (g_RC_LOG) ICO_TRA("end divide zero!?");
307         return false;
308     }
309     calc.user = (int)(duser / ttl * dCarryUp);
310     calc.nice = (int)(dnice / ttl * dCarryUp);
311     calc.system = (int)(dsystem / ttl * dCarryUp);
312     calc.idle = (int)(didle / ttl * dCarryUp);
313     calc.iowait = (int)(diowait / ttl * dCarryUp);
314     calc.irq = (int)(dirq / ttl * dCarryUp);
315     calc.softirq = (int)(dsoftirq / ttl * dCarryUp);
316     calc.steal = (int)(dsteal / ttl * dCarryUp);
317     calc.guest = (int)(dguest / ttl * dCarryUp);
318     calc.guest_nice = (int)(dguest_nice / ttl * dCarryUp);
319     if (g_RC_LOG) ICO_TRA("end");
320     return true;
321 }
322
323 /**
324  * @brief get resource free memory
325  */
326 void CicoSCSysResourceMonitor::getResourceMEM()
327 {
328     if (g_RC_LOG) ICO_TRA("start");
329     if (0 >= m_totalMem) {
330         readProcMeminfo(true);
331     }
332     else {
333         readProcMeminfo();
334     }
335     if (g_RC_LOG) ICO_TRA("end");
336 }
337
338 /**
339  * @brief read /proc/meminfo
340  * @param ttlMem total memory read flag
341  */
342 void CicoSCSysResourceMonitor::readProcMeminfo(bool ttlMem)
343 {
344 #if 0
345     if (g_RC_LOG) ICO_TRA("start %s", ttlMem? "true": "false");
346     string tag;
347     ifstream ifs(rdTgtMEM);
348     bool tgt1 = false;
349     bool tgt2 = ttlMem;       // total memory get flag set
350     while(ifs >> tag) {
351         if (true == tgt2) {   // flag on
352             if (rdMEMTag2 == tag) { // is total memory tag?
353                 ifs >> m_totalMem; // total memory size get
354                 tgt2 = false; // flag off
355             }
356         }
357         if (rdMEMTag1 == tag) { // is free memory tag
358             ifs >> m_freeMem; // get free memory size
359             tgt1 = true;  // get flag on
360         }
361         if ((true == tgt1) && (false == tgt2)) {
362             break;   // break of while
363         }
364     }
365     ifs.close();
366     if (0 != m_totalMem) {
367         if (true == tgt1) {
368             m_usageFreeMem = (int)
369                 (((double)m_freeMem / (double)m_totalMem) * 10000);
370         }
371     }
372     else {
373         m_usageFreeMem = -1;
374     }
375     if (g_RC_LOG) ICO_TRA("end usage free mem st.(%d)", m_usageFreeMem);
376 #else 
377     m_usageFreeMem = -1;
378     return;
379 #endif
380 }