Refactoring homescreen.
[profile/ivi/ico-uxf-homescreen.git] / lib / system-controller / CicoSCSysResourceController.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 #include <memory>
10 #include <iostream>
11 #include <fstream>
12 #include <cstdlib>
13 #include <cstdio>
14
15 #include <dirent.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18
19 #include "CicoLog.h"
20 #include "CicoEvent.h"
21 #include "CicoEventInfo.h"
22 #include "CicoStateCore.h"
23 #include "CicoState.h"
24 #include "CicoHistoryState.h"
25 #include "CicoFinalState.h"
26 #include "CicoStateMachine.h"
27 #include "CicoStateMachineCreator.h"
28 #include "CicoSCSysResourceMonitor.h"
29 #include "CicoSCLifeCycleController.h"
30 #include "CicoSCSysResourceController.h"
31 #include "CicoSCConf.h"
32 #include "CicoSCSystemConfig.h"
33 #include <Ecore.h>
34 //#include <Ecore_Evas.h>
35
36 const int gEV1000 = 1000; // CPU event
37 const int gEV1001 = 1001; // MEMORY event
38
39 const string gstrSRCCPU_LOW  = "SRCCPU_LOW";
40 const string gstrSRCCPU_HIGH = "SRCCPU_HIGH";
41 const string gstrSRCMEM_LOW  = "SRCMEM_LOW";
42 const string gstrSRCMEM_HIGH = "SRCMEM_HIGH";
43
44 static const string gstrStateMachineFileName = "CicoSCSysResourceSM.json";
45
46 bool g_RC_LOG = false;
47 int  g_samplingWaitTimer = 200;
48
49 Ecore_Timer* g_SCResourceWatch = 0;
50 static Eina_Bool ico_SCResourceWatch(void *data)
51 {
52     if (g_RC_LOG) ICO_TRA("start data(%x)", data);
53     if ((NULL == data) || (0 == data)) {
54         if (g_RC_LOG) ICO_TRA("end");
55         return ECORE_CALLBACK_RENEW;
56     }
57     CicoSCSysResourceController* oCSCSRC = (CicoSCSysResourceController*)data;
58     oCSCSRC->watch();
59 //    double tVal = (double)g_samplingWaitTimer / 100;
60 //    ecore_timer_add(g_samplingWaitTimer, ico_SCResourceWatch, data);
61     if (g_RC_LOG) ICO_TRA("end");
62     return ECORE_CALLBACK_RENEW;
63 }
64
65
66 /**
67  * @brief constractor
68  */
69 CicoSCSysResourceController::CicoSCSysResourceController()
70 {
71     ICO_TRA("start");
72     m_cgrpCPU = 0;
73     m_cgrpMEM = 0;
74     m_cpu = -1;
75     m_mem = -1;
76     m_rConf = CicoSCSystemConfig::getInstance()->getResourceConf();
77     if (0 != m_rConf) {
78         g_RC_LOG = m_rConf->m_bLog;
79         if (-1 != m_rConf->m_sampling) {
80             g_samplingWaitTimer = m_rConf->m_sampling;
81         }
82     }
83     // cpu,cpuacct cgroup init
84     init_cgroup();  // cgroup 
85     m_monitor = new CicoSCSysResourceMonitor();
86     CicoSCSystemConfig* CSCSC = CicoSCSystemConfig::getInstance();
87     string filePath(CSCSC->getDefaultConf()->confdir);
88     filePath += string("/");
89     filePath += gstrStateMachineFileName;
90
91     CicoStateMachineCreator csmc;
92     m_stt = csmc.createFile(filePath);
93     if ((CicoStateMachine*)0 == m_stt) {
94         ICO_ERR("state machine create error(%s)", filePath.c_str());
95         return;
96     }
97
98     m_SRCCPU_LOW  = new CicoSRCCPU_LOW(this);
99     m_SRCCPU_HIGH = new CicoSRCCPU_HIGH(this);
100     m_SRCMEM_LOW  = new CicoSRCMEM_LOW(this);
101     m_SRCMEM_HIGH = new CicoSRCMEM_HIGH(this);
102
103     CicoState* s = (CicoState*)m_stt->getState(gstrSRCCPU_LOW);
104     if ((CicoState*)0 != s) {
105         s->addEntryAction(m_SRCCPU_LOW);
106         s->addDoAction(m_SRCCPU_LOW);
107     }
108     s = (CicoState*)m_stt->getState(gstrSRCCPU_HIGH);
109     if ((CicoState*)0 != s) {
110         s->addEntryAction(m_SRCCPU_HIGH);
111         s->addDoAction(m_SRCCPU_HIGH);
112     }
113     s = (CicoState*)m_stt->getState(gstrSRCMEM_LOW);
114     if ((CicoState*)0 != s) {
115         s->addEntryAction(m_SRCMEM_LOW);
116         s->addDoAction(m_SRCMEM_LOW);
117     }
118     s = (CicoState*)m_stt->getState(gstrSRCMEM_HIGH);
119     if ((CicoState*)0 != s) {
120         s->addEntryAction(m_SRCMEM_HIGH);
121         s->addDoAction(m_SRCMEM_HIGH);
122     }
123     m_stt->start();
124     double tVal = (double)g_samplingWaitTimer / 100;
125 #if 1
126     ICO_TRA("ECORE_TIMER(%f)", tVal);
127     g_SCResourceWatch = ecore_timer_add(tVal, ico_SCResourceWatch, this);
128 #else
129     ICO_TRA("ECORE_TIMER(%f)", tVal);
130     g_SCResourceWatch = ecore_timer_add(tVal, ico_SCResourceWatch, 0);
131 #endif
132     ICO_TRA("end");
133 }
134
135 /**
136  * @brief destructor
137  */
138 CicoSCSysResourceController::~CicoSCSysResourceController()
139 {
140     ICO_TRA("start");
141     if (0 != g_SCResourceWatch) {
142         ecore_timer_del(g_SCResourceWatch);
143     }
144
145     if ((CicoStateMachine*)0 != m_stt) {
146         m_stt->stop();
147         delete m_stt;
148         m_stt = (CicoStateMachine*)0;
149         ICO_TRA("delete CicoStateMachine");
150     }
151
152     if ((CicoSRCCPU_LOW*)0 != m_SRCCPU_LOW) {
153         delete m_SRCCPU_LOW;
154         m_SRCCPU_LOW = (CicoSRCCPU_LOW*)0;
155         ICO_TRA("delete CicoSRCCPU_LOW");
156     }
157
158     if ((CicoSRCCPU_HIGH*)0 != m_SRCCPU_HIGH) {
159         delete m_SRCCPU_HIGH;
160         m_SRCCPU_HIGH = (CicoSRCCPU_HIGH*)0;
161         ICO_TRA("delete CicoSRCCPU_HIGH");
162     }
163
164     if ((CicoSRCMEM_LOW*)0 != m_SRCMEM_LOW) {
165         delete m_SRCMEM_LOW;
166         m_SRCMEM_LOW = (CicoSRCMEM_LOW*)0;
167         ICO_TRA("delete CicoSRCMEM_LOW");
168     }
169
170     if ((CicoSRCMEM_HIGH*)0 != m_SRCMEM_HIGH) {
171         delete m_SRCMEM_HIGH;
172         m_SRCMEM_HIGH = (CicoSRCMEM_HIGH*)0;
173         ICO_TRA("delete CicoSRCMEM_HIGH");
174     }
175
176     if ((CicoSCSysResourceMonitor*)0 != m_monitor) {
177         delete m_monitor;
178         m_monitor = (CicoSCSysResourceMonitor*)0;
179         ICO_TRA("delete CicoSCSysResourceMonitor");
180     }
181     ICO_TRA("end");
182 }
183
184 /**
185  * @brief watch
186  * @return true:change level false:no change
187  */
188 bool CicoSCSysResourceController::watch()
189 {
190     if (g_RC_LOG) ICO_TRA("start");
191     if ((CicoSCSysResourceMonitor*)0 == m_monitor) {
192         if (g_RC_LOG) ICO_TRA("end false");
193         return false;
194     }
195     bool r = false;
196     m_monitor->monitoring();
197     int cpu = m_monitor->getCPUuser(); // application cpu
198     if (-1 != cpu) {
199         cpu /= 100;
200         if (g_RC_LOG) ICO_TRA("cpu %d -> %d", m_cpu, cpu);
201         CicoEvent ev(gEV1000, cpu);
202         m_stt->eventEntry(ev);
203         m_cpu = cpu;
204         r = true;
205     }
206     int mem = m_monitor->getUsageFreeMem(); // free memory
207     if (-1 != mem) {
208         mem = (10000 - mem)/100;  // free->used memory calc
209         CicoEvent ev(gEV1001, mem);
210         m_stt->eventEntry(ev);
211         m_mem = mem;
212         r = true;
213     }
214     if (g_RC_LOG) ICO_TRA("end %s", r? "true": "false");
215     return r;
216 }
217
218 /**
219  * @brief CPU share control request
220  * @param pulus true:level up / false level down
221  */
222 void CicoSCSysResourceController::resourceControlCPUShares(bool bHight)
223 {
224     ICO_TRA("start %s",
225             bHight? "true": "false");
226     if ((NULL == m_rConf) || (false == m_rConf->m_bDoIt)) {
227         ICO_TRA("end");
228         return;
229     }
230     if (true == m_rConf->m_cpuCtrl.empty()) {
231         ICO_TRA("end");
232         return;
233     }
234     int newCgrpCPU = -1;
235     int sz = m_rConf->m_cpuCtrl.size();
236     for (int i = 0; i < sz; i++) {
237         if (true == m_RCCpuShares[i].empty()) { // write target none
238             continue; // next target
239         }
240         int sharesVal = -1; // initialize cpu.shares value
241         if (true == bHight) {
242             if (m_cgrpCPU < (int)m_rConf->m_cpuCtrl[i]->m_hight.size()) {
243                 sharesVal = m_rConf->m_cpuCtrl[i]->m_hight[m_cgrpCPU];
244                 newCgrpCPU = m_cgrpCPU + 1;
245                 ICO_DBG("m_hight[%d]=%d", m_cgrpCPU, sharesVal);
246             }
247         }
248         else {
249             if (0 != m_cgrpCPU) {
250                 int tmp = m_cgrpCPU - 1;
251                 if (tmp < (int)m_rConf->m_cpuCtrl[i]->m_low.size()) {
252                     sharesVal = m_rConf->m_cpuCtrl[i]->m_low[tmp];
253                     newCgrpCPU = tmp;
254                     ICO_DBG("m_low[%d]=%d", tmp, sharesVal);
255                 }
256             }
257         }
258         if (0 <= sharesVal) {
259             replaceCgroupFile(m_RCCpuShares[i], sharesVal);
260         }
261 //        else if (-9 == sharesVal) {
262 //        }
263     }
264     if (-1 != newCgrpCPU) { // control level value check
265         ICO_DBG("control level %d -> %d", m_cgrpCPU, newCgrpCPU);
266         m_cgrpCPU = newCgrpCPU; // set next control level
267     }
268     ICO_TRA("end");
269 }
270
271 bool CicoSCSysResourceController::replaceCgroupFile(const std::string& tgt,
272                                                     int val)
273 {
274     char sv[64];
275     sprintf(sv, "%d", val);
276     return replaceCgroupFile(tgt, sv);
277 }
278
279 bool CicoSCSysResourceController::replaceCgroupFile(const std::string& tgt,
280                                                     const char* val)
281 {
282     ICO_TRA("start");
283     if (true == tgt.empty()) {
284         ICO_TRA("end");
285         return false;
286     }
287     FILE *fp = fopen(tgt.c_str(), "wt");
288     if (0 == fp) {
289         ICO_TRA("end open error %s", tgt.c_str());
290         return false;
291     }
292     fprintf(fp, val);
293     fclose(fp);
294     ICO_TRA("end Cmd(echo %s > %s", val, tgt.c_str());
295     return true;
296 }
297
298 /**
299  * @brief memory limit control request
300  * @param pulus true:level up / false level down
301  */
302 void CicoSCSysResourceController::resourceControlMemLimit(bool bHight)
303 {
304     ICO_TRA("start");
305     if ((NULL == m_rConf) || (false == m_rConf->m_bDoIt)) {
306         ICO_TRA("end");
307         return;
308     }
309     // TODO mk_k coming soon
310     if (true == bHight) {
311         // coming soon
312         ICO_TRA("hight (true)");
313     }
314     else {
315         // coming soon
316         ICO_TRA("low (false)");
317     }
318 //    m_cgrpMEM++;
319     ICO_TRA("end");
320 }
321
322
323
324 /**
325  * @breif
326  *
327  */
328 bool CicoSCSysResourceController::entryCgroupCPU(int pid, int grpNo)
329 {
330     ICO_TRA("start pid(%d), cgrpNo(%d)", pid, grpNo);
331     if ((0 > grpNo) || ((int)m_RCCpuTasks.size() <= grpNo)) {
332         ICO_TRA("end %d", m_RCCpuTasks.size());
333         return false;
334     }
335 #if 1
336     struct stat statbuf;
337     char procdir[128];
338     sprintf(procdir, "/proc/%d/task", pid);
339     if (0 != stat(procdir, &statbuf)) {
340         ICO_TRA("end %s ng dir", procdir);
341         return false;
342     }
343     DIR *dp;
344     dp = opendir(procdir);
345     if(dp == NULL) {
346         ICO_TRA("end opendir error");
347         return false;
348     }
349     struct dirent *ent;
350     while((ent = readdir(dp)) != NULL){
351         if (0 != isdigit(ent->d_name[0])) {
352             ICO_DBG("echo %s > %s", ent->d_name, m_RCCpuTasks[grpNo].c_str());
353             replaceCgroupFile(m_RCCpuTasks[grpNo], ent->d_name);
354         }
355     }
356     closedir(dp);
357     ICO_TRA("end");
358     return true;
359 #else
360     return replaceCgroupFile(m_RCCpuTasks[grpNo], pid);
361 #endif
362 }
363
364 /**
365  * @breif initialize cgroup 
366  */
367 void CicoSCSysResourceController::init_cgroup()
368 {
369     ICO_TRA("start");
370     init_cgroup_cpu();
371     // memory cgroup directory get
372     init_cgroup_memory();
373     ICO_TRA("end");
374 }
375
376 /**
377  * @breif initialize cgroup cpu
378  */
379 void CicoSCSysResourceController::init_cgroup_cpu()
380 {
381     ICO_TRA("start");
382     if (NULL == m_rConf) {
383         ICO_TRA("end");
384         return;
385     }
386     string ss("/");
387     string sTasks("tasks");
388     string sShares("cpu.shares");
389     string t1(m_rConf->m_cpuCGRPPath);
390     if ('/' != t1[t1.size()-1]) {
391         t1 += ss;
392     }
393     vector<string> d;
394     d.push_back(m_rConf->m_cpuCGRPPath);
395     int sz = m_rConf->m_cpuCtrl.size();
396     for (int i = 0; i < sz; i++) {
397         CicoSCCpuResourceGrp* obj = m_rConf->m_cpuCtrl[i];
398         string t2;
399         if (0 != obj) {
400             t2 = t1;
401             t2 += obj->m_grpNm;
402         }
403         else {
404             t2.clear();
405         }
406         d.push_back(t2);
407         string t3(t2);
408         string t4(t2);
409         if (false == t2.empty()) {
410             if ('/' != t2[t2.size()-1]) {
411                 t3 += ss;
412                 t4 += ss;
413             }
414             t3 += sTasks;
415             t4 += sShares;
416         }
417         m_RCCpuTasks.push_back(t3);
418         m_RCCpuShares.push_back(t4);
419     }
420     make_directorys(d);
421     ICO_TRA("end");
422     return;
423 }
424
425 /**
426  * @breif initialize cgroup memory
427  */
428 void CicoSCSysResourceController::init_cgroup_memory()
429 {
430     ICO_TRA("start");
431     if (NULL == m_rConf) {
432         ICO_TRA("end error config class");
433         return;
434     }
435     // Coming Soon
436     ICO_TRA("end");
437     return;
438 }
439
440 /**
441  * @breif make directory
442  * @param d create directory target
443  */
444 void CicoSCSysResourceController::make_directorys(std::vector<std::string> dir)
445 {
446     ICO_TRA("start");
447     int sz = dir.size();
448     for (int i = 0; i < sz; i++) {
449         if (true == dir[i].empty()) {
450             continue;
451         }
452         const char* dpath = dir[i].c_str();
453         struct stat stat_buf;
454         if (0 != stat(dpath, &stat_buf)) {
455             // drwxr-xr-x
456             int r = mkdir(dpath, S_IRUSR| S_IWUSR| S_IXUSR| S_IRGRP|
457                           S_IXGRP| S_IROTH| S_IXOTH);
458             ICO_DBG("%s create status(%d)", dpath, r);
459         }
460     }
461     ICO_TRA("end");
462 }
463
464 /**
465  * @brief Class ico System Resource Controller CPU LOW level
466  *        constructor
467  */
468 CicoSRCCPU_LOW::CicoSRCCPU_LOW(CicoSCSysResourceController* obj):
469     m_cntlr(obj)
470 {
471     ICO_TRA("constructor");
472     m_val = -1;      // cpu or memory usage value
473     m_baseVal = -1;  // cpu or memory base usage value
474 }
475
476 /**
477  * @brief Class ico System Resource Controller CPU LOW level
478  *        destructor
479  */
480 CicoSRCCPU_LOW::~CicoSRCCPU_LOW()
481 {
482     ICO_TRA("destructor");
483     m_cntlr = NULL;
484 }
485
486 /**
487  * @brief resource control entry state
488  * @param ev event data
489  * @param stt state object
490  */
491 void CicoSRCCPU_LOW::onEnttry(const CicoEvent& ev, const CicoState* stt, int)
492 {
493     ICO_TRA("start %s,%d,%d", stt->getName().c_str(),
494             ev.getEV(),ev.getGCVi());
495     m_baseVal = ev.getGCVi();
496     m_val = m_baseVal;
497 }
498
499 /**
500  * @brief cpu usage low resource control
501  * @param ev event data
502  * @param stt state object
503  */
504 void CicoSRCCPU_LOW::onDo(const CicoEvent& ev, const CicoState* stt, int)
505 {
506     int valN = ev.getGCVi();
507     ICO_TRA("start o(%d), n(%d)", m_val, valN);
508     if (valN >= m_val) {
509         // When the value is greater than the previous
510         ICO_TRA("end n(%d) >= o(%d)", m_val, valN);
511         return;
512     }
513     // When the value is less than the previous
514     int t = ((double)valN / (double)m_baseVal)*100;
515     if (50 <= t) {
516         m_cntlr->resourceControlCPUShares(false);
517         ICO_DBG("BASE CHG %d->%d",m_baseVal, valN);
518         m_baseVal = valN;
519     }
520     m_val = valN;
521     ICO_TRA("end");
522 }
523
524
525 /**
526  * @brief resource control exit state
527  * @param ev event data
528  * @param stt state object
529  */
530 void CicoSRCCPU_LOW::onExit(const CicoEvent&, const CicoState*, int)
531 {
532     ICO_TRA("start");
533     m_baseVal = -1;
534     m_val = -1;
535     ICO_TRA("end");
536 }
537
538 /**
539  * @brief Class ico System Resource Controller CPU HIGH level
540  *        constructor
541  */
542 CicoSRCCPU_HIGH::CicoSRCCPU_HIGH(CicoSCSysResourceController* obj):
543         CicoSRCCPU_LOW(obj)
544 {
545     ICO_TRA("constructor");
546 }
547
548 /**
549  * @brief Class ico System Resource Controller CPU HIGH level
550  *        destructor
551  */
552 CicoSRCCPU_HIGH::~CicoSRCCPU_HIGH()
553 {
554     ICO_TRA("destructor");
555 }
556
557 /**
558  * @brief cpu usage high resource control
559  * @param ev event data
560  * @param stt state object
561  */
562 void CicoSRCCPU_HIGH::onDo(const CicoEvent& ev, const CicoState* stt, int)
563 {
564     int valN = ev.getGCVi();
565     ICO_TRA("start o(%d), n(%d)", m_val, valN);
566     if (valN <= m_val) {
567         // When the value is less than the previous
568         ICO_TRA("end n(%d)<=o(%d)", valN, m_val);
569         return;
570     }
571     // When the value is greater than the previous
572     int t = ((double)(100-valN) / (double)(100-m_baseVal))*100;
573     if (50 <= t) {
574         m_cntlr->resourceControlCPUShares(true);
575         ICO_DBG("BASE CHG %d -> %d", m_baseVal, valN);
576         m_baseVal = valN;
577     }
578     m_val = valN;
579     ICO_TRA("end");
580 }
581
582 /**
583  * @brief Class ico System Resource Controller MEMory LOW level
584  *        constructor
585  */
586 CicoSRCMEM_LOW::CicoSRCMEM_LOW(CicoSCSysResourceController* obj):
587         CicoSRCCPU_LOW(obj)
588 {
589     ICO_TRA("constructor");
590 }
591
592 /**
593  * @brief Class ico System Resource Controller MEMory LOW level
594  *        constructor
595  */
596 CicoSRCMEM_LOW::~CicoSRCMEM_LOW()
597 {
598     ICO_TRA("destructor");
599 }
600
601 /**
602  * @brief memory usage low resource control
603  * @param ev event data
604  * @param stt state object
605  */
606 void CicoSRCMEM_LOW::onDo(const CicoEvent& ev, const CicoState* stt, int)
607 {
608     int valN = ev.getGCVi();
609     ICO_TRA("start o(%d), n(%d)", m_val, valN);
610     if (valN >= m_val) {
611         // When the value is greater than the previous
612         ICO_TRA("n(%d)>=o(%d)", valN, m_val);
613         return;
614     }
615     // When the value is less than the previous
616     int t = ((double)valN / (double)m_baseVal)*100;
617     if (50 <= t) {
618         m_cntlr->resourceControlMemLimit(false);
619         ICO_TRA("BASE CHG %d->%d",m_baseVal, valN);
620         m_baseVal = valN;
621     }
622     m_val = valN;
623     ICO_TRA("end");
624
625 }
626
627 /**
628  * @brief Class ico System Resource Controller MEMory HIGH level
629  *        constructor
630  */
631 CicoSRCMEM_HIGH::CicoSRCMEM_HIGH(CicoSCSysResourceController* obj):
632     CicoSRCCPU_LOW(obj)
633 {
634     ICO_TRA("constructor");
635 }
636
637 /**
638  * @brief Class ico System Resource Controller MEMory HIGH level
639  *        destructor
640  */
641 CicoSRCMEM_HIGH::~CicoSRCMEM_HIGH()
642 {
643     ICO_TRA("destructor");
644 }
645
646 /**
647  * @brief memory usage high resource control
648  * @param ev event data
649  * @param stt state object
650  */
651 void CicoSRCMEM_HIGH::onDo(const CicoEvent& ev, const CicoState* stt, int)
652 {
653     int valN = ev.getGCVi();
654     ICO_TRA("start o(%d), n(%d)", m_val, valN);
655     if (valN <= m_val) {
656         // When the value is less than the previous
657         ICO_TRA("end");
658         return;
659     }
660     // When the value is greater than the previous
661     int t = ((double)(100-valN) / (double)(100-m_baseVal))*100;
662     if (50 <= t) {
663         m_cntlr->resourceControlMemLimit(true);
664         ICO_TRA("BASE CHG %d -> %d", m_baseVal, valN);
665         m_baseVal = valN;
666     }
667     m_val = valN;
668     ICO_TRA("end");
669 }