Add 'CpuSched' & Rearrange 'Swap' sections
[platform/core/system/resourced.git] / src / common / config-parser.c
1 /*
2  * resourced
3  *
4  * Copyright (c) 2013 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the License);
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 #include <stdio.h>
20 #include <string.h>
21 #include <errno.h>
22 #include <assert.h>
23 #include <limits.h>
24
25 #include "util.h"
26 #include "trace.h"
27 #include "config-parser.h"
28 #include "proc-common.h"
29 #include "cpu-cgroup.h"
30 #include "swap-common.h"
31 #include "dedup-common.h"
32 #include "compact-common.h"
33 #include "cpu-sched-common.h"
34
35 #define MAX_SECTION             64
36 #define CPU_INIT_PRIO   100
37
38 static int config_parse_swap_types(
39                                   const char *rvalue,
40                                   void *data)
41 {
42         enum swap_type *type = data;
43         char *word, *state;
44         size_t l;
45
46         if (is_empty(rvalue))
47                 return 0;
48
49         *type = 0;
50
51         FOREACH_WORD_SEPARATOR(word, l, rvalue, "+|", state) {
52                 if (strneq(word, "zram", l))
53                         *type |= SWAP_TYPE_ZRAM;
54                 else if (strneq(word, "file", l))
55                         *type |= SWAP_TYPE_FILE;
56                 else if (strneq(word, "zswap", l))
57                         *type |= SWAP_TYPE_ZSWAP;
58                 else
59                         return -EINVAL;
60         }
61
62         return 0;
63 }
64
65 static int config_parse_cpu_sched_features(const char *value)
66 {
67         int cpu_sched_type = CPU_SCHED_UNINITIALIZED;
68         char *word, *state;
69         size_t l;
70
71         if (is_empty(value))
72                 return cpu_sched_type;
73
74         FOREACH_WORD_SEPARATOR(word, l, value, ",", state) {
75                 if (strneq(word, RT_RUNTIME_SHARE, l))
76                         cpu_sched_type |= CPU_SCHED_RUNTIME_SHARE;
77                 else if (strneq(word, NO_RT_RUNTIME_SHARE, l))
78                         cpu_sched_type |= CPU_SCHED_NO_RUNTIME_SHARE;
79                 else if (strneq(word, RT_RUNTIME_GREED, l))
80                         cpu_sched_type |= CPU_SCHED_RUNTIME_GREED;
81                 else
82                         return CPU_SCHED_UNINITIALIZED;
83         }
84
85         return cpu_sched_type;
86 }
87
88 static int config_parse_time_us(const char *value)
89 {
90         char size;
91         char *ptr = strchr(value, 's');
92         if (ptr == NULL) {
93                 _E("[DEBUG] Cannot find 's' in the string (%s)", value);
94                 return 0;
95         }
96
97         if (value > (ptr - 1)) {
98                 _E("[DEBUG] Size of string should be larger than 1");
99                 return 0;
100         }
101
102         size = *(ptr - 1);
103         *(ptr - 1) = '\0';
104
105         if (size == ' ') {
106                 return atoi(value) * 1000 * 1000;
107         }
108         else if (size == 'm') {
109                 return atoi(value) * 1000;
110         }
111         else if (size == 'u') {
112                 return atoi(value);
113         }
114         else {
115                 _E("[DEBUG] Unknown unit of time");
116                 return 0;
117         }
118 }
119
120 static int optimizer_config(struct parse_result *result, void *user_data)
121 {
122         if (!result)
123                 return RESOURCED_ERROR_INVALID_PARAMETER;
124
125         struct swap_conf *swap_conf = get_swap_conf();
126         if (swap_conf == NULL) {
127                 _E("[DEBUG] swap configuration is NULL");
128                 return RESOURCED_ERROR_FAIL;
129         }
130
131         struct dedup_conf *dedup_conf = get_dedup_conf();
132         if (dedup_conf == NULL) {
133                 _E("[DEBUG] dedup configuration is NULL");
134                 return RESOURCED_ERROR_FAIL;
135         }
136
137         struct compact_conf *compact_conf = get_compact_conf();
138         if (compact_conf == NULL) {
139                 _E("[DEBUG] compact configuration is NULL");
140                 return RESOURCED_ERROR_FAIL;
141         }
142
143         struct cpu_sched_conf *cpu_sched_conf = get_cpu_sched_conf();
144         if (cpu_sched_conf == NULL) {
145                 _E("[DEBUG] cpu_sched configuration is NULL");
146                 return RESOURCED_ERROR_FAIL;
147         }
148
149         if (!strncmp(result->section, SWAP_SECTION, strlen(SWAP_SECTION)+1)) {
150                 if (!strncmp(result->name, SWAP_ENABLE_CONF, strlen(SWAP_ENABLE_CONF)+1)) {
151                         if (!strncmp(result->value, "yes", 4) ||
152                                 !strncmp(result->value, "1", 2) ||
153                                 !strncmp(result->value, "ok", 3))
154                                 swap_conf->enable = true;
155                         else if (!strncmp(result->value, "no", 3) ||
156                                 !strncmp(result->value, "0", 2))
157                                 swap_conf->enable = false;
158                         else {
159                                 _E("[DEBUG] Unknown value for %s", result->name);
160                                 return RESOURCED_ERROR_FAIL;
161                         }
162                 }
163                 else if (!strncmp(result->name, RECLAIM_AT_BOOT_CONF,
164                                         strlen(RECLAIM_AT_BOOT_CONF)+1)) {
165                         if (!strncmp(result->value, "yes", 4) ||
166                                 !strncmp(result->value, "1", 2) ||
167                                 !strncmp(result->value, "ok", 3))
168                                 swap_conf->boot_reclaim_enable = true;
169                         else if (!strncmp(result->value, "no", 3) ||
170                                 !strncmp(result->value, "0", 2))
171                                 swap_conf->boot_reclaim_enable = false;
172                         else {
173                                 _E("[DEBUG] Unknown value for %s", result->name);
174                                 return RESOURCED_ERROR_FAIL;
175                         }
176                 }
177                 else if (!strncmp(result->name, SWAP_TYPE_CONF,
178                                         strlen(SWAP_TYPE_CONF)+1)) {
179                         if (config_parse_swap_types(result->value, &swap_conf->swap_type) < 0) {
180                                 _E("[DEBUG] Failed to parse type of swap, so use default zram type");
181                                 swap_conf->swap_type = SWAP_TYPE_ZRAM;
182                         }
183 /*                      if (strlen(result->value) + 1 > sizeof(swap_conf->type)) {
184                                 _E("Size of swap_conf->type is not enough");
185                                 return RESOURCED_ERROR_OUT_OF_MEMORY;
186                         }
187                         strncpy(swap_conf->type, result->value, sizeof(swap_conf->type) - 1);*/
188                 }
189                 else if (!strncmp(result->name, VIP_GROUP_SWAPPINESS_CONF,
190                                         strlen(VIP_GROUP_SWAPPINESS_CONF)+1)) {
191                         swap_conf->swappiness[CGROUP_VIP] = atoi(result->value);
192                 }
193                 else if (!strncmp(result->name, HIGH_GROUP_SWAPPINESS_CONF,
194                                         strlen(HIGH_GROUP_SWAPPINESS_CONF)+1)) {
195                         swap_conf->swappiness[CGROUP_HIGH] = atoi(result->value);
196                 }
197                 else if (!strncmp(result->name, MEDIUM_GROUP_SWAPPINESS_CONF,
198                                         strlen(MEDIUM_GROUP_SWAPPINESS_CONF)+1)) {
199                         swap_conf->swappiness[CGROUP_MEDIUM] = atoi(result->value);
200                 }
201                 else if (!strncmp(result->name, LOWEST_GROUP_SWAPPINESS_CONF,
202                                         strlen(LOWEST_GROUP_SWAPPINESS_CONF)+1)) {
203                         swap_conf->swappiness[CGROUP_LOW] = atoi(result->value);
204                 }
205                 else {
206                         _E("[DEBUG] Unknown configuration name (%s) and value (%s) on section (%s)",
207                                         result->name, result->value, result->section);
208                 }
209         }
210         else if (!strncmp(result->section, ZRAM_SECTION, strlen(ZRAM_SECTION)+1)) {
211                 if (!strncmp(result->name, COMP_ALGORITHM_CONF, strlen(COMP_ALGORITHM_CONF)+1)) {
212                         if (strlen(result->value) + 1 > sizeof(swap_conf->zram.algorithm)) {
213                                 _E("Size of swap_conf->zram.algorithm is not enough");
214                                 return RESOURCED_ERROR_OUT_OF_MEMORY;
215                         }
216                         strncpy(swap_conf->zram.algorithm, result->value,
217                                         sizeof(swap_conf->zram.algorithm) - 1);
218                 }
219                 else if (!strncmp(result->name, ZRAM_RATIO_CONF, strlen(ZRAM_RATIO_CONF)+1)) {
220                         swap_conf->zram.ratio = atof(result->value);
221                 }
222                 else {
223                         _E("[DEBUG] Unknown configuration name (%s) and value (%s) on section (%s)",
224                                         result->name, result->value, result->section);
225                 }
226         }
227         else if (!strncmp(result->section, ZSWAP_SECTION, strlen(ZSWAP_SECTION)+1)) {
228                 if (!strncmp(result->name, POOL_RATIO_CONF, strlen(POOL_RATIO_CONF)+1)) {
229                         swap_conf->zswap.pool_ratio = atof(result->value);
230                 }
231                 else if (!strncmp(result->name, POOL_TYPE_CONF, strlen(POOL_TYPE_CONF)+1)) {
232                         if (strlen(result->value) + 1 > sizeof(swap_conf->zswap.pool_type)) {
233                                 _E("Size of swap_conf->zswap.pool_type is not enough");
234                                 return RESOURCED_ERROR_OUT_OF_MEMORY;
235                         }
236                         strncpy(swap_conf->zswap.pool_type, result->value,
237                                         sizeof(swap_conf->zswap.pool_type) - 1);
238                 }
239                 else {
240                         _E("[DEBUG] Unknown configuration name (%s) and value (%s) on section (%s)",
241                                         result->name, result->value, result->section);
242                 }
243         }
244         else if (!strncmp(result->section, DEDUP_SECTION, strlen(DEDUP_SECTION)+1)) {
245                 if (!strncmp(result->name, DEDUP_ENABLE_CONF, strlen(DEDUP_ENABLE_CONF)+1)) {
246                         if (!strncmp(result->value, "yes", 4) ||
247                                 !strncmp(result->value, "1", 2) ||
248                                 !strncmp(result->value, "ok", 3))
249                                 dedup_conf->enable = true;
250                         else if (!strncmp(result->value, "no", 3) ||
251                                 !strncmp(result->value, "0", 2))
252                                 dedup_conf->enable = false;
253                         else {
254                                 _E("[DEBUG] Unknown value for %s", result->name);
255                                 return RESOURCED_ERROR_FAIL;
256                         }
257                 }
258                 else if (!strncmp(result->name, DEDUP_AT_BOOT_CONF, strlen(DEDUP_AT_BOOT_CONF)+1)) {
259                         if (!strncmp(result->value, "yes", 4) ||
260                                 !strncmp(result->value, "1", 2) ||
261                                 !strncmp(result->value, "ok", 3))
262                                 dedup_conf->boot_dedup_enable = true;
263                         else if (!strncmp(result->value, "no", 3) ||
264                                 !strncmp(result->value, "0", 2))
265                                 dedup_conf->boot_dedup_enable = false;
266                         else {
267                                 _E("[DEBUG] Unknown value for %s", result->name);
268                                 return RESOURCED_ERROR_FAIL;
269                         }
270                 }
271                 else if (!strncmp(result->name, SCAN_ON_LOWMEM_CONF, strlen(SCAN_ON_LOWMEM_CONF)+1)) {
272                         if (!strncmp(result->value, "yes", 4) ||
273                                 !strncmp(result->value, "1", 2) ||
274                                 !strncmp(result->value, "ok", 3) ||
275                                 !strncmp(result->value, "true", 5))
276                                 dedup_conf->scan_on_lowmem = true;
277                         else if (!strncmp(result->value, "no", 3) ||
278                                 !strncmp(result->value, "0", 2) ||
279                                 !strncmp(result->value, "false", 6))
280                                 dedup_conf->scan_on_lowmem = false;
281                         else {
282                                 _E("[DEBUG] Unknown value for %s", result->name);
283                                 return RESOURCED_ERROR_FAIL;
284                         }
285                 }
286                 else {
287                         _E("[DEBUG] Unknown configuration name (%s) and value (%s) on section (%s)",
288                                         result->name, result->value, result->section);
289                 }
290         }
291         else if (!strncmp(result->section, KSM_SECTION, strlen(KSM_SECTION)+1)) {
292                 if (!strncmp(result->name, KSM_MODE_CONF, strlen(KSM_MODE_CONF)+1)) {
293                         if (strlen(result->value) + 1 > sizeof(dedup_conf->ksm.mode)) {
294                                 _E("Size of swap_conf->type is not enough");
295                                 return RESOURCED_ERROR_OUT_OF_MEMORY;
296                         }
297                         strncpy(dedup_conf->ksm.mode, result->value,
298                                         sizeof(dedup_conf->ksm.mode) - 1);
299                 }
300                 else if (!strncmp(result->name, PAGES_TO_SCAN_CONF, strlen(PAGES_TO_SCAN_CONF)+1)) {
301                         dedup_conf->ksm.pages = atoi(result->value);
302                 }
303                 else if (!strncmp(result->name, PAGES_TO_SCAN_WITH_BOOST_CONF,
304                                         strlen(PAGES_TO_SCAN_WITH_BOOST_CONF)+1)) {
305                         dedup_conf->ksm.boost_pages = atoi(result->value);
306                 }
307                 else {
308                         _E("[DEBUG] Unknown configuration name (%s) and value (%s) on section (%s)",
309                                         result->name, result->value, result->section);
310                 }
311         }
312         else if (!strncmp(result->section, COMPACTION_SECTION, strlen(COMPACTION_SECTION)+1)) {
313                 if (!strncmp(result->name, COMPACTION_ENABLE_CONF, strlen(COMPACTION_ENABLE_CONF)+1)) {
314                         if (!strncmp(result->value, "yes", 4) ||
315                                 !strncmp(result->value, "1", 2) ||
316                                 !strncmp(result->value, "ok", 3) ||
317                                 !strncmp(result->value, "true", 5))
318                                 compact_conf->enable = true;
319                         else if (!strncmp(result->value, "no", 3) ||
320                                 !strncmp(result->value, "0", 2) ||
321                                 !strncmp(result->value, "false", 6))
322                                 compact_conf->enable = false;
323                         else {
324                                 _E("[DEBUG] Unknown value for %s", result->name);
325                                 return RESOURCED_ERROR_FAIL;
326                         }
327                 }
328                 else if (!strncmp(result->name, FRAG_LEVEL_CONF, strlen(FRAG_LEVEL_CONF)+1)) {
329                         compact_conf->frag_level = atoi(result->value);
330                 }
331                 else {
332                         _E("[DEBUG] Unknown configuration name (%s) and value (%s) on section (%s)",
333                                         result->name, result->value, result->section);
334                 }
335         }
336         else if (!strncmp(result->section, CPU_SCHED_SECTION,
337                                 strlen(CPU_SCHED_SECTION)+1)) {
338                 if (!strncmp(result->name, CPU_SCHED_FEATURE_CONF,
339                                         strlen(CPU_SCHED_FEATURE_CONF) + 1)) {
340                         cpu_sched_conf->cpu_sched_flag = config_parse_cpu_sched_features(result->value);
341                 }
342                 else if (!strncmp(result->name, CPU_RT_RUN_TIME_CONF,
343                                         strlen(CPU_RT_RUN_TIME_CONF) + 1)) {
344                         cpu_sched_conf->rt_runtime_us = config_parse_time_us(result->value);
345                 }
346                 else if (!strncmp(result->name, CPU_RT_PERIOD_CONF,
347                                         strlen(CPU_RT_PERIOD_CONF) + 1)) {
348                         cpu_sched_conf->rt_period_us = config_parse_time_us(result->value);
349                 }
350                 else {
351                         _E("[DEBUG] Unknown configuration name (%s) and value (%s) on section (%s)",
352                                         result->name, result->value, result->section);
353                 }
354         }
355         else if (!strncmp(result->section, CPU_AFFINITY_SECTION,
356                                 strlen(CPU_AFFINITY_SECTION)+1)) {
357                 int error = RESOURCED_ERROR_NONE;
358
359                 if (!strncmp(result->name, FOREGROUND_APPS,
360                                         strlen(FOREGROUND_APPS) + 1)) {
361                         error = set_cpucg_conf(result->name, result->value);
362                 }
363                 else {
364                         _E("[DEBUG] Unknown configuration name (%s) and value (%s) on section (%s)",
365                                         result->name, result->value, result->section);
366                 }
367
368                 return error;
369         }
370         else {
371                 _E("[DEBUG] Unknown section name (%s) and value (%s) on section (%s)",
372                                 result->name, result->value, result->section);
373         }
374
375         return RESOURCED_ERROR_NONE;
376 }
377
378
379 static int limiter_config(struct parse_result *result, void *user_data)
380 {
381         if (!result)
382                 return RESOURCED_ERROR_INVALID_PARAMETER;
383
384         struct memcg_conf *memcg_conf = get_memcg_conf();
385         if (memcg_conf == NULL) {
386                 _E("[DEBUG] memory cgroup configuration is NULL");
387                 return RESOURCED_ERROR_FAIL;
388         }
389
390         if (!strncmp(result->section, MEMORY_GROUP_LIMIT_SECTION,
391                                 strlen(MEMORY_GROUP_LIMIT_SECTION)+1)) {
392                 char *ptr = strchr(result->value, '%');
393                 if (ptr == NULL) {
394                         _E("[DEBUG] Cannot find '%%' in the string (%s)", result->value);
395                         return RESOURCED_ERROR_FAIL;
396                 }
397                 else
398                         *ptr = '\0';
399
400                 if (!strncmp(result->name, VIP_GROUP_LIMIT_CONF,
401                                         strlen(VIP_GROUP_LIMIT_CONF) + 1)) {
402                         memcg_conf->cgroup_limit[CGROUP_VIP] = atof(result->value);
403                 }
404                 else if (!strncmp(result->name, HIGH_GROUP_LIMIT_CONF,
405                                         strlen(HIGH_GROUP_LIMIT_CONF) + 1)) {
406                         memcg_conf->cgroup_limit[CGROUP_HIGH] = atof(result->value);
407                 }
408                 else if (!strncmp(result->name, MEDIUM_GROUP_LIMIT_CONF,
409                                         strlen(MEDIUM_GROUP_LIMIT_CONF) + 1)) {
410                         memcg_conf->cgroup_limit[CGROUP_MEDIUM] = atof(result->value);
411                 }
412                 else if (!strncmp(result->name, LOWEST_GROUP_LIMIT_CONF,
413                                         strlen(LOWEST_GROUP_LIMIT_CONF) + 1)) {
414                         memcg_conf->cgroup_limit[CGROUP_LOW] = atof(result->value);
415                 }
416                 else {
417                         _E("[DEBUG] Unknown configuration name (%s) and value (%s) on section (%s)",
418                                         result->name, result->value, result->section);
419                 }
420         }
421         else if (!strncmp(result->section, MEMORY_LEVEL_THRESHOLD_SECTION,
422                                 strlen(MEMORY_LEVEL_THRESHOLD_SECTION)+1)) {
423
424                 if (!strncmp(result->name, OOM_POPUP_CONF,
425                                         strlen(OOM_POPUP_CONF) + 1)) {
426                         if (!strncmp(result->value, "yes", 4) ||
427                                 !strncmp(result->value, "1", 2) ||
428                                 !strncmp(result->value, "ok", 3))
429                                 memcg_conf->oom_popup = true;
430                         else if (!strncmp(result->value, "no", 3) ||
431                                 !strncmp(result->value, "0", 2))
432                                 memcg_conf->oom_popup = false;
433                         else {
434                                 _E("[DEBUG] Unknown value for %s", result->name);
435                                 return RESOURCED_ERROR_FAIL;
436                         }
437                 }
438                 else {
439                         char temp = '\0';
440                         int error = RESOURCED_ERROR_NONE;
441                         bool percent;
442                         char *ptr = strchr(result->value, '%');
443                         if (ptr == NULL) {
444                                 ptr = strchr(result->value, 'B');
445                                 if (ptr == NULL) {
446                                         _E("[DEBUG] Cannot find 'B' in the string (%s)", result->value);
447                                         return RESOURCED_ERROR_FAIL;
448                                 }
449
450                                 if (result->value > (ptr - 1)) {
451                                         _E("[DEBUG] Size of string should be larger than 1");
452                                         return RESOURCED_ERROR_FAIL;
453                                 }
454
455                                 temp = *(ptr - 1);
456                                 *(ptr - 1) = '\0';
457                                 percent = false;
458                         }
459                         else {
460                                 *ptr = '\0';
461                                 percent = true;
462                         }
463
464                         if (!strncmp(result->name, MEDIUM_LEVEL_CONF,
465                                                 strlen(MEDIUM_LEVEL_CONF) + 1)) {
466                                 error = set_memcg_conf_threshold(percent, temp, MEM_LEVEL_MEDIUM, result->value);
467                         }
468                         else if (!strncmp(result->name, LOW_LEVEL_CONF,
469                                                 strlen(LOW_LEVEL_CONF) + 1)) {
470                                 error = set_memcg_conf_threshold(percent, temp, MEM_LEVEL_LOW, result->value);
471                         }
472                         else if (!strncmp(result->name, CRITICAL_LEVEL_CONF,
473                                                 strlen(CRITICAL_LEVEL_CONF) + 1)) {
474                                 error = set_memcg_conf_threshold(percent, temp, MEM_LEVEL_CRITICAL, result->value);
475                         }
476                         else if (!strncmp(result->name, OOM_LEVEL_CONF,
477                                                 strlen(OOM_LEVEL_CONF) + 1)) {
478                                 error = set_memcg_conf_threshold(percent, temp, MEM_LEVEL_OOM, result->value);
479                         }
480
481                         else {
482                                 _E("[DEBUG] Unknown configuration name (%s) and value (%s) on section (%s)",
483                                                 result->name, result->value, result->section);
484                         }
485                         
486                         return error;
487                 }
488         }
489         else if (!strncmp(result->section, MEMORY_APP_TYPE_LIMIT_SECTION,
490                                 strlen(MEMORY_APP_TYPE_LIMIT_SECTION)+1)) {
491                 int error = RESOURCED_ERROR_NONE;
492
493                 if (!strncmp(result->name, SERVICE_PER_APP_LIMIT_ACTION,
494                                         strlen(SERVICE_PER_APP_LIMIT_ACTION) + 1)) {
495                         error = set_mem_action_conf(&memcg_conf->service, result->value);
496                 }
497                 else if (!strncmp(result->name, WIDGET_PER_APP_LIMIT_ACTION,
498                                         strlen(WIDGET_PER_APP_LIMIT_ACTION) + 1)) {
499                         error = set_mem_action_conf(&memcg_conf->widget, result->value);
500                 }
501                 else if (!strncmp(result->name, GUI_PER_APP_LIMIT_ACTION,
502                                         strlen(GUI_PER_APP_LIMIT_ACTION) + 1)) {
503                         error = set_mem_action_conf(&memcg_conf->guiapp, result->value);
504                 }
505                 else {
506                         _E("[DEBUG] Unknown configuration name (%s) and value (%s) on section (%s)",
507                                         result->name, result->value, result->section);
508                 }
509
510                 return error;
511         }
512         else if (!strncmp(result->section, MEMORY_APP_STATUS_LIMIT_SECTION,
513                                 strlen(MEMORY_APP_STATUS_LIMIT_SECTION)+1)) {
514                 int error = RESOURCED_ERROR_NONE;
515
516                 if (!strncmp(result->name, BACKGROUND_PER_APP_LIMIT_ACTION,
517                                         strlen(BACKGROUND_PER_APP_LIMIT_ACTION) + 1)) {
518                         error = set_mem_action_conf(&memcg_conf->background, result->value);
519                 }
520                 else {
521                         _E("[DEBUG] Unknown configuration name (%s) and value (%s) on section (%s)",
522                                         result->name, result->value, result->section);
523                 }
524
525                 return error;
526         }
527         else {
528                 _E("[DEBUG] Unknown section name (%s) and value (%s) on section (%s)",
529                                 result->name, result->value, result->section);
530         }
531
532         return RESOURCED_ERROR_NONE;
533 }
534
535 static int vendor_config(struct parse_result *result, void *user_data)
536 {
537         int *config_type = (int *)user_data;
538         static struct proc_conf_info *pci = NULL;
539
540         if (!result || !user_data)
541                 return RESOURCED_ERROR_INVALID_PARAMETER;
542
543         if (strncmp(result->section, PER_PROCESS_SECTION, strlen(PER_PROCESS_SECTION)+1))
544                 return RESOURCED_ERROR_NONE;
545
546         if (!strncmp(result->name, SERVICE_NAME_CONF, strlen(SERVICE_NAME_CONF)+1) ||
547                 !strncmp(result->name, APP_NAME_CONF, strlen(APP_NAME_CONF)+1)) {
548                 pci = fixed_app_and_service_exist_check(result->value,
549                                 result->name[0] == 'A' ? APP_TYPE : SERVICE_TYPE);
550                 if (pci == NULL) {
551                         pci = (struct proc_conf_info *)calloc(1, sizeof(struct proc_conf_info));
552                         if (pci == NULL) {
553                                 _E("Failed to allocate memory during parsing vendor configurations");
554                                 return RESOURCED_ERROR_OUT_OF_MEMORY;
555                         }
556                         pci->mem_type = CGROUP_TOP;
557                         pci->cpu_type = CGROUP_TOP;
558                         pci->cpu_priority = CPU_INIT_PRIO;
559                         pci->watchdog_action = PROC_ACTION_KILL;
560                         pci->fail_action = PROC_ACTION_IGNORE;
561                         strncpy(pci->name, result->value, sizeof(pci->name)-1);
562
563                         if (result->name[0] == 'A') {
564                                 fixed_app_list_insert(pci);
565                         }
566                         else {
567                                 fixed_service_list_insert(pci);
568                         }
569                 }
570         }
571         else if (!strncmp(result->name, CPU_CGROUP_NAME_CONF, strlen(CPU_CGROUP_NAME_CONF)+1) &&
572                         *config_type == LIMITER_CONFIG) {
573                 if (!pci) {
574                         _E("process configuration information pointer should not be NULL");
575                         return RESOURCED_ERROR_FAIL;
576                 }
577
578                 if (!strncmp(result->value, CGROUP_VIP_VALUE_CONF,
579                         strlen(CGROUP_VIP_VALUE_CONF) +1)) {
580                         pci->cpu_type = CGROUP_VIP;
581                 }
582                 else if (!strncmp(result->value, CGROUP_HIGH_VALUE_CONF,
583                         strlen(CGROUP_HIGH_VALUE_CONF) +1)) {
584                         pci->cpu_type = CGROUP_HIGH;
585                 }
586                 else if (!strncmp(result->value, CGROUP_MEDIUM_VALUE_CONF,
587                         strlen(CGROUP_MEDIUM_VALUE_CONF) +1)) {
588                         pci->cpu_type = CGROUP_MEDIUM;
589                 }
590                 else if (!strncmp(result->value, CGROUP_LOW_VALUE_CONF,
591                         strlen(CGROUP_LOW_VALUE_CONF) +1)) {
592                         pci->cpu_type = CGROUP_LOW;
593                 }
594                 else {
595                         _E("invalid parameter (%s)", result->value);
596                         return RESOURCED_ERROR_INVALID_PARAMETER;
597                 }
598         }
599         else if (!strncmp(result->name, MEM_CGROUP_NAME_CONF, strlen(MEM_CGROUP_NAME_CONF)+1) &&
600                         *config_type == LIMITER_CONFIG) {
601                 if (!pci) {
602                         _E("process configuration information pointer should not be NULL");
603                         return RESOURCED_ERROR_FAIL;
604                 }
605
606                 if (!strncmp(result->value, CGROUP_VIP_VALUE_CONF,
607                         strlen(CGROUP_VIP_VALUE_CONF) +1)) {
608                         pci->mem_type = CGROUP_VIP;
609                 }
610                 else if (!strncmp(result->value, CGROUP_HIGH_VALUE_CONF,
611                         strlen(CGROUP_HIGH_VALUE_CONF) +1)) {
612                         pci->mem_type = CGROUP_HIGH;
613                 }
614                 else if (!strncmp(result->value, CGROUP_MEDIUM_VALUE_CONF,
615                         strlen(CGROUP_MEDIUM_VALUE_CONF) +1)) {
616                         pci->mem_type = CGROUP_MEDIUM;
617                 }
618                 else if (!strncmp(result->value, CGROUP_LOW_VALUE_CONF,
619                         strlen(CGROUP_LOW_VALUE_CONF) +1)) {
620                         pci->mem_type = CGROUP_LOW;
621                 }
622                 else {
623                         _E("invalid parameter (%s)", result->value);
624                         return RESOURCED_ERROR_INVALID_PARAMETER;
625                 }
626         }
627         else if (!strncmp(result->name, MEM_LIMIT_ACTION_NAME_CONF,
628                 strlen(MEM_LIMIT_ACTION_NAME_CONF)+1) && *config_type == LIMITER_CONFIG) {
629                 int error;
630
631                 if (!pci) {
632                         _E("process configuration information pointer should not be NULL");
633                         return RESOURCED_ERROR_FAIL;
634                 }
635                 
636                 error = set_mem_action_conf(&pci->mem_action, result->value);
637                 return error;   
638         }
639         else if (!strncmp(result->name, CPU_PRIORITY_NAME_CONF, strlen(CPU_PRIORITY_NAME_CONF)+1) &&
640                         *config_type == LIMITER_CONFIG) {
641                 if (!pci) {
642                         _E("process configuration information pointer should not be NULL");
643                         return RESOURCED_ERROR_FAIL;
644                 }
645                 pci->cpu_priority = atoi(result->value);
646         }
647         else if (!strncmp(result->name, ACTION_ON_FAILURE_NAME_CONF,
648                                 strlen(ACTION_ON_FAILURE_NAME_CONF)+1) && *config_type == PROCESS_CONFIG) {
649                 if (!pci) {
650                         _E("process configuration information pointer should not be NULL");
651                         return RESOURCED_ERROR_FAIL;
652                 }
653
654                 if (!strncmp(result->value, ACTION_REBOOT_VALUE_CONF,
655                                         strlen(ACTION_REBOOT_VALUE_CONF) +1)) {
656                         pci->fail_action = PROC_ACTION_REBOOT;
657                 }
658                 else {
659                         _E("invalid parameter (%s)", result->value);
660                         return RESOURCED_ERROR_INVALID_PARAMETER;
661                 }
662         }
663         else if (!strncmp(result->name, WATCHDOG_ACTION_NAME_CONF,
664                                 strlen(WATCHDOG_ACTION_NAME_CONF)+1) && *config_type == PROCESS_CONFIG) {
665                 if (!pci) {
666                         _E("process configuration information pointer should not be NULL");
667                         return RESOURCED_ERROR_FAIL;
668                 }
669
670                 if (!strncmp(result->value, ACTION_IGNORE_VALUE_CONF,
671                                         strlen(ACTION_IGNORE_VALUE_CONF) +1)) {
672                         pci->watchdog_action = PROC_ACTION_IGNORE;
673                 }
674                 else if (!strncmp(result->value, ACTION_KILL_VALUE_CONF,
675                                         strlen(ACTION_KILL_VALUE_CONF) +1)) {
676                         pci->watchdog_action = PROC_ACTION_KILL;
677                 }
678                 else {
679                         _E("invalid parameter (%s)", result->value);
680                         return RESOURCED_ERROR_INVALID_PARAMETER;
681                 }
682         }
683         else {
684                 _E("Unknown configuration name (%s) and value (%s) on section (%s)",
685                                 result->name, result->value, result->section);
686         }
687
688         return RESOURCED_ERROR_NONE;
689 }
690
691 static void load_per_vendor_configs(const char *dir, int func(struct parse_result *result,
692                                                                 void *user_data), void *user_data)
693 {
694         int count;
695         int idx;
696         struct dirent **namelist;
697
698         if ((count = scandir(dir, &namelist, NULL, alphasort)) == -1) {
699                 _W("failed to opendir (%s)", dir);
700                 return;
701         }
702
703         for (idx = 0; idx < count; idx++) {
704                 char path[PATH_MAX] = {0, };
705
706                 if (!strstr(namelist[idx]->d_name, CONF_FILE_SUFFIX))
707                         continue;
708
709                 snprintf(path, sizeof(path), "%s/%s", dir, namelist[idx]->d_name);
710                 config_parse(path, func, user_data);
711                 free(namelist[idx]);
712         }
713
714         free(namelist);
715 }
716
717 void resourced_parse_vendor_configs(void)
718 {
719         int config_type;
720
721         fixed_app_and_service_list_init();
722
723         /* Load configurations in limiter.conf and limiter.conf.d/ */
724         config_parse(LIMITER_CONF_FILE, limiter_config, NULL);
725         config_type = LIMITER_CONFIG;
726         load_per_vendor_configs(LIMITER_CONF_DIR, vendor_config, &config_type);
727
728         /* Load configurations in optimizer.conf and optimizer.conf.d */
729         config_parse(OPTIMIZER_CONF_FILE, optimizer_config, NULL);
730         config_type = OPTIMIZER_CONFIG;
731         load_per_vendor_configs(OPTIMIZER_CONF_DIR, vendor_config, &config_type);
732
733         /* Load configuration in process.conf */
734         config_type = PROCESS_CONFIG;
735         load_per_vendor_configs(PROC_CONF_DIR, vendor_config, &config_type);
736 }
737
738 void resourced_free_vendor_configs(void)
739 {
740         fixed_app_and_service_list_exit();
741 }
742
743 int config_parse(const char *file_name, int cb(struct parse_result *result,
744                         void *user_data), void *user_data)
745 {
746         FILE *f = NULL;
747         struct parse_result result;
748         /* use stack for parsing */
749         char line[LINE_MAX];
750         char section[MAX_SECTION];
751         char *start, *end, *name, *value;
752         int lineno = 0, ret = 0;
753
754         if (!file_name || !cb) {
755                 ret = -EINVAL;
756                 goto error;
757         }
758
759         /* open conf file */
760         f = fopen(file_name, "r");
761         if (!f) {
762                 _E("Failed to open file %s", file_name);
763                 ret = -EIO;
764                 goto error;
765         }
766
767         /* parsing line by line */
768         while (fgets(line, LINE_MAX, f) != NULL) {
769                 lineno++;
770
771                 start = line;
772                 truncate_nl(start);
773                 start = strstrip(start);
774
775                 if (*start == COMMENT) {
776                         continue;
777                 } else if (*start == '[') {
778                         /* parse section */
779                         end = strchr(start, ']');
780                         if (!end || *end != ']') {
781                                 ret = -EBADMSG;
782                                 goto error;
783                         }
784
785                         *end = '\0';
786                         strncpy(section, start + 1, sizeof(section)-1);
787                         section[MAX_SECTION-1] = '\0';
788                 } else if (*start) {
789                         /* parse name & value */
790                         end = strchr(start, '=');
791                         if (!end || *end != '=') {
792                                 ret = -EBADMSG;
793                                 goto error;
794                         }
795                         *end = '\0';
796                         name = strstrip(start);
797                         value = strstrip(end + 1);
798                         end = strchr(value, COMMENT);
799                         if (end && *end == COMMENT) {
800                                 *end = '\0';
801                                 value = strstrip(value);
802                         }
803
804                         result.section = section;
805                         result.name = name;
806                         result.value = value;
807                         /* callback with parse result */
808                         ret = cb(&result, user_data);
809                         if (ret < 0) {
810                                 ret = -EBADMSG;
811                                 goto error;
812                         }
813                 }
814         }
815         return 0;
816
817 error:
818         if (f)
819                 fclose(f);
820         _E("Failed to read %s:%d!", file_name, lineno);
821         return ret;
822 }