Rearrange files and directories 04/279704/1 accepted/tizen/unified/20220824.135639 submit/tizen/20220822.111221
authorUnsung Lee <unsung.lee@samsung.com>
Tue, 16 Aug 2022 11:18:12 +0000 (20:18 +0900)
committerUnsung Lee <unsung.lee@samsung.com>
Tue, 16 Aug 2022 11:19:12 +0000 (20:19 +0900)
Change-Id: I2fd8069de754a50f9c2f3094ac87dcd014d4b44a
Signed-off-by: Unsung Lee <unsung.lee@samsung.com>
81 files changed:
CMakeLists.txt
conf/process.conf
src/CMakeLists.txt
src/common/appid-helper.c [deleted file]
src/common/appid-helper.h [deleted file]
src/common/compact-common.c [deleted file]
src/common/compact-common.h [deleted file]
src/common/conf/compact-common.c [new file with mode: 0644]
src/common/conf/compact-common.h [new file with mode: 0644]
src/common/conf/config-parser.c [new file with mode: 0644]
src/common/conf/config-parser.h [new file with mode: 0644]
src/common/conf/config.h.in [new file with mode: 0644]
src/common/conf/cpu-common.c [new file with mode: 0644]
src/common/conf/cpu-common.h [new file with mode: 0644]
src/common/conf/dedup-common.c [new file with mode: 0644]
src/common/conf/dedup-common.h [new file with mode: 0644]
src/common/conf/swap-common.c [new file with mode: 0644]
src/common/conf/swap-common.h [new file with mode: 0644]
src/common/config-parser.c [deleted file]
src/common/config-parser.h [deleted file]
src/common/config.h.in [deleted file]
src/common/cpu-common.c [deleted file]
src/common/cpu-common.h [deleted file]
src/common/dbus-handler.c [deleted file]
src/common/dbus-handler.h [deleted file]
src/common/dbus-names-external.h [deleted file]
src/common/dbus-names-local.h [deleted file]
src/common/dedup-common.c [deleted file]
src/common/dedup-common.h [deleted file]
src/common/ipc/dbus-handler.c [new file with mode: 0644]
src/common/ipc/dbus-handler.h [new file with mode: 0644]
src/common/ipc/dbus-names-external.h [new file with mode: 0644]
src/common/ipc/dbus-names-local.h [new file with mode: 0644]
src/common/ipc/safe-kill.c [new file with mode: 0644]
src/common/ipc/safe-kill.h [new file with mode: 0644]
src/common/meminfo-lookup.c [deleted file]
src/common/meminfo-lookup.gperf [deleted file]
src/common/module-data.c [deleted file]
src/common/module-data.h [deleted file]
src/common/module.c [deleted file]
src/common/module.h [deleted file]
src/common/module/module-data.c [new file with mode: 0644]
src/common/module/module-data.h [new file with mode: 0644]
src/common/module/module.c [new file with mode: 0644]
src/common/module/module.h [new file with mode: 0644]
src/common/procfs.c [deleted file]
src/common/procfs.h [deleted file]
src/common/procfs/meminfo-lookup.c [new file with mode: 0644]
src/common/procfs/meminfo-lookup.gperf [new file with mode: 0644]
src/common/procfs/procfs.c [new file with mode: 0644]
src/common/procfs/procfs.h [new file with mode: 0644]
src/common/procfs/smaps-lookup.c [new file with mode: 0644]
src/common/procfs/smaps-lookup.gperf [new file with mode: 0644]
src/common/procfs/smaps.c [new file with mode: 0644]
src/common/procfs/smaps.h [new file with mode: 0644]
src/common/safe-kill.c [deleted file]
src/common/safe-kill.h [deleted file]
src/common/smaps-lookup.c [deleted file]
src/common/smaps-lookup.gperf [deleted file]
src/common/smaps.c [deleted file]
src/common/smaps.h [deleted file]
src/common/swap-common.c [deleted file]
src/common/swap-common.h [deleted file]
src/process/priority/proc-priority.c [deleted file]
src/process/proc-priority.c [new file with mode: 0644]
src/resource-limiter/cpu-throttling.c [new file with mode: 0644]
src/resource-limiter/cpu/cpu-throttling.c [deleted file]
src/resource-monitor/abnormal/heart-abnormal.c [deleted file]
src/resource-monitor/battery/heart-battery.c [deleted file]
src/resource-monitor/cpu/heart-cpu.c [deleted file]
src/resource-monitor/heart-abnormal.c [new file with mode: 0644]
src/resource-monitor/heart-battery.c [new file with mode: 0644]
src/resource-monitor/heart-cpu.c [new file with mode: 0644]
src/resource-monitor/heart-memory.c [new file with mode: 0644]
src/resource-monitor/heart-storage.c [new file with mode: 0644]
src/resource-monitor/memory/heart-memory.c [deleted file]
src/resource-monitor/storage/heart-storage.c [deleted file]
src/resource-optimizer/memory/compaction.c [new file with mode: 0644]
src/resource-optimizer/memory/compaction/compaction.c [deleted file]
src/resource-optimizer/memory/dedup.c [new file with mode: 0644]
src/resource-optimizer/memory/dedup/dedup.c [deleted file]

index 974cc66a49c3161c0437c2fe19324c4d6a9b67ae..7eb6d8dc5be31fb2638edf40a757f42d5ff2b060 100644 (file)
@@ -40,10 +40,15 @@ SET(VERSION ${FULLVER})
 SET(DATA_DIR                                        ${CMAKE_SOURCE_DIR}/data)
 SET(CMAKELISTS_DIR                                  ${CMAKE_SOURCE_DIR}/CMakeLists)
 SET(INCLUDE_COMMON_DIR                              ${CMAKE_SOURCE_DIR}/src/common)
+SET(INCLUDE_PROCFS_DIR                              ${CMAKE_SOURCE_DIR}/src/common/procfs)
+SET(INCLUDE_MODULE_DIR                              ${CMAKE_SOURCE_DIR}/src/common/module)
+SET(INCLUDE_CONF_DIR                                ${CMAKE_SOURCE_DIR}/src/common/conf)
+SET(INCLUDE_IPC_DIR                                 ${CMAKE_SOURCE_DIR}/src/common/ipc)
 SET(INCLUDE_CGROUP_DIR                              ${CMAKE_SOURCE_DIR}/src/common/cgroup)
 SET(INCLUDE_PUBLIC_DIR                              ${CMAKE_SOURCE_DIR}/include)
 SET(CONF_DIR                                                                           ${CMAKE_SOURCE_DIR}/conf)
-SET(RESOURCED_INCLUDEDIR                            ${INCLUDE_COMMON_DIR} ${INCLUDE_CGROUP_DIR} ${INCLUDE_PUBLIC_DIR})
+SET(RESOURCED_INCLUDEDIR                            
+                       ${INCLUDE_COMMON_DIR} ${INCLUDE_CGROUP_DIR} ${INCLUDE_CONF_DIR} ${INCLUDE_IPC_DIR} ${INCLUDE_MODULE_DIR} ${INCLUDE_PROCFS_DIR} ${INCLUDE_PUBLIC_DIR})
 
 #misc
 SET(SOURCE_DIR                                      ${CMAKE_SOURCE_DIR}/src)
@@ -53,35 +58,39 @@ SET(COMMON_SOURCE_DIR                               ${SOURCE_DIR}/common)
 #cgroup
 SET(CGROUP_SOURCE_DIR                               ${COMMON_SOURCE_DIR}/cgroup)
 
+#conf
+SET(CONF_SOURCE_DIR                                 ${COMMON_SOURCE_DIR}/conf)
+
+#ipc (dbus, signal)
+SET(IPC_SOURCE_DIR                                  ${COMMON_SOURCE_DIR}/ipc)
+
+#module
+SET(MODULE_SOURCE_DIR                               ${COMMON_SOURCE_DIR}/module)
+
+#procfs
+SET(PROCFS_SOURCE_DIR                                                          ${COMMON_SOURCE_DIR}/procfs)
+
 #resource-optimizer source folders
 SET(RESOURCE_OPTIMIZER_SOURCE_DIR                   ${SOURCE_DIR}/resource-optimizer)
 SET(CPU_RESOURCE_OPTIMIZER_SOURCE_DIR               ${RESOURCE_OPTIMIZER_SOURCE_DIR}/cpu)
 SET(MEMORY_RESOURCE_OPTIMIZER_SOURCE_DIR            ${RESOURCE_OPTIMIZER_SOURCE_DIR}/memory)
-SET(DEDUP_SOURCE_DIR                                ${RESOURCE_OPTIMIZER_SOURCE_DIR}/memory/dedup)
+SET(DEDUP_SOURCE_DIR                                ${MEMORY_RESOURCE_OPTIMIZER_SOURCE_DIR})
 SET(SWAP_SOURCE_DIR                                 ${RESOURCE_OPTIMIZER_SOURCE_DIR}/memory/swap)
-SET(COMPACTION_SOURCE_DIR                           ${RESOURCE_OPTIMIZER_SOURCE_DIR}/memory/compaction)
+SET(COMPACTION_SOURCE_DIR                           ${MEMORY_RESOURCE_OPTIMIZER_SOURCE_DIR})
 
 #resource-limiter source folders
 SET(RESOURCE_LIMITER_SOURCE_DIR                     ${SOURCE_DIR}/resource-limiter)
 SET(FREEZER_SOURCE_DIR                              ${RESOURCE_LIMITER_SOURCE_DIR}/freezer)
 SET(MEMORY_LIMITER_SOURCE_DIR                       ${RESOURCE_LIMITER_SOURCE_DIR}/memory)
-SET(CPU_LIMITER_SOURCE_DIR                          ${RESOURCE_LIMITER_SOURCE_DIR}/cpu)
+SET(CPU_LIMITER_SOURCE_DIR                          ${RESOURCE_LIMITER_SOURCE_DIR})
 
 #resource-monitor source folders
 SET(RESOURCE_MONITOR_SOURCE_DIR                     ${SOURCE_DIR}/resource-monitor)
-SET(CPU_MONITOR_SOURCE_DIR                          ${RESOURCE_MONITOR_SOURCE_DIR}/cpu)
-SET(MEMORY_MONITOR_SOURCE_DIR                       ${RESOURCE_MONITOR_SOURCE_DIR}/memory)
-SET(STORAGE_MONITOR_SOURCE_DIR                      ${RESOURCE_MONITOR_SOURCE_DIR}/storage)
-SET(DBUS_MONITOR_SOURCE_DIR                         ${RESOURCE_MONITOR_SOURCE_DIR})
-SET(BATTERY_MONITOR_SOURCE_DIR                      ${RESOURCE_MONITOR_SOURCE_DIR}/battery)
-SET(ABNORMAL_MONITOR_SOURCE_DIR                     ${RESOURCE_MONITOR_SOURCE_DIR}/abnormal)
 
 #process
 SET(PROCESS_SOURCE_DIR                              ${SOURCE_DIR}/process)
 SET(BLOCK_SOURCE_DIR                                ${PROCESS_SOURCE_DIR}/block)
 SET(WATCHDOG_SOURCE_DIR                             ${PROCESS_SOURCE_DIR}/watchdog)
-SET(PRIORITY_SOURCE_DIR                             ${PROCESS_SOURCE_DIR}/priority)
-
 
 INSTALL(FILES ${CONF_DIR}/org.tizen.resourced.conf DESTINATION /etc/dbus-1/system.d)
 
index a901e22033e504804576fed75608c5b59c04a45e..faec5973cad39e1ecf6ade90007a49b2fb402594 100644 (file)
@@ -1,13 +1,6 @@
 [APPUSAGE]
 APPUSAGE=ON
 
-[WatchdogExcludedApps]
-PREDEFINE=indicator-win
-PREDEFINE=lockscreen
-PREDEFINE=quickpanel
-PREDEFINE=volume
-PREDEFINE=data-provider-master
-
 [BLOCK]
 activate=TRUE
 mode=WRITE
index 00c302308e3d4814b495247e421ba14095bc15d4..6ac553821f640e060ccf160570f5d522ebce46eb 100644 (file)
@@ -35,26 +35,33 @@ SET(RESOURCED_SHARED_SOURCES ${RESOURCED_SHARED_SOURCES} ${FILES})
 FILE(GLOB FILES "${WATCHDOG_SOURCE_DIR}/*.c")
 SET(RESOURCED_SHARED_SOURCES ${RESOURCED_SHARED_SOURCES} ${FILES})
 
-FILE(GLOB FILES "${PRIORITY_SOURCE_DIR}/*.c")
-SET(RESOURCED_SHARED_SOURCES ${RESOURCED_SHARED_SOURCES} ${FILES})
-
 FILE(GLOB FILES "${COMMON_SOURCE_DIR}/*.c")
 SET(RESOURCED_SHARED_SOURCES ${RESOURCED_SHARED_SOURCES} ${FILES})
 
 FILE(GLOB FILES "${CGROUP_SOURCE_DIR}/*.c")
 SET(RESOURCED_SHARED_SOURCES ${RESOURCED_SHARED_SOURCES} ${FILES})
 
+FILE(GLOB FILES "${CONF_SOURCE_DIR}/*.c")
+SET(RESOURCED_SHARED_SOURCES ${RESOURCED_SHARED_SOURCES} ${FILES})
+
+FILE(GLOB FILES "${IPC_SOURCE_DIR}/*.c")
+SET(RESOURCED_SHARED_SOURCES ${RESOURCED_SHARED_SOURCES} ${FILES})
+
+FILE(GLOB FILES "${MODULE_SOURCE_DIR}/*.c")
+SET(RESOURCED_SHARED_SOURCES ${RESOURCED_SHARED_SOURCES} ${FILES})
+
+FILE(GLOB FILES "${PROCFS_SOURCE_DIR}/*.c")
+SET(RESOURCED_SHARED_SOURCES ${RESOURCED_SHARED_SOURCES} ${FILES})
+
 SET(CMAKE_EXTRA_INCLUDE_FILES unistd.h)
 
 INCLUDE_DIRECTORIES(${RESOURCED_INCLUDEDIR}
   ${RESOURCED_SOURCE_DIR}
   ${RESOURCE_MONITOR_SOURCE_DIR}
-  ${CPU_LIMITER_SOURCE_DIR}
   ${MEMORY_LIMITER_SOURCE_DIR}
   ${PROCESS_SOURCE_DIR}
   ${BLOCK_SOURCE_DIR}
   ${FREEZER_SOURCE_DIR}
-  ${PRIORITY_SOURCE_DIR}
 )
 
 IF("${PROC_WATCHDOG}" STREQUAL "ON")
@@ -72,7 +79,7 @@ IF("${MEMORY_MODULE}" STREQUAL "ON")
 ENDIF()
 
 IF("${CPU_THROTTLING_MODULE}" STREQUAL "ON")
-  FILE(GLOB FILES "${CPU_LIMITER_SOURCE_DIR}/*.c")
+  FILE(GLOB FILES "${CPU_LIMITER_SOURCE_DIR}/cpu-throttling.c")
   FOREACH(FILE ${FILES})
       SET(SOURCES ${SOURCES} ${FILE})
   ENDFOREACH()
@@ -114,11 +121,11 @@ ENDFOREACH(flag)
 
 SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -pthread -fPIE -fPIC")
 
-CONFIGURE_FILE(${INCLUDE_COMMON_DIR}/config.h.in
-  ${INCLUDE_COMMON_DIR}/config.h)
+CONFIGURE_FILE(${INCLUDE_CONF_DIR}/config.h.in
+  ${INCLUDE_CONF_DIR}/config.h)
 
 # resourced internal private API
-FILE(GLOB FILES "${INCLUDE_COMMON_DIR}/*.h" "${INCLUDE_CGROUP_DIR}/*.h" "${INCLUDE_PUBLIC_DIR}/*.h" "${PROCESS_SOURCE_DIR}/*.h" "${RESOURCED_SOURCE_DIR}/*.h")
+FILE(GLOB FILES "${INCLUDE_COMMON_DIR}/*.h" "${INCLUDE_CGROUP_DIR}/*.h" "${INCLUDE_CONF_DIR}/*.h" "${INCLUDE_PUBLIC_DIR}/*.h" "${PROCESS_SOURCE_DIR}/*.h" "${RESOURCED_SOURCE_DIR}/*.h")
 FOREACH(FILE ${FILES})
   SET(RESOURCED_HEADERS ${RESOURCED_HEADERS} ${FILE})
 ENDFOREACH()
@@ -172,12 +179,12 @@ INSTALL(FILES ${CONF_DIR}/optimizer-profile-tv.conf DESTINATION ${RD_CONFIG_PATH
 
 ADD_LIBRARY(heart MODULE
        ${RESOURCE_MONITOR_SOURCE_DIR}/heart.c
-       ${ABNORMAL_MONITOR_SOURCE_DIR}/heart-abnormal.c
-       ${BATTERY_MONITOR_SOURCE_DIR}/heart-battery.c
-       ${CPU_MONITOR_SOURCE_DIR}/heart-cpu.c
-       ${DBUS_MONITOR_SOURCE_DIR}/heart-dbus.c
-       ${MEMORY_MONITOR_SOURCE_DIR}/heart-memory.c
-       ${STORAGE_MONITOR_SOURCE_DIR}/heart-storage.c
+       ${RESOURCE_MONITOR_SOURCE_DIR}/heart-abnormal.c
+       ${RESOURCE_MONITOR_SOURCE_DIR}/heart-battery.c
+       ${RESOURCE_MONITOR_SOURCE_DIR}/heart-cpu.c
+       ${RESOURCE_MONITOR_SOURCE_DIR}/heart-dbus.c
+       ${RESOURCE_MONITOR_SOURCE_DIR}/heart-memory.c
+       ${RESOURCE_MONITOR_SOURCE_DIR}/heart-storage.c
        ${RESOURCE_MONITOR_SOURCE_DIR}/logging.c)
 TARGET_LINK_LIBRARIES(heart resourced-private-api ${RESOURCED_REQUIRE_PKGS_LDFLAGS})
 INSTALL(TARGETS heart DESTINATION ${MAKE_INSTALL_PREFIX}${RD_PLUGIN_PATH})
diff --git a/src/common/appid-helper.c b/src/common/appid-helper.c
deleted file mode 100644 (file)
index b1eb539..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * resourced
- *
- * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
-*/
diff --git a/src/common/appid-helper.h b/src/common/appid-helper.h
deleted file mode 100644 (file)
index b1eb539..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * resourced
- *
- * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
-*/
diff --git a/src/common/compact-common.c b/src/common/compact-common.c
deleted file mode 100644 (file)
index 4faed44..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-
-#include "compact-common.h"
-#include "trace.h"
-
-static struct compact_conf *compact_conf = NULL;
-
-struct compact_conf *get_compact_conf(void)
-{
-       if (!compact_conf) {
-               compact_conf = (struct compact_conf *)calloc(1, sizeof (struct compact_conf));
-               if (!compact_conf) {
-                       _E("Failed to alloc memory for cpu configuration");
-                       return NULL;
-               }
-               else {
-                       compact_conf->enable = false;
-                       compact_conf->frag_level = 0;
-               }
-       }
-
-       return compact_conf;
-}
-
-void free_compact_conf(void)
-{
-       if (compact_conf)
-               free(compact_conf);
-}
-
diff --git a/src/common/compact-common.h b/src/common/compact-common.h
deleted file mode 100644 (file)
index 01f044e..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef __COMPACT_COMMON_H__
-#define __COMPACT_COMMON_H__
-
-#include "resourced.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-struct compact_conf {
-       bool enable;
-       int frag_level;
-};
-
-struct compact_conf *get_compact_conf(void);
-void free_compact_conf(void);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __COMPACT_COMMON_H__ */
diff --git a/src/common/conf/compact-common.c b/src/common/conf/compact-common.c
new file mode 100644 (file)
index 0000000..4faed44
--- /dev/null
@@ -0,0 +1,29 @@
+
+#include "compact-common.h"
+#include "trace.h"
+
+static struct compact_conf *compact_conf = NULL;
+
+struct compact_conf *get_compact_conf(void)
+{
+       if (!compact_conf) {
+               compact_conf = (struct compact_conf *)calloc(1, sizeof (struct compact_conf));
+               if (!compact_conf) {
+                       _E("Failed to alloc memory for cpu configuration");
+                       return NULL;
+               }
+               else {
+                       compact_conf->enable = false;
+                       compact_conf->frag_level = 0;
+               }
+       }
+
+       return compact_conf;
+}
+
+void free_compact_conf(void)
+{
+       if (compact_conf)
+               free(compact_conf);
+}
+
diff --git a/src/common/conf/compact-common.h b/src/common/conf/compact-common.h
new file mode 100644 (file)
index 0000000..01f044e
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef __COMPACT_COMMON_H__
+#define __COMPACT_COMMON_H__
+
+#include "resourced.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+struct compact_conf {
+       bool enable;
+       int frag_level;
+};
+
+struct compact_conf *get_compact_conf(void);
+void free_compact_conf(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __COMPACT_COMMON_H__ */
diff --git a/src/common/conf/config-parser.c b/src/common/conf/config-parser.c
new file mode 100644 (file)
index 0000000..7e4ffc3
--- /dev/null
@@ -0,0 +1,1022 @@
+/*
+ * resourced
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <limits.h>
+#include <ctype.h>
+
+#include "util.h"
+#include "trace.h"
+#include "config-parser.h"
+#include "proc-common.h"
+#include "cpu-cgroup.h"
+#include "swap-common.h"
+#include "dedup-common.h"
+#include "compact-common.h"
+#include "cpu-common.h"
+
+#define MAX_SECTION            64
+
+static int config_parse_swap_types(
+                                 const char *rvalue,
+                                 void *data)
+{
+       enum swap_type *type = data;
+       char *word, *state;
+       size_t l;
+
+       if (is_empty(rvalue))
+               return 0;
+
+       *type = 0;
+
+       FOREACH_WORD_SEPARATOR(word, l, rvalue, "+|", state) {
+               if (strneq(word, "zram", l))
+                       *type |= SWAP_TYPE_ZRAM;
+               else if (strneq(word, "file", l))
+                       *type |= SWAP_TYPE_FILE;
+               else if (strneq(word, "zswap", l))
+                       *type |= SWAP_TYPE_ZSWAP;
+               else
+                       return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int config_parse_cpu_sched_features(const char *value)
+{
+       int cpu_sched_flag = CPU_SCHED_UNINITIALIZED;
+       char *word, *state;
+       size_t l;
+
+       if (is_empty(value))
+               return cpu_sched_flag;
+
+       FOREACH_WORD_SEPARATOR(word, l, value, ",", state) {
+               if (strneq(word, RT_RUNTIME_SHARE_VALUE_CONF, l))
+                       cpu_sched_flag |= CPU_SCHED_RUNTIME_SHARE;
+               else if (strneq(word, NO_RT_RUNTIME_SHARE_VALUE_CONF, l))
+                       cpu_sched_flag |= CPU_SCHED_NO_RUNTIME_SHARE;
+/*             else if (strneq(word, RT_RUNTIME_GREED_VALUE_CONF, l))
+                       cpu_sched_flag |= CPU_SCHED_RUNTIME_GREED;*/
+               else
+                       return CPU_SCHED_UNINITIALIZED;
+       }
+
+       return cpu_sched_flag;
+}
+
+static char config_parse_time_unit(const char *value)
+{
+       char chr;
+       char *ptr = strchr(value, 's');
+       if (ptr == NULL) {
+               _E("[CONFIG] Cannot find 's' in the string (%s)", value);
+               return 'X';
+       }
+
+       if (value > (ptr - 1)) {
+               _E("[CONFIG] Size of string should be larger than 1");
+               return 'X';
+       }
+
+       chr = *(ptr - 1);
+       if (isdigit(chr)) {
+               *ptr = '\0';
+               return ' ';
+       }
+       else {
+               *(ptr - 1) = '\0';
+               return chr;
+       }
+}
+
+static long long config_parse_ll_time_us(const char *value)
+{
+       char unit = config_parse_time_unit(value);
+
+       if (unit == ' ') {
+               return strtoll(value, NULL, 10) * 1000 * 1000;
+       }
+       else if (unit == 'm') {
+               return strtoll(value, NULL, 10) * 1000;
+       }
+       else if (unit == 'u') {
+               return strtoll(value, NULL, 10);
+       }
+       else {
+               _E("[CONFIG] Unknown unit of time");
+               return 0;
+       }
+}
+
+static unsigned long long config_parse_ull_time_us(const char *value)
+{
+       char unit = config_parse_time_unit(value);
+
+       if (unit == ' ') {
+               return strtoull(value, NULL, 10) * 1000 * 1000;
+       }
+       else if (unit == 'm') {
+               return strtoull(value, NULL, 10) * 1000;
+       }
+       else if (unit == 'u') {
+               return strtoull(value, NULL, 10);
+       }
+       else {
+               _E("[CONFIG] Unknown unit of time");
+               return 0;
+       }
+}
+
+static bool config_parse_bool(const char *value)
+{
+       if (!strncmp(value, "yes", 4) ||
+                       !strncmp(value, "1", 2) ||
+                       !strncmp(value, "ok", 3) ||
+                       !strncmp(value, "on", 3))
+               return true;
+       else if (!strncmp(value, "no", 3) ||
+                       !strncmp(value, "0", 2) ||
+                       !strncmp(value, "off", 4))
+               return false;
+       else {
+               _E("Unknown name (%s)", value);
+               return false;
+       }
+}
+
+static int config_parse_sched_type(const char *value)
+{
+       if (!strncmp(value, CPU_SCHED_IDLE_VALUE_CONF,
+                               strlen(CPU_SCHED_IDLE_VALUE_CONF) +1))
+               return CPU_SCHED_IDLE;
+       else if (!strncmp(value, CPU_SCHED_OTHER_VALUE_CONF,
+                               strlen(CPU_SCHED_OTHER_VALUE_CONF) +1))
+               return CPU_SCHED_OTHER;
+       else if (!strncmp(value, CPU_SCHED_BATCH_VALUE_CONF,
+                               strlen(CPU_SCHED_BATCH_VALUE_CONF) +1))
+               return CPU_SCHED_BATCH;
+       else if (!strncmp(value, CPU_SCHED_FIFO_VALUE_CONF,
+                               strlen(CPU_SCHED_FIFO_VALUE_CONF) +1))
+               return CPU_SCHED_FIFO;
+       else if (!strncmp(value, CPU_SCHED_RR_VALUE_CONF,
+                               strlen(CPU_SCHED_RR_VALUE_CONF) +1))
+               return CPU_SCHED_RR;
+       else if (!strncmp(value, CPU_SCHED_DEADLINE_VALUE_CONF,
+                               strlen(CPU_SCHED_DEADLINE_VALUE_CONF) +1))
+               return CPU_SCHED_DEADLINE;
+       else {
+               _E("invalid parameter (%s)", value);
+               return CPU_SCHED_NONE;
+       }
+}
+
+static cpu_boosting_level_e config_parse_boosting_level(const char *value)
+{
+       if (!strncmp(value, CPU_BOOSTING_LEVEL_STRONG_VALUE_CONF,
+                               strlen(CPU_BOOSTING_LEVEL_STRONG_VALUE_CONF) + 1))
+               return CPU_BOOSTING_LEVEL_STRONG;
+       else if (!strncmp(value, CPU_BOOSTING_LEVEL_MEDIUM_VALUE_CONF,
+                               strlen(CPU_BOOSTING_LEVEL_MEDIUM_VALUE_CONF) + 1))
+               return CPU_BOOSTING_LEVEL_MEDIUM;
+       else if (!strncmp(value, CPU_BOOSTING_LEVEL_WEAK_VALUE_CONF,
+                               strlen(CPU_BOOSTING_LEVEL_WEAK_VALUE_CONF) + 1))
+               return CPU_BOOSTING_LEVEL_WEAK;
+       else
+               return CPU_BOOSTING_LEVEL_NONE;
+}
+
+static int optimizer_config(struct parse_result *result, void *user_data)
+{
+       if (!result)
+               return RESOURCED_ERROR_INVALID_PARAMETER;
+
+       struct swap_conf *swap_conf = get_swap_conf();
+       if (swap_conf == NULL) {
+               _E("[CONFIG] memory swap configuration is NULL");
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       struct dedup_conf *dedup_conf = get_dedup_conf();
+       if (dedup_conf == NULL) {
+               _E("[CONFIG] memory dedup configuration is NULL");
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       struct compact_conf *compact_conf = get_compact_conf();
+       if (compact_conf == NULL) {
+               _E("[CONFIG] memory compact configuration is NULL");
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       struct cpu_sched_conf *cpu_sched_conf = get_cpu_sched_conf();
+       if (cpu_sched_conf == NULL) {
+               _E("[CONFIG] cpu_sched configuration is NULL");
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       if (!strncmp(result->section, SWAP_SECTION, strlen(SWAP_SECTION)+1)) {
+               if (!swap_conf->enable)
+                       swap_conf->enable = true;
+/*             if (!strncmp(result->name, SWAP_ENABLE_NAME_CONF, strlen(SWAP_ENABLE_NAME_CONF)+1)) {
+                               swap_conf->enable = config_parse_bool(result->value);
+               }*/
+               if (!strncmp(result->name, RECLAIM_AT_BOOT_NAME_CONF,
+                                       strlen(RECLAIM_AT_BOOT_NAME_CONF)+1)) {
+                               swap_conf->boot_reclaim_enable = config_parse_bool(result->value);
+               }
+               else if (!strncmp(result->name, SWAP_TYPE_NAME_CONF,
+                                       strlen(SWAP_TYPE_NAME_CONF)+1)) {
+                       if (config_parse_swap_types(result->value, &swap_conf->swap_type) < 0) {
+                               _E("[CONFIG] Failed to parse type of swap, so use zram type");
+                               swap_conf->swap_type = SWAP_TYPE_ZRAM;
+                       }
+               }
+               else if (!strncmp(result->name, THROTTLING_SWAPPINESS_NAME_CONF,
+                                       strlen(THROTTLING_SWAPPINESS_NAME_CONF)+1)) {
+                       swap_conf->swappiness[MEMCG_THROTTLING] = atoi(result->value);
+               }
+               else {
+                       _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
+                                       result->name, result->value, result->section);
+               }
+       }
+       else if (!strncmp(result->section, ZRAM_SECTION, strlen(ZRAM_SECTION)+1)) {
+               if (!strncmp(result->name, COMP_ALGORITHM_NAME_CONF, strlen(COMP_ALGORITHM_NAME_CONF)+1)) {
+                       if (strlen(result->value) + 1 > sizeof(swap_conf->zram.algorithm)) {
+                               _E("Size of swap_conf->zram.algorithm is not enough");
+                               return RESOURCED_ERROR_OUT_OF_MEMORY;
+                       }
+                       strncpy(swap_conf->zram.algorithm, result->value,
+                                       sizeof(swap_conf->zram.algorithm) - 1);
+               }
+               else if (!strncmp(result->name, ZRAM_RATIO_NAME_CONF, strlen(ZRAM_RATIO_NAME_CONF)+1)) {
+                       swap_conf->zram.ratio = atof(result->value);
+               }
+               else {
+                       _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
+                                       result->name, result->value, result->section);
+               }
+       }
+       else if (!strncmp(result->section, ZSWAP_SECTION, strlen(ZSWAP_SECTION)+1)) {
+               if (!strncmp(result->name, POOL_RATIO_NAME_CONF, strlen(POOL_RATIO_NAME_CONF)+1)) {
+                       swap_conf->zswap.pool_ratio = atof(result->value);
+               }
+               else if (!strncmp(result->name, POOL_TYPE_NAME_CONF, strlen(POOL_TYPE_NAME_CONF)+1)) {
+                       if (strlen(result->value) + 1 > sizeof(swap_conf->zswap.pool_type)) {
+                               _E("Size of swap_conf->zswap.pool_type is not enough");
+                               return RESOURCED_ERROR_OUT_OF_MEMORY;
+                       }
+                       strncpy(swap_conf->zswap.pool_type, result->value,
+                                       sizeof(swap_conf->zswap.pool_type) - 1);
+               }
+               else {
+                       _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
+                                       result->name, result->value, result->section);
+               }
+       }
+       else if (!strncmp(result->section, DEDUP_SECTION, strlen(DEDUP_SECTION)+1)) {
+               if (!dedup_conf->enable)
+                       dedup_conf->enable = true;
+/*             if (!strncmp(result->name, DEDUP_ENABLE_NAME_CONF, strlen(DEDUP_ENABLE_NAME_CONF)+1)) {
+                               dedup_conf->enable = config_parse_bool(result->value);
+               }*/
+               if (!strncmp(result->name, DEDUP_AT_BOOT_NAME_CONF, strlen(DEDUP_AT_BOOT_NAME_CONF)+1)) {
+                       dedup_conf->boot_dedup_enable = config_parse_bool(result->value);
+               }
+               else if (!strncmp(result->name, SCAN_ON_LOWMEM_NAME_CONF, strlen(SCAN_ON_LOWMEM_NAME_CONF)+1)) {
+                       dedup_conf->scan_on_lowmem = config_parse_bool(result->value);
+               }
+               else {
+                       _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
+                                       result->name, result->value, result->section);
+               }
+       }
+       else if (!strncmp(result->section, KSM_SECTION, strlen(KSM_SECTION)+1)) {
+               if (!strncmp(result->name, KSM_MODE_NAME_CONF, strlen(KSM_MODE_NAME_CONF)+1)) {
+                       if (strlen(result->value) + 1 > sizeof(dedup_conf->ksm.mode)) {
+                               _E("Size of swap_conf->type is not enough");
+                               return RESOURCED_ERROR_OUT_OF_MEMORY;
+                       }
+                       strncpy(dedup_conf->ksm.mode, result->value,
+                                       sizeof(dedup_conf->ksm.mode) - 1);
+               }
+               else if (!strncmp(result->name, PAGES_TO_SCAN_NAME_CONF, strlen(PAGES_TO_SCAN_NAME_CONF)+1)) {
+                       dedup_conf->ksm.pages = atoi(result->value);
+               }
+               else if (!strncmp(result->name, PAGES_TO_SCAN_WITH_BOOST_NAME_CONF,
+                                       strlen(PAGES_TO_SCAN_WITH_BOOST_NAME_CONF)+1)) {
+                       dedup_conf->ksm.boost_pages = atoi(result->value);
+               }
+               else {
+                       _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
+                                       result->name, result->value, result->section);
+               }
+       }
+       else if (!strncmp(result->section, COMPACTION_SECTION, strlen(COMPACTION_SECTION)+1)) {
+               if (!compact_conf->enable)
+                       compact_conf->enable = true;
+/*             if (!strncmp(result->name, COMPACTION_ENABLE_NAME_CONF,
+                                       strlen(COMPACTION_ENABLE_NAME_CONF)+1)) {
+                       compact_conf->enable = config_parse_bool(result->value);
+               }*/
+               if (!strncmp(result->name, FRAG_LEVEL_NAME_CONF, strlen(FRAG_LEVEL_NAME_CONF)+1)) {
+                       compact_conf->frag_level = atoi(result->value);
+               }
+               else {
+                       _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
+                                       result->name, result->value, result->section);
+               }
+       }
+       else if (!strncmp(result->section, CPU_SCHED_SECTION,
+                               strlen(CPU_SCHED_SECTION)+1)) {
+               if (!strncmp(result->name, CPU_SCHED_FEATURE_NAME_CONF,
+                                       strlen(CPU_SCHED_FEATURE_NAME_CONF) + 1)) {
+                       cpu_sched_conf->cpu_sched_flag = config_parse_cpu_sched_features(result->value);
+               }
+               else if (!strncmp(result->name, CPU_RT_RUN_TIME_NAME_CONF,
+                                       strlen(CPU_RT_RUN_TIME_NAME_CONF) + 1)) {
+                       cpu_sched_conf->cpu_cgroup_info.rt_runtime_us = config_parse_ll_time_us(result->value);
+               }
+               else if (!strncmp(result->name, CPU_RT_PERIOD_NAME_CONF,
+                                       strlen(CPU_RT_PERIOD_NAME_CONF) + 1)) {
+                       cpu_sched_conf->cpu_cgroup_info.rt_period_us = config_parse_ull_time_us(result->value);
+               }
+               else {
+                       _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
+                                       result->name, result->value, result->section);
+               }
+       }
+       else if (!strncmp(result->section, CPU_AFFINITY_SECTION,
+                               strlen(CPU_AFFINITY_SECTION)+1)) {
+               int error = RESOURCED_ERROR_NONE;
+
+               if (!strncmp(result->name, FOREGROUND_APPS_NAME_CONF,
+                                       strlen(FOREGROUND_APPS_NAME_CONF) + 1)) {
+                       error = set_cpu_affinity_conf(result->name, result->value);
+               }
+               else {
+                       _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
+                                       result->name, result->value, result->section);
+               }
+
+               return error;
+       }
+       else if (!strncmp(result->section, CPU_BOOSTING_LEVEL_STRONG_SECTION,
+                               strlen(CPU_BOOSTING_LEVEL_STRONG_SECTION)+1)) {
+               struct cpu_boosting_conf *cpu_boosting_conf =
+                       get_cpu_boosting_conf(CPU_BOOSTING_LEVEL_STRONG);
+               if (cpu_boosting_conf == NULL) {
+                       _E("[CONFIG] cpu_boosting configuration is NULL");
+                       return RESOURCED_ERROR_FAIL;
+               }
+
+               if (!cpu_boosting_conf->enable)
+                       cpu_boosting_conf->enable = true;
+
+               if (!strncmp(result->name, CPU_SCHED_NAME_CONF,
+                                       strlen(CPU_SCHED_NAME_CONF) + 1)) {
+                       cpu_boosting_conf->cpu_sched_info.cpu_sched_type =
+                               config_parse_sched_type(result->value);
+               }
+               else if (!strncmp(result->name, CPU_NICE_NAME_CONF,
+                                       strlen(CPU_NICE_NAME_CONF) + 1)) {
+                       cpu_boosting_conf->cpu_sched_info.cpu_nice =
+                               atoi(result->value);
+               }
+               else if (!strncmp(result->name, CPU_RT_PRIORITY_NAME_CONF,
+                                       strlen(CPU_RT_PRIORITY_NAME_CONF) + 1)) {
+                       cpu_boosting_conf->cpu_sched_info.cpu_rt_priority =
+                               atoi(result->value);
+               }
+               else {
+                       _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
+                                       result->name, result->value, result->section);
+               }
+       }
+       else if (!strncmp(result->section, CPU_BOOSTING_LEVEL_MEDIUM_SECTION,
+                               strlen(CPU_BOOSTING_LEVEL_MEDIUM_SECTION)+1)) {
+               struct cpu_boosting_conf *cpu_boosting_conf =
+                       get_cpu_boosting_conf(CPU_BOOSTING_LEVEL_MEDIUM);
+               if (cpu_boosting_conf == NULL) {
+                       _E("[CONFIG] cpu_boosting configuration is NULL");
+                       return RESOURCED_ERROR_FAIL;
+               }
+
+               if (!cpu_boosting_conf->enable)
+                       cpu_boosting_conf->enable = true;
+
+               if (!strncmp(result->name, CPU_SCHED_NAME_CONF,
+                                       strlen(CPU_SCHED_NAME_CONF) + 1)) {
+                       cpu_boosting_conf->cpu_sched_info.cpu_sched_type =
+                               config_parse_sched_type(result->value);
+               }
+               else if (!strncmp(result->name, CPU_NICE_NAME_CONF,
+                                       strlen(CPU_NICE_NAME_CONF) + 1)) {
+                       cpu_boosting_conf->cpu_sched_info.cpu_nice =
+                               atoi(result->value);
+               }
+               else if (!strncmp(result->name, CPU_RT_PRIORITY_NAME_CONF,
+                                       strlen(CPU_RT_PRIORITY_NAME_CONF) + 1)) {
+                       cpu_boosting_conf->cpu_sched_info.cpu_rt_priority =
+                               atoi(result->value);
+               }
+               else {
+                       _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
+                                       result->name, result->value, result->section);
+               }
+       }
+       else if (!strncmp(result->section, CPU_BOOSTING_LEVEL_WEAK_SECTION,
+                               strlen(CPU_BOOSTING_LEVEL_WEAK_SECTION)+1)) {
+               struct cpu_boosting_conf *cpu_boosting_conf =
+                       get_cpu_boosting_conf(CPU_BOOSTING_LEVEL_WEAK);
+               if (cpu_boosting_conf == NULL) {
+                       _E("[CONFIG] cpu_boosting configuration is NULL");
+                       return RESOURCED_ERROR_FAIL;
+               }
+
+               if (!cpu_boosting_conf->enable)
+                       cpu_boosting_conf->enable = true;
+
+               if (!strncmp(result->name, CPU_SCHED_NAME_CONF,
+                                       strlen(CPU_SCHED_NAME_CONF) + 1)) {
+                       cpu_boosting_conf->cpu_sched_info.cpu_sched_type =
+                               config_parse_sched_type(result->value);
+               }
+               else if (!strncmp(result->name, CPU_NICE_NAME_CONF,
+                                       strlen(CPU_NICE_NAME_CONF) + 1)) {
+                       cpu_boosting_conf->cpu_sched_info.cpu_nice =
+                               atoi(result->value);
+               }
+               else if (!strncmp(result->name, CPU_RT_PRIORITY_NAME_CONF,
+                                       strlen(CPU_RT_PRIORITY_NAME_CONF) + 1)) {
+                       cpu_boosting_conf->cpu_sched_info.cpu_rt_priority =
+                               atoi(result->value);
+               }
+               else {
+                       _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
+                                       result->name, result->value, result->section);
+               }
+       }
+       else {
+               _E("[CONFIG] Unknown section name (%s) and value (%s) on section (%s)",
+                               result->name, result->value, result->section);
+       }
+
+       return RESOURCED_ERROR_NONE;
+}
+
+
+static int limiter_config(struct parse_result *result, void *user_data)
+{
+       if (!result)
+               return RESOURCED_ERROR_INVALID_PARAMETER;
+
+       struct memcg_conf *memcg_conf = get_memcg_conf();
+       if (memcg_conf == NULL) {
+               _E("[CONFIG] memory cgroup configuration is NULL");
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       struct cpu_throttling_conf *cpu_throttling_conf = get_cpu_throttling_conf();
+       if (cpu_throttling_conf == NULL) {
+               _E("[CONFIG] cpu_throttling configuration is NULL");
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       if (!strncmp(result->section, MEMORY_THROTTLING_SECTION,
+                               strlen(MEMORY_THROTTLING_SECTION)+1)) {
+               char *ptr = strchr(result->value, '%');
+               if (ptr == NULL) {
+                       _E("[CONFIG] Cannot find '%%' in the string (%s)", result->value);
+                       return RESOURCED_ERROR_FAIL;
+               }
+               else
+                       *ptr = '\0';
+
+               if (!strncmp(result->name, THROTTLING_LIMIT_NAME_CONF,
+                                       strlen(THROTTLING_LIMIT_NAME_CONF) + 1)) {
+                       memcg_conf->cgroup_limit[MEMCG_THROTTLING] = atof(result->value);
+               }
+               else {
+                       _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
+                                       result->name, result->value, result->section);
+               }
+       }
+       else if (!strncmp(result->section, MEMORY_LEVEL_THRESHOLD_SECTION,
+                               strlen(MEMORY_LEVEL_THRESHOLD_SECTION)+1)) {
+
+               if (!strncmp(result->name, OOM_POPUP_NAME_CONF,
+                                       strlen(OOM_POPUP_NAME_CONF) + 1)) {
+                       memcg_conf->oom_popup = config_parse_bool(result->value);
+               }
+               else {
+                       char temp = '\0';
+                       int error = RESOURCED_ERROR_NONE;
+                       bool percent;
+                       char *ptr = strchr(result->value, '%');
+                       if (ptr == NULL) {
+                               ptr = strchr(result->value, 'B');
+                               if (ptr == NULL) {
+                                       _E("[CONFIG] Cannot find 'B' in the string (%s)", result->value);
+                                       return RESOURCED_ERROR_FAIL;
+                               }
+
+                               if (result->value > (ptr - 1)) {
+                                       _E("[CONFIG] Size of string should be larger than 1");
+                                       return RESOURCED_ERROR_FAIL;
+                               }
+
+                               temp = *(ptr - 1);
+                               *(ptr - 1) = '\0';
+                               percent = false;
+                       }
+                       else {
+                               *ptr = '\0';
+                               percent = true;
+                       }
+
+                       if (!strncmp(result->name, MEDIUM_LEVEL_NAME_CONF,
+                                               strlen(MEDIUM_LEVEL_NAME_CONF) + 1)) {
+                               error = set_memcg_conf_threshold(percent, temp, MEM_LEVEL_MEDIUM, result->value);
+                       }
+                       else if (!strncmp(result->name, LOW_LEVEL_NAME_CONF,
+                                               strlen(LOW_LEVEL_NAME_CONF) + 1)) {
+                               error = set_memcg_conf_threshold(percent, temp, MEM_LEVEL_LOW, result->value);
+                       }
+                       else if (!strncmp(result->name, CRITICAL_LEVEL_NAME_CONF,
+                                               strlen(CRITICAL_LEVEL_NAME_CONF) + 1)) {
+                               error = set_memcg_conf_threshold(percent, temp, MEM_LEVEL_CRITICAL, result->value);
+                       }
+                       else if (!strncmp(result->name, OOM_LEVEL_NAME_CONF,
+                                               strlen(OOM_LEVEL_NAME_CONF) + 1)) {
+                               error = set_memcg_conf_threshold(percent, temp, MEM_LEVEL_OOM, result->value);
+                       }
+                       else {
+                               _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
+                                               result->name, result->value, result->section);
+                       }
+
+                       return error;
+               }
+       }
+       else if (!strncmp(result->section, MEMORY_APP_TYPE_LIMIT_SECTION,
+                               strlen(MEMORY_APP_TYPE_LIMIT_SECTION)+1)) {
+               int error = RESOURCED_ERROR_NONE;
+
+               if (!strncmp(result->name, SERVICE_PER_APP_LIMIT_ACTION_NAME_CONF,
+                                       strlen(SERVICE_PER_APP_LIMIT_ACTION_NAME_CONF) + 1)) {
+                       error = set_mem_action_conf(&memcg_conf->service, result->value);
+               }
+               else if (!strncmp(result->name, WIDGET_PER_APP_LIMIT_ACTION_NAME_CONF,
+                                       strlen(WIDGET_PER_APP_LIMIT_ACTION_NAME_CONF) + 1)) {
+                       error = set_mem_action_conf(&memcg_conf->widget, result->value);
+               }
+               else if (!strncmp(result->name, GUI_PER_APP_LIMIT_ACTION_NAME_CONF,
+                                       strlen(GUI_PER_APP_LIMIT_ACTION_NAME_CONF) + 1)) {
+                       error = set_mem_action_conf(&memcg_conf->guiapp, result->value);
+               }
+               else {
+                       _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
+                                       result->name, result->value, result->section);
+               }
+
+               return error;
+       }
+       else if (!strncmp(result->section, MEMORY_APP_STATUS_LIMIT_SECTION,
+                               strlen(MEMORY_APP_STATUS_LIMIT_SECTION)+1)) {
+               int error = RESOURCED_ERROR_NONE;
+
+               if (!strncmp(result->name, BACKGROUND_PER_APP_LIMIT_ACTION_NAME_CONF,
+                                       strlen(BACKGROUND_PER_APP_LIMIT_ACTION_NAME_CONF) + 1)) {
+                       error = set_mem_action_conf(&memcg_conf->background, result->value);
+               }
+               else {
+                       _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
+                                       result->name, result->value, result->section);
+               }
+
+               return error;
+       }
+       else if (!strncmp(result->section, CPU_THROTTLING_SECTION,
+                               strlen(CPU_THROTTLING_SECTION)+1)) {
+               if (!cpu_throttling_conf->enable)
+                       cpu_throttling_conf->enable = true;
+
+               if (!strncmp(result->name, CPU_SCHED_NAME_CONF,
+                                       strlen(CPU_SCHED_NAME_CONF)+1)) {
+                       cpu_throttling_conf->cpu_sched_info.cpu_sched_type =
+                               config_parse_sched_type(result->value);
+               }
+               else if (!strncmp(result->name, CPU_NICE_NAME_CONF,
+                                       strlen(CPU_NICE_NAME_CONF)+1)) {
+                       cpu_throttling_conf->cpu_sched_info.cpu_nice =
+                               atoi(result->value);
+               }
+               else if (!strncmp(result->name, CPU_SHARE_NAME_CONF,
+                                       strlen(CPU_SHARE_NAME_CONF)+1)) {
+                       cpu_throttling_conf->cpu_cgroup_info.cpu_share =
+                               strtoull(result->value, NULL, 10);
+               }
+               else if (!strncmp(result->name, CPU_CFS_RUN_TIME_NAME_CONF,
+                                       strlen(CPU_CFS_RUN_TIME_NAME_CONF)+1)) {
+                       cpu_throttling_conf->cpu_cgroup_info.cfs_runtime_us =
+                               config_parse_ll_time_us(result->value);
+               }
+               else if (!strncmp(result->name, CPU_CFS_PERIOD_NAME_CONF,
+                                       strlen(CPU_CFS_PERIOD_NAME_CONF)+1)) {
+                       cpu_throttling_conf->cpu_cgroup_info.cfs_period_us =
+                               config_parse_ull_time_us(result->value);
+               }
+               else {
+                       _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
+                                       result->name, result->value, result->section);
+               }
+       }
+       else {
+               _E("[CONFIG] Unknown section name (%s) and value (%s) on section (%s)",
+                               result->name, result->value, result->section);
+       }
+
+       return RESOURCED_ERROR_NONE;
+}
+
+static int vendor_config(struct parse_result *result, void *user_data)
+{
+       int *config_type = (int *)user_data;
+       static struct proc_conf_info *pci = NULL;
+
+       if (!result || !user_data)
+               return RESOURCED_ERROR_INVALID_PARAMETER;
+
+       if (strncmp(result->section, PRIVATE_SECTION, strlen(PRIVATE_SECTION)+1)) {
+               if (strncmp(result->section, OLD_VIP_GROUP_SECTION, strlen(OLD_VIP_GROUP_SECTION)+1)) {
+                       return RESOURCED_ERROR_NONE;
+               }
+       }
+
+       /* common(App or Service or Process) */
+       if (!strncmp(result->name, APP_NAME_CONF, strlen(APP_NAME_CONF)+1)                 ||
+               !strncmp(result->name, SERVICE_NAME_CONF, strlen(SERVICE_NAME_CONF)+1)         ||
+           !strncmp(result->name, OLD_SERVICE_NAME_CONF, strlen(OLD_SERVICE_NAME_CONF)+1) ||
+               !strncmp(result->name, PROCESS_NAME_CONF, strlen(PROCESS_NAME_CONF)+1)         ||
+               !strncmp(result->name, OLD_PROCESS_NAME_CONF, strlen(OLD_PROCESS_NAME_CONF)+1)) {
+               pci = fixed_app_and_service_exist_check(result->value,
+                               result->name[0] == 'A' ? APP_TYPE :
+                               result->name[0] == 'S' ? SERVICE_TYPE : PROCESS_TYPE);
+               if (pci == NULL) {
+                       pci = (struct proc_conf_info *)calloc(1, sizeof(struct proc_conf_info));
+                       if (pci == NULL) {
+                               _E("Failed to allocate memory during parsing vendor configurations");
+                               return RESOURCED_ERROR_OUT_OF_MEMORY;
+                       }
+                       pci->cpu_sched_info.cpu_sched_type = CPU_SCHED_NONE;
+                       pci->cpu_sched_info.cpu_rt_priority = CPU_INIT_PRIO;
+                       pci->cpu_sched_info.cpu_nice = CPU_INIT_NICE;
+                       pci->watchdog_action = PROC_ACTION_KILL;
+                       pci->fail_action = PROC_ACTION_IGNORE;
+                       pci->cpu_boosting_level = CPU_BOOSTING_LEVEL_NONE;
+                       strncpy(pci->name, result->value, sizeof(pci->name)-1);
+
+                       if (result->name[0] == 'A')
+                               fixed_app_list_insert(pci);
+                       else if (result->name[0] == 'S')
+                               fixed_service_list_insert(pci);
+                       else
+                               fixed_process_list_insert(pci);
+               }
+       }
+       /* limiter.conf.d */
+/*     else if (!strncmp(result->name, MEM_CGROUP_NAME_CONF, strlen(MEM_CGROUP_NAME_CONF)+1) &&
+                       *config_type == LIMITER_CONFIG) {
+               if (!pci) {
+                       _E("process configuration information pointer should not be NULL");
+                       return RESOURCED_ERROR_FAIL;
+               }
+
+               if (!strncmp(result->value, CGROUP_HIGH_VALUE_CONF,
+                       strlen(CGROUP_HIGH_VALUE_CONF) +1)) {
+                       pci->mem_type = MEMCG_HIGH;
+               }
+               else if (!strncmp(result->value, CGROUP_MEDIUM_VALUE_CONF,
+                       strlen(CGROUP_MEDIUM_VALUE_CONF) +1)) {
+                       pci->mem_type = MEMCG_MEDIUM;
+               }
+               else if (!strncmp(result->value, CGROUP_LOW_VALUE_CONF,
+                       strlen(CGROUP_LOW_VALUE_CONF) +1)) {
+                       pci->mem_type = MEMCG_LOW;
+               }
+               else {
+                       _E("invalid parameter (%s)", result->value);
+                       return RESOURCED_ERROR_INVALID_PARAMETER;
+               }
+       }*/
+       else if (!strncmp(result->name, MEM_LIMIT_ACTION_NAME_CONF,
+               strlen(MEM_LIMIT_ACTION_NAME_CONF)+1) && *config_type == LIMITER_CONFIG) {
+               int error;
+
+               if (!pci) {
+                       _E("process configuration information pointer should not be NULL");
+                       return RESOURCED_ERROR_FAIL;
+               }
+
+               error = set_mem_action_conf(&pci->mem_action, result->value);
+               return error;
+       }
+       else if (!strncmp(result->name, MEMORY_THROTTLING_NAME_CONF,
+               strlen(MEMORY_THROTTLING_NAME_CONF)+1) && *config_type == LIMITER_CONFIG) {
+
+               if (!pci) {
+                       _E("process configuration information pointer should not be NULL");
+                       return RESOURCED_ERROR_FAIL;
+               }
+
+               /* Enable throttling of a service */
+               pci->memory_throttling_enable = config_parse_bool(result->value);
+       }
+       else if (!strncmp(result->name, CPU_THROTTLING_NAME_CONF,
+               strlen(CPU_THROTTLING_NAME_CONF)+1) && *config_type == LIMITER_CONFIG) {
+
+               if (!pci) {
+                       _E("process configuration information pointer should not be NULL");
+                       return RESOURCED_ERROR_FAIL;
+               }
+
+               /* Enable throttling of an app (or a service) */
+               pci->cpu_throttling_enable = config_parse_bool(result->value);
+       }
+       /* optimizer.conf.d */
+       else if (!strncmp(result->name, CPU_SCHED_NAME_CONF, strlen(CPU_SCHED_NAME_CONF)+1) &&
+                       *config_type == OPTIMIZER_CONFIG) {
+               if (!pci) {
+                       _E("process configuration information pointer should not be NULL");
+                       return RESOURCED_ERROR_FAIL;
+               }
+
+               pci->cpu_sched_info.cpu_sched_type = config_parse_sched_type(result->value);
+
+       }
+       else if (!strncmp(result->name, CPU_NICE_NAME_CONF,
+                               strlen(CPU_NICE_NAME_CONF)+1) && *config_type == OPTIMIZER_CONFIG) {
+               if (!pci) {
+                       _E("process configuration information pointer should not be NULL");
+                       return RESOURCED_ERROR_FAIL;
+               }
+
+               pci->cpu_sched_info.cpu_nice = atoi(result->value);
+       }
+       else if (!strncmp(result->name, CPU_RT_PRIORITY_NAME_CONF,
+                               strlen(CPU_RT_PRIORITY_NAME_CONF)+1) && *config_type == OPTIMIZER_CONFIG) {
+               if (!pci) {
+                       _E("process configuration information pointer should not be NULL");
+                       return RESOURCED_ERROR_FAIL;
+               }
+
+               pci->cpu_sched_info.cpu_rt_priority = atoi(result->value);
+       }
+       else if (!strncmp(result->name, CPU_BOOSTING_LEVEL_NAME_CONF,
+                               strlen(CPU_BOOSTING_LEVEL_NAME_CONF)+1) && *config_type == OPTIMIZER_CONFIG) {
+               if (!pci) {
+                       _E("process configuration information pointer should not be NULL");
+                       return RESOURCED_ERROR_FAIL;
+               }
+
+               pci->cpu_boosting_level = config_parse_boosting_level(result->value);
+       }
+/*     else if (!strncmp(result->name, CPU_RT_RUN_TIME_NAME_CONF,
+                               strlen(CPU_RT_RUN_TIME_NAME_CONF)+1) &&
+                       *config_type == OPTIMIZER_CONFIG) {
+               if (!pci) {
+                       _E("process configuration information pointer should not be NULL");
+                       return RESOURCED_ERROR_FAIL;
+               }
+               pci->cpu_sched_info.rt_runtime_us = config_parse_time_us(result->value);
+       }
+       else if (!strncmp(result->name, CPU_RT_PERIOD_NAME_CONF,
+                               strlen(CPU_RT_PERIOD_NAME_CONF)+1) &&
+                       *config_type == OPTIMIZER_CONFIG) {
+               if (!pci) {
+                       _E("process configuration information pointer should not be NULL");
+                       return RESOURCED_ERROR_FAIL;
+               }
+               pci->cpu_sched_info.rt_period_us = config_parse_time_us(result->value);
+       }*/
+       else if (!strncmp(result->name, ACTION_ON_FAILURE_NAME_CONF,
+                               strlen(ACTION_ON_FAILURE_NAME_CONF)+1) && *config_type == PROCESS_CONFIG) {
+               if (!pci) {
+                       _E("process configuration information pointer should not be NULL");
+                       return RESOURCED_ERROR_FAIL;
+               }
+
+               if (!strncmp(result->value, ACTION_REBOOT_VALUE_CONF,
+                                       strlen(ACTION_REBOOT_VALUE_CONF) +1)) {
+                       pci->fail_action = PROC_ACTION_REBOOT;
+               }
+               else {
+                       _E("invalid parameter (%s)", result->value);
+                       return RESOURCED_ERROR_INVALID_PARAMETER;
+               }
+       }
+       else if (!strncmp(result->name, WATCHDOG_ACTION_NAME_CONF,
+                               strlen(WATCHDOG_ACTION_NAME_CONF)+1) && *config_type == PROCESS_CONFIG) {
+               if (!pci) {
+                       _E("process configuration information pointer should not be NULL");
+                       return RESOURCED_ERROR_FAIL;
+               }
+
+               if (!strncmp(result->value, ACTION_IGNORE_VALUE_CONF,
+                                       strlen(ACTION_IGNORE_VALUE_CONF) +1)) {
+                       pci->watchdog_action = PROC_ACTION_IGNORE;
+               }
+               else if (!strncmp(result->value, ACTION_KILL_VALUE_CONF,
+                                       strlen(ACTION_KILL_VALUE_CONF) +1)) {
+                       pci->watchdog_action = PROC_ACTION_KILL;
+               }
+               else {
+                       _E("invalid parameter (%s)", result->value);
+                       return RESOURCED_ERROR_INVALID_PARAMETER;
+               }
+       }
+       /* old style */
+       else if (!strncmp(result->name, OLD_ACTION_ON_FAILURE_NAME_CONF,
+                               strlen(OLD_ACTION_ON_FAILURE_NAME_CONF)+1) && *config_type == VIP_CONFIG) {
+               if (!pci) {
+                       _E("process configuration information pointer should not be NULL");
+                       return RESOURCED_ERROR_FAIL;
+               }
+
+               if (!strncmp(result->value, ACTION_REBOOT_VALUE_CONF,
+                                       strlen(ACTION_REBOOT_VALUE_CONF) +1)) {
+                       pci->fail_action = PROC_ACTION_REBOOT;
+               }
+               else {
+                       _E("invalid parameter (%s)", result->value);
+                       return RESOURCED_ERROR_INVALID_PARAMETER;
+               }
+       }
+       else {
+               _E("Unknown configuration name (%s) and value (%s) on section (%s)",
+                               result->name, result->value, result->section);
+       }
+
+       return RESOURCED_ERROR_NONE;
+}
+
+static void load_per_vendor_configs(const char *dir, int func(struct parse_result *result,
+                                                               void *user_data), void *user_data)
+{
+       int count;
+       int idx;
+       struct dirent **namelist;
+
+       if ((count = scandir(dir, &namelist, NULL, alphasort)) == -1) {
+               _I("(%s) conf dir does not exist", dir);
+               return;
+       }
+
+       for (idx = 0; idx < count; idx++) {
+               char path[PATH_MAX] = {0, };
+
+               if (!strstr(namelist[idx]->d_name, CONF_FILE_SUFFIX))
+                       continue;
+
+               snprintf(path, sizeof(path), "%s/%s", dir, namelist[idx]->d_name);
+               config_parse(path, func, user_data);
+               free(namelist[idx]);
+       }
+
+       free(namelist);
+}
+
+void resourced_parse_vendor_configs(void)
+{
+       int config_type;
+
+       fixed_app_and_service_list_init();
+
+       /* Load configurations in limiter.conf and limiter.conf.d/ */
+       config_parse(LIMITER_CONF_FILE, limiter_config, NULL);
+       config_type = LIMITER_CONFIG;
+       load_per_vendor_configs(LIMITER_CONF_DIR, vendor_config, &config_type);
+
+       /* Load configurations in optimizer.conf and optimizer.conf.d */
+       config_parse(OPTIMIZER_CONF_FILE, optimizer_config, NULL);
+       config_type = OPTIMIZER_CONFIG;
+       load_per_vendor_configs(OPTIMIZER_CONF_DIR, vendor_config, &config_type);
+
+       /* Load configuration in process.conf */
+       config_type = PROCESS_CONFIG;
+       load_per_vendor_configs(PROC_CONF_DIR, vendor_config, &config_type);
+
+       /* old style */
+       config_type = VIP_CONFIG;
+       load_per_vendor_configs(VIP_CONF_DIR, vendor_config, &config_type);
+}
+
+void resourced_free_vendor_configs(void)
+{
+       fixed_app_and_service_list_exit();
+}
+
+int config_parse(const char *file_name, int cb(struct parse_result *result,
+                       void *user_data), void *user_data)
+{
+       FILE *f = NULL;
+       struct parse_result result;
+       /* use stack for parsing */
+       char line[LINE_MAX];
+       char section[MAX_SECTION];
+       char *start, *end, *name, *value;
+       int lineno = 0, ret = 0;
+
+       if (!file_name || !cb) {
+               ret = -EINVAL;
+               goto error;
+       }
+
+       /* open conf file */
+       f = fopen(file_name, "r");
+       if (!f) {
+               _E("Failed to open file %s", file_name);
+               ret = -EIO;
+               goto error;
+       }
+
+       /* parsing line by line */
+       while (fgets(line, LINE_MAX, f) != NULL) {
+               lineno++;
+
+               start = line;
+               truncate_nl(start);
+               start = strstrip(start);
+
+               if (*start == COMMENT) {
+                       continue;
+               } else if (*start == '[') {
+                       /* parse section */
+                       end = strchr(start, ']');
+                       if (!end || *end != ']') {
+                               ret = -EBADMSG;
+                               goto error;
+                       }
+
+                       *end = '\0';
+                       strncpy(section, start + 1, sizeof(section)-1);
+                       section[MAX_SECTION-1] = '\0';
+               } else if (*start) {
+                       /* parse name & value */
+                       end = strchr(start, '=');
+                       if (!end || *end != '=') {
+                               ret = -EBADMSG;
+                               goto error;
+                       }
+                       *end = '\0';
+                       name = strstrip(start);
+                       value = strstrip(end + 1);
+                       end = strchr(value, COMMENT);
+                       if (end && *end == COMMENT) {
+                               *end = '\0';
+                               value = strstrip(value);
+                       }
+
+                       result.section = section;
+                       result.name = name;
+                       result.value = value;
+                       /* callback with parse result */
+                       ret = cb(&result, user_data);
+                       if (ret < 0) {
+                               ret = -EBADMSG;
+                               goto error;
+                       }
+               }
+       }
+       _D("Success to load %s", file_name);
+       fclose(f);
+       return 0;
+
+error:
+       if (f)
+               fclose(f);
+       _E("Failed to read %s:%d!", file_name, lineno);
+       return ret;
+}
diff --git a/src/common/conf/config-parser.h b/src/common/conf/config-parser.h
new file mode 100644 (file)
index 0000000..66787d7
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * resourced
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef __CONFIG_PARSER_H__
+#define __CONFIG_PARSER_H__
+
+#include <stdio.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define CONF_FILE_SUFFIX                    ".conf"
+
+#define LIMITER_CONF_FILE                   RD_CONFIG_FILE(limiter)
+#define OPTIMIZER_CONF_FILE                 RD_CONFIG_FILE(optimizer)
+#define LIMITER_CONF_DIR                    RD_CONFIG_PATH"/limiter.conf.d"
+#define OPTIMIZER_CONF_DIR                  RD_CONFIG_PATH"/optimizer.conf.d"
+#define PROC_CONF_DIR                       RD_CONFIG_PATH"/process.conf.d"
+/* old style */
+#define VIP_CONF_DIR                        RD_CONFIG_PATH"/vip-process.d"
+
+/* section name */
+/* limiter.conf */
+#define        PRIVATE_SECTION                     "Private"
+#define MEMORY_LEVEL_THRESHOLD_SECTION      "MemoryLevelThreshold"
+#define MEMORY_APP_TYPE_LIMIT_SECTION       "MemoryAppTypeLimit"
+#define MEMORY_APP_STATUS_LIMIT_SECTION     "MemoryAppStatusLimit"
+#define MEMORY_THROTTLING_SECTION           "MemoryThrottling"
+#define CPU_THROTTLING_SECTION              "CpuThrottling"
+#define OLD_VIP_GROUP_SECTION               "VIP_GROUP"
+
+/* optimizer.conf */
+#define SWAP_SECTION                        "MemorySwap"
+#define ZRAM_SECTION                        "MemoryZram"
+#define ZSWAP_SECTION                       "MemoryZswap"
+#define DEDUP_SECTION                       "MemoryDedup"
+#define KSM_SECTION                         "MemoryKsm"
+#define COMPACTION_SECTION                  "MemoryCompaction"
+#define CPU_SCHED_SECTION                   "CpuSched"
+#define CPU_AFFINITY_SECTION                "CpuAffinity"
+#define CPU_BOOSTING_LEVEL_STRONG_SECTION   "CpuBoostingLevelStrong"
+#define CPU_BOOSTING_LEVEL_MEDIUM_SECTION   "CpuBoostingLevelMedium"
+#define CPU_BOOSTING_LEVEL_WEAK_SECTION     "CpuBoostingLevelWeak"
+
+/* configuration name */
+/* limiter.conf */
+#define APP_NAME_CONF                                "App"
+#define SERVICE_NAME_CONF                            "Service"
+#define OLD_SERVICE_NAME_CONF                        "SERVICE"  /* old style */
+#define PROCESS_NAME_CONF                            "Process"
+#define OLD_PROCESS_NAME_CONF                        "PROCESS" /* old style */
+#define MEM_CGROUP_NAME_CONF                         "MemGroup"
+#define MEM_LIMIT_ACTION_NAME_CONF                   "MemLimitAction"
+#define ACTION_ON_FAILURE_NAME_CONF                  "ActionOnFailure"
+#define OLD_ACTION_ON_FAILURE_NAME_CONF              "ACTION_ON_FAILURE"
+#define        WATCHDOG_ACTION_NAME_CONF                    "WatchdogAction"
+#define THROTTLING_LIMIT_NAME_CONF                   "ThrottlingLimit"
+#define MEDIUM_LEVEL_NAME_CONF                       "MediumLevel"
+#define LOW_LEVEL_NAME_CONF                          "LowLevel"
+#define CRITICAL_LEVEL_NAME_CONF                     "CriticalLevel"
+#define OOM_LEVEL_NAME_CONF                          "OomLevel"
+#define OOM_POPUP_NAME_CONF                          "OomPopup"
+#define SERVICE_PER_APP_LIMIT_ACTION_NAME_CONF       "ServicePerAppLimitAction"
+#define WIDGET_PER_APP_LIMIT_ACTION_NAME_CONF        "WidgetPerAppLimitAction"
+#define GUI_PER_APP_LIMIT_ACTION_NAME_CONF           "GUIPerAppLimitAction"
+#define BACKGROUND_PER_APP_LIMIT_ACTION_NAME_CONF    "BackgroundPerAppLimitAction"
+
+/* CPU specific configuration name */
+#define CPU_SCHED_NAME_CONF                          "CpuSched"
+#define CPU_NICE_NAME_CONF                           "CpuNice"
+#define CPU_SHARE_NAME_CONF                          "CpuShare"
+#define CPU_RT_PRIORITY_NAME_CONF                    "CpuRTPriority"
+#define CPU_SCHED_FEATURE_NAME_CONF                  "CpuSchedFeature"
+#define CPU_RT_RUN_TIME_NAME_CONF                    "CpuRTRuntime"
+#define CPU_RT_PERIOD_NAME_CONF                      "CpuRTPeriod"
+#define CPU_CFS_RUN_TIME_NAME_CONF                   "CpuCFSRuntime"
+#define CPU_CFS_PERIOD_NAME_CONF                     "CpuCFSPeriod"
+#define CPU_BOOSTING_LEVEL_NAME_CONF                 "CpuBoostingLevel"
+#define MEMORY_THROTTLING_NAME_CONF                  "MemoryThrottling"
+#define CPU_THROTTLING_NAME_CONF                     "CpuThrottling"
+
+/* optimizer.conf */
+#define        SWAP_ENABLE_NAME_CONF                        "SwapEnable"
+#define RECLAIM_AT_BOOT_NAME_CONF                    "ReclaimAtBoot"
+#define SWAP_TYPE_NAME_CONF                          "SwapType"
+#define THROTTLING_SWAPPINESS_NAME_CONF              "ThrottlingSwappiness"
+#define COMP_ALGORITHM_NAME_CONF                     "CompAlgorithm"
+#define ZRAM_RATIO_NAME_CONF                         "ZramRatio"
+#define POOL_RATIO_NAME_CONF                         "PoolRatio"
+#define POOL_TYPE_NAME_CONF                          "PoolType"
+#define        DEDUP_ENABLE_NAME_CONF                       "DedupEnable"
+#define DEDUP_AT_BOOT_NAME_CONF                      "DedupAtBoot"
+#define        SCAN_ON_LOWMEM_NAME_CONF                     "ScanOnLowmem"
+#define KSM_MODE_NAME_CONF                           "KsmMode"
+#define        PAGES_TO_SCAN_NAME_CONF                      "PagesToScan"
+#define PAGES_TO_SCAN_WITH_BOOST_NAME_CONF           "PagesToScanWithBoost"
+#define        COMPACTION_ENABLE_NAME_CONF                  "CompactionEnable"
+#define FRAG_LEVEL_NAME_CONF                         "FragLevel"
+#define FOREGROUND_APPS_NAME_CONF                    "ForegroundApps"
+
+/* configuration value */
+#define CGROUP_LOW_VALUE_CONF                        "lowest"
+#define ACTION_BROADCAST_VALUE_CONF                  "broadcast"
+#define ACTION_RECLAIM_VALUE_CONF                    "reclaim"
+#define ACTION_KILL_VALUE_CONF                       "kill"
+#define ACTION_REBOOT_VALUE_CONF                     "reboot"
+#define ACTION_IGNORE_VALUE_CONF                     "ignore"
+
+/* CPU specific configuration name */
+#define RT_RUNTIME_SHARE_VALUE_CONF                  "rt_runtime_share"
+#define NO_RT_RUNTIME_SHARE_VALUE_CONF               "no_rt_runtime_share"
+#define CPU_SCHED_DEADLINE_VALUE_CONF                "deadline"
+#define CPU_SCHED_FIFO_VALUE_CONF                    "fifo"
+#define CPU_SCHED_RR_VALUE_CONF                      "rr"
+#define CPU_SCHED_OTHER_VALUE_CONF                   "other"
+#define CPU_SCHED_IDLE_VALUE_CONF                    "idle"
+#define CPU_SCHED_BATCH_VALUE_CONF                   "batch"
+#define CPU_BOOSTING_LEVEL_STRONG_VALUE_CONF         "strong"
+#define CPU_BOOSTING_LEVEL_MEDIUM_VALUE_CONF         "medium"
+#define CPU_BOOSTING_LEVEL_WEAK_VALUE_CONF           "weak"
+
+#define MATCH(a, b)    (!strncmp(a, b, strlen(a) + 1) ? 1 : 0)
+#define SET_CONF(a, b) (a = (b > 0.0 ? b : a))
+
+enum config_type {
+       LIMITER_CONFIG,
+       OPTIMIZER_CONFIG,
+       MONITOR_CONFIG,
+       PROCESS_CONFIG,
+       VIP_CONFIG, /* old style */
+};
+
+struct parse_result {
+       char *section;
+       char *name;
+       char *value;
+};
+
+/**
+ * @brief Parse config file and call callback\n
+ * @param[in] file_name conf file.
+ * @param[in] cb cb is called when conf file is parsed line by line.
+ * @param[in] user_data user data is passed to cb.
+ * @return 0 on success, negative if failed
+ */
+int config_parse(const char *file_name, int cb(struct parse_result *result,
+                       void *user_data), void *user_data);
+
+/* Prototype for a parser for a specific configuration setting */
+typedef int (*ConfigParserCallback)(
+               const char *filename,
+               unsigned line,
+               const char *section,
+               const char *lvalue,
+               int ltype,
+               const char *rvalue,
+               void *data);
+
+typedef int (*ConfigParseFunc)(const char *path, void *data);
+
+/* Wraps information for parsing a specific configuration variable, to
+ * be stored in a simple array */
+typedef struct ConfigTableItem {
+       const char *section;            /* Section */
+       const char *lvalue;             /* Name of the variable */
+       ConfigParserCallback cb;        /* Function that is called to
+                                        * parse the variable's
+                                        * value */
+       int ltype;                      /* Distinguish different
+                                        * variables passed to the
+                                        * same callback */
+       void *data;                     /* Where to store the
+                                        * variable's data */
+} ConfigTableItem;
+
+void remove_app_conf_info_list(void);
+void remove_service_conf_info_list(void);
+GSList *get_app_conf_info_list(void);
+GSList *get_service_conf_info_list(void);
+void resourced_parse_vendor_configs(void);
+void resourced_free_vendor_configs(void);
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/src/common/conf/config.h.in b/src/common/conf/config.h.in
new file mode 100644 (file)
index 0000000..15d12d1
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _CONFIG_H_GENERATED
+#define _CONFIG_H_GENERATED
+
+#cmakedefine EXCLUDE_LIST_RO_PATH "@EXCLUDE_LIST_RO_PATH@"
+#cmakedefine EXCLUDE_LIST_RW_PATH "@EXCLUDE_LIST_RW_PATH@"
+/* It's command line arguments*/
+
+#cmakedefine CONFIG_DATAUSAGE_NFACCT @CONFIG_DATAUSAGE_NFACCT@
+#cmakedefine TETHERING_FEATURE  @TETHERING_FEATURE@
+
+#endif /* _CONFIG_H_GENERATED*/
diff --git a/src/common/conf/cpu-common.c b/src/common/conf/cpu-common.c
new file mode 100644 (file)
index 0000000..f264360
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * resourced
+ *
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "macro.h"
+#include "cpu-common.h"
+#include "trace.h"
+#include "resourced.h"
+
+static struct cpu_sched_conf *cpu_sched_conf = NULL;
+static struct cpu_affinity_conf *cpu_affinity_conf = NULL;
+static struct cpu_throttling_conf *cpu_throttling_conf = NULL;
+static struct cpu_boosting_conf *cpu_boosting_conf[CPU_BOOSTING_LEVEL_END] = {NULL, };
+
+struct cpu_sched_conf *get_cpu_sched_conf(void)
+{
+       if (!cpu_sched_conf) {
+               cpu_sched_conf = (struct cpu_sched_conf *)calloc(1, sizeof (struct cpu_sched_conf));
+               if (!cpu_sched_conf) {
+                       _E("Failed to alloc memory for cpu scheduler configuration");
+                       return NULL;
+               }
+               else {
+                       cpu_sched_conf->cpu_sched_flag = CPU_SCHED_UNINITIALIZED;
+                       cpu_sched_conf->cpu_cgroup_info.rt_runtime_us = 0;
+                       cpu_sched_conf->cpu_cgroup_info.rt_period_us = 0;
+               }
+       }
+
+       return cpu_sched_conf;
+}
+
+void free_cpu_sched_conf(void)
+{
+       if (cpu_sched_conf)
+               free(cpu_sched_conf);
+}
+
+char *get_cpu_affinity_conf_name(void)
+{
+       if (cpu_affinity_conf)
+               return cpu_affinity_conf->cpuset_cgroup_info.name;
+       else
+               return NULL;
+}
+
+char *get_cpu_affinity_conf_value(void)
+{
+       if (cpu_affinity_conf)
+               return cpu_affinity_conf->cpuset_cgroup_info.value;
+       else
+               return NULL;
+}
+
+int set_cpu_affinity_conf(const char *name, const char *value)
+{
+       if (!cpu_affinity_conf) {
+               cpu_affinity_conf = (struct cpu_affinity_conf *)calloc(1, sizeof (struct cpu_affinity_conf));
+               if (!cpu_affinity_conf) {
+                       _E("Failed to alloc memory for cpu affinity configuration");
+                       return RESOURCED_ERROR_OUT_OF_MEMORY;
+               }
+       }
+
+       if (strlen(name) + 1 > sizeof(cpu_affinity_conf->cpuset_cgroup_info.name)) {
+               _E("Size of cpu configuration for name is not enough");
+               return RESOURCED_ERROR_OUT_OF_MEMORY;
+       }
+       strncpy(cpu_affinity_conf->cpuset_cgroup_info.name, name, sizeof(cpu_affinity_conf->cpuset_cgroup_info.name) - 1);
+
+       if (strlen(value) + 1 > sizeof(cpu_affinity_conf->cpuset_cgroup_info.value)) {
+               _E("Size of cpu configuration for value is not enough");
+               return RESOURCED_ERROR_OUT_OF_MEMORY;
+       }
+       strncpy(cpu_affinity_conf->cpuset_cgroup_info.value, value, sizeof(cpu_affinity_conf->cpuset_cgroup_info.value) - 1);
+
+       return RESOURCED_ERROR_NONE;
+}
+
+void free_cpu_affinity_conf(void)
+{
+       if (cpu_affinity_conf)
+               free(cpu_affinity_conf);
+}
+
+struct cpu_throttling_conf *get_cpu_throttling_conf(void)
+{
+       if (!cpu_throttling_conf) {
+               cpu_throttling_conf = (struct cpu_throttling_conf *)calloc(1, sizeof (struct cpu_throttling_conf));
+               if (!cpu_throttling_conf) {
+                       _E("Failed to alloc memory for cpu throttling configuration");
+                       return NULL;
+               }
+               else {
+                       cpu_throttling_conf->enable = false;
+                       cpu_throttling_conf->cpu_sched_info.cpu_sched_type = CPU_SCHED_NONE;
+                       cpu_throttling_conf->cpu_sched_info.cpu_nice = CPU_INIT_NICE;
+                       cpu_throttling_conf->cpu_cgroup_info.cfs_runtime_us = 0;
+                       cpu_throttling_conf->cpu_cgroup_info.cfs_period_us = 0;
+                       cpu_throttling_conf->cpu_cgroup_info.cpu_share = 0;
+               }
+       }
+
+       return cpu_throttling_conf;
+}
+
+void free_cpu_throttling_conf(void)
+{
+       if (cpu_throttling_conf)
+               free(cpu_throttling_conf);
+}
+
+struct cpu_boosting_conf *get_cpu_boosting_conf(cpu_boosting_level_e level)
+{
+       if (!cpu_boosting_conf[level]) {
+               cpu_boosting_conf[level] = (struct cpu_boosting_conf *)
+                       calloc(1, sizeof (struct cpu_boosting_conf));
+
+               if (!cpu_boosting_conf[level]) {
+                       _E("Failed to alloc memory for cpu boosting (level = %d) configuration", level);
+                       return NULL;
+               }
+               else {
+                       cpu_boosting_conf[level]->enable = false;
+                       cpu_boosting_conf[level]->cpu_sched_info.cpu_sched_type = CPU_SCHED_NONE;
+                       cpu_boosting_conf[level]->cpu_sched_info.cpu_nice = CPU_INIT_NICE;
+                       cpu_boosting_conf[level]->cpu_sched_info.cpu_rt_priority = CPU_INIT_PRIO;
+               }
+       }
+
+       return cpu_boosting_conf[level];
+}
+
+void free_cpu_boosting_conf(cpu_boosting_level_e level)
+{
+       if (cpu_boosting_conf[level])
+               free(cpu_boosting_conf[level]);
+}
diff --git a/src/common/conf/cpu-common.h b/src/common/conf/cpu-common.h
new file mode 100644 (file)
index 0000000..bd549b8
--- /dev/null
@@ -0,0 +1,114 @@
+#ifndef __CPU_COMMON_H__
+#define __CPU_COMMON_H__
+
+#include <stdbool.h>
+
+#include <cpu-boosting-type.h>
+#include <cpu-boosting-private.h>
+
+#include "util.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define CPU_INIT_NICE         100
+#define CPU_MAX_NICE          19
+#define CPU_MIN_NICE          -20
+#define CPU_DEFAULT_NICE      0
+
+#define CPU_INIT_PRIO         0
+#define CPU_MAX_PRIO          99
+#define CPU_MIN_PRIO          1
+
+#define CPU_DEFAULT_SHARE     1024
+#define CPU_THROTTLING_SHARE  64
+
+enum cpu_sched_flag {
+       CPU_SCHED_UNINITIALIZED = 0,
+       CPU_SCHED_RUNTIME_SHARE = 1,
+       CPU_SCHED_NO_RUNTIME_SHARE = 2,
+       CPU_SCHED_RUNTIME_GREED = 4,
+};
+
+enum cpu_sched_type {
+       CPU_SCHED_NONE = 0,
+       CPU_SCHED_IDLE = 1,
+       CPU_SCHED_BATCH,
+       CPU_SCHED_OTHER,
+       CPU_SCHED_FIFO,
+       CPU_SCHED_RR,
+       CPU_SCHED_DEADLINE,
+};
+
+struct cpu_boosting_info {
+       pid_t tid;
+       int level;                     /* current boosting level */
+       guint gsource_id;              /* timer id */
+};
+
+struct cpu_boosting_input {
+       cpu_boosting_input_t client_input;
+       int sock;
+       guint *gsource_id;
+       bool remove_input;
+};
+
+struct cpu_sched_info {
+       enum cpu_sched_type cpu_sched_type;
+       int cpu_nice;                        /* fixed cpu nice */
+       int cpu_rt_priority;                 /* fixed cpu priority for rt schedulers */
+};
+
+struct cpuset_cgroup_info {
+       char name[64];
+       char value[64];
+};
+
+struct cpu_cgroup_info {
+       long long cfs_runtime_us;
+       long long rt_runtime_us;
+       unsigned long long cfs_period_us;
+       unsigned long long rt_period_us;
+       unsigned long long cpu_share;
+};
+
+struct cpu_sched_conf {
+       enum cpu_sched_flag cpu_sched_flag;
+       struct cpu_cgroup_info cpu_cgroup_info;
+};
+
+struct cpu_affinity_conf {
+       struct cpuset_cgroup_info cpuset_cgroup_info;
+};
+
+struct cpu_throttling_conf {
+       bool enable;
+       struct cpu_sched_info cpu_sched_info;
+       struct cpu_cgroup_info cpu_cgroup_info;
+};
+
+struct cpu_boosting_conf {
+       bool enable;
+       struct cpu_sched_info cpu_sched_info;
+};
+
+struct cpu_sched_conf *get_cpu_sched_conf(void);
+void free_cpu_sched_conf(void);
+
+char *get_cpu_affinity_conf_name(void);
+char *get_cpu_affinity_conf_value(void);
+int set_cpu_affinity_conf(const char *name, const char *value);
+void free_cpu_affinity_conf(void);
+
+struct cpu_throttling_conf *get_cpu_throttling_conf(void);
+void free_cpu_throttling_conf(void);
+
+struct cpu_boosting_conf *get_cpu_boosting_conf(cpu_boosting_level_e level);
+void free_cpu_boosting_conf(cpu_boosting_level_e level);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __CPU_COMMON_H__ */
diff --git a/src/common/conf/dedup-common.c b/src/common/conf/dedup-common.c
new file mode 100644 (file)
index 0000000..c45be8c
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * resourced
+ *
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "macro.h"
+#include "dedup-common.h"
+#include "trace.h"
+
+static struct dedup_conf *dedup_conf = NULL;
+
+static enum dedup_state dedup_state;
+
+struct dedup_conf *get_dedup_conf(void)
+{
+       if (!dedup_conf) {
+               dedup_conf = (struct dedup_conf *)calloc(1, sizeof (struct dedup_conf));
+               if (!dedup_conf) {
+                       _E("Failed to alloc memory for cpu configuration");
+                       return NULL;
+               }
+               else {
+                       dedup_conf->enable = false;
+                       dedup_conf->boot_dedup_enable = false;
+                       dedup_conf->scan_on_lowmem = false;
+               }
+       }
+
+       return dedup_conf;
+}
+
+void free_dedup_conf(void)
+{
+       if (dedup_conf)
+               free(dedup_conf);
+}
+
+enum dedup_state dedup_get_state(void)
+{
+       return dedup_state;
+}
+
+void dedup_set_state(enum dedup_state state)
+{
+       if ((state != DEDUP_ON) && (state != DEDUP_OFF) &&
+                       state != DEDUP_ONE_SHOT)
+               return;
+
+       dedup_state = state;
+}
diff --git a/src/common/conf/dedup-common.h b/src/common/conf/dedup-common.h
new file mode 100644 (file)
index 0000000..be10294
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * resourced
+ *
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * @file dedup-common.h
+ * @desc dedup common process
+ **/
+
+#ifndef __DEDUP_COMMON_H__
+#define __DEDUP_COMMON_H__
+
+#include <stdio.h>
+#include "resourced.h"
+#include "memory-cgroup.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define DEDUP_CONF_FILE                RD_CONFIG_FILE(optimizer)
+#define DEDUP_SYSFS_KSM_PATH   "/sys/kernel/mm/ksm"
+
+/* KSM operations */
+#define DEDUP_SYSFS_KSM_RUN    "/sys/kernel/mm/ksm/run"
+#define DEDUP_SYSFS_KSM_ONESHOT "/sys/kernel/mm/ksm/one_shot_scanning"
+
+enum dedup_state {
+       DEDUP_ARG_START = -1,
+       DEDUP_OFF,
+       DEDUP_ON,
+       DEDUP_ONE_SHOT,
+       DEDUP_ARG_END,
+};
+
+enum dedup_mode {
+       DEDUP_MODE_NONE = 0,
+       DEDUP_MODE_PERIODIC,
+       DEDUP_MODE_ONESHOT,
+       DEDUP_MODE_MAX,
+};
+
+enum ksm_stat {
+       KSM_STAT_PAGES_SHARING = 0,
+       KSM_STAT_PAGES_SHARED,
+       KSM_STAT_MAX,
+};
+
+enum ksm_scan_mode {
+       KSM_SCAN_NONE = 0,
+       KSM_SCAN_PARTIAL,
+       KSM_SCAN_FULL,
+};
+
+struct ksm {
+       char mode[MAX_TYPE_LENGTH];
+       int pages;
+       int boost_pages;
+};
+
+struct dedup_conf {
+       bool enable;
+       bool boot_dedup_enable;
+       bool scan_on_lowmem;
+       struct ksm ksm;
+};
+
+struct dedup_conf *get_dedup_conf(void);
+void free_dedup_conf(void);
+
+enum dedup_state dedup_get_state(void);
+void dedup_set_state(enum dedup_state state);
+unsigned int dedup_get_ksm_stat(enum ksm_stat stat_type);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __DEDUP_COMMON_H__ */
diff --git a/src/common/conf/swap-common.c b/src/common/conf/swap-common.c
new file mode 100644 (file)
index 0000000..709e8e3
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * resourced
+ *
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "macro.h"
+#include "swap-common.h"
+#include "trace.h"
+
+static struct swap_conf *swap_conf = NULL;
+
+static enum swap_state swap_state = SWAP_OFF;
+
+struct swap_conf *get_swap_conf(void)
+{
+       if (!swap_conf) {
+               swap_conf = (struct swap_conf *)calloc(1, sizeof (struct swap_conf));
+               if (!swap_conf) {
+                       _E("Failed to alloc memory for cpu configuration");
+                       return NULL;
+               }
+               else {
+                       swap_conf->enable = false;
+                       swap_conf->boot_reclaim_enable = false;
+                       swap_conf->swap_type = SWAP_TYPE_NONE;
+                       swap_conf->swappiness[MEMCG_THROTTLING] = MEMORY_INIT_SWAPPINESS;
+               }
+       }
+
+       return swap_conf;
+}
+
+
+void free_swap_conf(void)
+{
+       if (swap_conf)
+               free(swap_conf);
+}
+
+enum swap_state swap_get_state(void)
+{
+       return swap_state;
+}
+
+/* Following function is supposed to be used by swap module only.
+ *
+ * Implemented in common part for the purpose of integration with
+ * dynamically loaded "swap" plugin.
+ *
+ * From available options it seems cleaner to export getter/setter
+ * like the one below (with a bit of swap-internal logic).
+ * Other option would be keeping set function in swap module, but
+ * that would require us to reference and alter then-global swap_state
+ * variable (in common part) from swap shared object.
+ */
+void swap_set_state(enum swap_state state)
+{
+       if ((state != SWAP_ON) && (state != SWAP_OFF))
+               return;
+
+       swap_state = state;
+}
diff --git a/src/common/conf/swap-common.h b/src/common/conf/swap-common.h
new file mode 100644 (file)
index 0000000..17116ed
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * resourced
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * @file swap-common.h
+ * @desc swap common process
+ **/
+
+#ifndef __SWAP_COMMON_H__
+#define __SWAP_COMMON_H__
+
+#include <stdio.h>
+#include "resourced.h"
+#include "memory-cgroup.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define SWAP_ZRAM_SYSFILE      "/sys/block/zram0/"
+#define SWAP_FILE_NAME         "/opt/usr/.swapfile"
+#define SWAP_CONF_FILE         RD_CONFIG_FILE(optimizer)
+
+#define MEMORY_INIT_SWAPPINESS   200
+
+enum swap_state {
+       SWAP_ARG_START = -1,
+       SWAP_OFF,
+       SWAP_ON,
+       SWAP_ARG_END,
+};
+
+enum swap_type {
+       SWAP_TYPE_NONE = 0x0,
+       SWAP_TYPE_ZRAM = 0x1,
+       SWAP_TYPE_FILE = 0x2,
+       SWAP_TYPE_ZSWAP = 0x4,
+       SWAP_TYPE_MAX,
+};
+
+struct swap_status_msg {
+       char path[MAX_PATH_LENGTH];
+};
+
+enum swap_compact_reason {
+       SWAP_COMPACT_MEM_LEVEL_CRITICAL,
+       SWAP_COMPACT_MEM_LEVEL_OOM,
+       SWAP_COMPACT_SWAP_FULL,
+       SWAP_COMPACT_RESASON_MAX,
+};
+
+/*
+ * Each swap modoule can have priority.
+ * The swap list of kernel has low-to-high order
+ * while swap ordering is high-to-low.
+ * So, if a swap module has lower priority, it should be intialized eariler.
+ * On the top of that, SWAP_PRI_DISABLE will be used
+ * not to support multiple swap devices.
+ */
+enum swap_priority {
+       SWAP_PRI_DISABLE = -255,
+       SWAP_PRI_LOW = -1,
+       SWAP_PRI_DEFAULT = 0,
+       SWAP_PRI_HIGH = 1,
+};
+
+struct swap_module_ops {
+       char *name;
+       enum swap_type type;
+       char *path;
+       int priority;
+       unsigned int k_size;
+       int (*init)(void *data);
+       int (*exit) (void *data);
+       int (*activate)(void *data);
+       int (*reclaim)(void *data);
+       int (*conf)(void *data);
+};
+
+struct zram_conf {
+       char algorithm[MAX_TYPE_LENGTH - 1];
+       float ratio;
+};
+
+struct zswap_conf {
+       float pool_ratio;
+       char pool_type[MAX_TYPE_LENGTH -1];
+};
+
+struct swap_conf {
+       bool enable;
+       bool boot_reclaim_enable;
+       enum swap_type swap_type;
+       int swappiness[MEMCG_END];
+       struct zram_conf zram;
+       struct zswap_conf zswap;
+};
+
+struct swap_conf *get_swap_conf(void);
+void free_swap_conf(void);
+
+enum swap_state swap_get_state(void);
+void swap_set_state(enum swap_state state);
+
+int swap_set_file(char *file, struct swap_module_ops *swap, char *crypt_type);
+int do_mkswap(const char *device);
+int do_dd(char *input, char *output, unsigned int size, unsigned int count);
+
+bool swap_is_on(const char *name);
+
+void swap_add(const struct swap_module_ops *swap);
+void swap_remove(const struct swap_module_ops *swap);
+
+#define SWAP_MODULE_REGISTER(swap)                                     \
+static void __attribute__ ((constructor)) swap_module_register(void)           \
+{                                                      \
+       swap_add(swap);                                 \
+}                                                      \
+static void __attribute__ ((destructor)) swap_module_unregister(void)  \
+{                                                      \
+       swap_remove(swap);                              \
+}
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __SWAP_COMMON_H__ */
diff --git a/src/common/config-parser.c b/src/common/config-parser.c
deleted file mode 100644 (file)
index 7e4ffc3..0000000
+++ /dev/null
@@ -1,1022 +0,0 @@
-/*
- * resourced
- *
- * Copyright (c) 2013 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <assert.h>
-#include <limits.h>
-#include <ctype.h>
-
-#include "util.h"
-#include "trace.h"
-#include "config-parser.h"
-#include "proc-common.h"
-#include "cpu-cgroup.h"
-#include "swap-common.h"
-#include "dedup-common.h"
-#include "compact-common.h"
-#include "cpu-common.h"
-
-#define MAX_SECTION            64
-
-static int config_parse_swap_types(
-                                 const char *rvalue,
-                                 void *data)
-{
-       enum swap_type *type = data;
-       char *word, *state;
-       size_t l;
-
-       if (is_empty(rvalue))
-               return 0;
-
-       *type = 0;
-
-       FOREACH_WORD_SEPARATOR(word, l, rvalue, "+|", state) {
-               if (strneq(word, "zram", l))
-                       *type |= SWAP_TYPE_ZRAM;
-               else if (strneq(word, "file", l))
-                       *type |= SWAP_TYPE_FILE;
-               else if (strneq(word, "zswap", l))
-                       *type |= SWAP_TYPE_ZSWAP;
-               else
-                       return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int config_parse_cpu_sched_features(const char *value)
-{
-       int cpu_sched_flag = CPU_SCHED_UNINITIALIZED;
-       char *word, *state;
-       size_t l;
-
-       if (is_empty(value))
-               return cpu_sched_flag;
-
-       FOREACH_WORD_SEPARATOR(word, l, value, ",", state) {
-               if (strneq(word, RT_RUNTIME_SHARE_VALUE_CONF, l))
-                       cpu_sched_flag |= CPU_SCHED_RUNTIME_SHARE;
-               else if (strneq(word, NO_RT_RUNTIME_SHARE_VALUE_CONF, l))
-                       cpu_sched_flag |= CPU_SCHED_NO_RUNTIME_SHARE;
-/*             else if (strneq(word, RT_RUNTIME_GREED_VALUE_CONF, l))
-                       cpu_sched_flag |= CPU_SCHED_RUNTIME_GREED;*/
-               else
-                       return CPU_SCHED_UNINITIALIZED;
-       }
-
-       return cpu_sched_flag;
-}
-
-static char config_parse_time_unit(const char *value)
-{
-       char chr;
-       char *ptr = strchr(value, 's');
-       if (ptr == NULL) {
-               _E("[CONFIG] Cannot find 's' in the string (%s)", value);
-               return 'X';
-       }
-
-       if (value > (ptr - 1)) {
-               _E("[CONFIG] Size of string should be larger than 1");
-               return 'X';
-       }
-
-       chr = *(ptr - 1);
-       if (isdigit(chr)) {
-               *ptr = '\0';
-               return ' ';
-       }
-       else {
-               *(ptr - 1) = '\0';
-               return chr;
-       }
-}
-
-static long long config_parse_ll_time_us(const char *value)
-{
-       char unit = config_parse_time_unit(value);
-
-       if (unit == ' ') {
-               return strtoll(value, NULL, 10) * 1000 * 1000;
-       }
-       else if (unit == 'm') {
-               return strtoll(value, NULL, 10) * 1000;
-       }
-       else if (unit == 'u') {
-               return strtoll(value, NULL, 10);
-       }
-       else {
-               _E("[CONFIG] Unknown unit of time");
-               return 0;
-       }
-}
-
-static unsigned long long config_parse_ull_time_us(const char *value)
-{
-       char unit = config_parse_time_unit(value);
-
-       if (unit == ' ') {
-               return strtoull(value, NULL, 10) * 1000 * 1000;
-       }
-       else if (unit == 'm') {
-               return strtoull(value, NULL, 10) * 1000;
-       }
-       else if (unit == 'u') {
-               return strtoull(value, NULL, 10);
-       }
-       else {
-               _E("[CONFIG] Unknown unit of time");
-               return 0;
-       }
-}
-
-static bool config_parse_bool(const char *value)
-{
-       if (!strncmp(value, "yes", 4) ||
-                       !strncmp(value, "1", 2) ||
-                       !strncmp(value, "ok", 3) ||
-                       !strncmp(value, "on", 3))
-               return true;
-       else if (!strncmp(value, "no", 3) ||
-                       !strncmp(value, "0", 2) ||
-                       !strncmp(value, "off", 4))
-               return false;
-       else {
-               _E("Unknown name (%s)", value);
-               return false;
-       }
-}
-
-static int config_parse_sched_type(const char *value)
-{
-       if (!strncmp(value, CPU_SCHED_IDLE_VALUE_CONF,
-                               strlen(CPU_SCHED_IDLE_VALUE_CONF) +1))
-               return CPU_SCHED_IDLE;
-       else if (!strncmp(value, CPU_SCHED_OTHER_VALUE_CONF,
-                               strlen(CPU_SCHED_OTHER_VALUE_CONF) +1))
-               return CPU_SCHED_OTHER;
-       else if (!strncmp(value, CPU_SCHED_BATCH_VALUE_CONF,
-                               strlen(CPU_SCHED_BATCH_VALUE_CONF) +1))
-               return CPU_SCHED_BATCH;
-       else if (!strncmp(value, CPU_SCHED_FIFO_VALUE_CONF,
-                               strlen(CPU_SCHED_FIFO_VALUE_CONF) +1))
-               return CPU_SCHED_FIFO;
-       else if (!strncmp(value, CPU_SCHED_RR_VALUE_CONF,
-                               strlen(CPU_SCHED_RR_VALUE_CONF) +1))
-               return CPU_SCHED_RR;
-       else if (!strncmp(value, CPU_SCHED_DEADLINE_VALUE_CONF,
-                               strlen(CPU_SCHED_DEADLINE_VALUE_CONF) +1))
-               return CPU_SCHED_DEADLINE;
-       else {
-               _E("invalid parameter (%s)", value);
-               return CPU_SCHED_NONE;
-       }
-}
-
-static cpu_boosting_level_e config_parse_boosting_level(const char *value)
-{
-       if (!strncmp(value, CPU_BOOSTING_LEVEL_STRONG_VALUE_CONF,
-                               strlen(CPU_BOOSTING_LEVEL_STRONG_VALUE_CONF) + 1))
-               return CPU_BOOSTING_LEVEL_STRONG;
-       else if (!strncmp(value, CPU_BOOSTING_LEVEL_MEDIUM_VALUE_CONF,
-                               strlen(CPU_BOOSTING_LEVEL_MEDIUM_VALUE_CONF) + 1))
-               return CPU_BOOSTING_LEVEL_MEDIUM;
-       else if (!strncmp(value, CPU_BOOSTING_LEVEL_WEAK_VALUE_CONF,
-                               strlen(CPU_BOOSTING_LEVEL_WEAK_VALUE_CONF) + 1))
-               return CPU_BOOSTING_LEVEL_WEAK;
-       else
-               return CPU_BOOSTING_LEVEL_NONE;
-}
-
-static int optimizer_config(struct parse_result *result, void *user_data)
-{
-       if (!result)
-               return RESOURCED_ERROR_INVALID_PARAMETER;
-
-       struct swap_conf *swap_conf = get_swap_conf();
-       if (swap_conf == NULL) {
-               _E("[CONFIG] memory swap configuration is NULL");
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       struct dedup_conf *dedup_conf = get_dedup_conf();
-       if (dedup_conf == NULL) {
-               _E("[CONFIG] memory dedup configuration is NULL");
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       struct compact_conf *compact_conf = get_compact_conf();
-       if (compact_conf == NULL) {
-               _E("[CONFIG] memory compact configuration is NULL");
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       struct cpu_sched_conf *cpu_sched_conf = get_cpu_sched_conf();
-       if (cpu_sched_conf == NULL) {
-               _E("[CONFIG] cpu_sched configuration is NULL");
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       if (!strncmp(result->section, SWAP_SECTION, strlen(SWAP_SECTION)+1)) {
-               if (!swap_conf->enable)
-                       swap_conf->enable = true;
-/*             if (!strncmp(result->name, SWAP_ENABLE_NAME_CONF, strlen(SWAP_ENABLE_NAME_CONF)+1)) {
-                               swap_conf->enable = config_parse_bool(result->value);
-               }*/
-               if (!strncmp(result->name, RECLAIM_AT_BOOT_NAME_CONF,
-                                       strlen(RECLAIM_AT_BOOT_NAME_CONF)+1)) {
-                               swap_conf->boot_reclaim_enable = config_parse_bool(result->value);
-               }
-               else if (!strncmp(result->name, SWAP_TYPE_NAME_CONF,
-                                       strlen(SWAP_TYPE_NAME_CONF)+1)) {
-                       if (config_parse_swap_types(result->value, &swap_conf->swap_type) < 0) {
-                               _E("[CONFIG] Failed to parse type of swap, so use zram type");
-                               swap_conf->swap_type = SWAP_TYPE_ZRAM;
-                       }
-               }
-               else if (!strncmp(result->name, THROTTLING_SWAPPINESS_NAME_CONF,
-                                       strlen(THROTTLING_SWAPPINESS_NAME_CONF)+1)) {
-                       swap_conf->swappiness[MEMCG_THROTTLING] = atoi(result->value);
-               }
-               else {
-                       _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
-                                       result->name, result->value, result->section);
-               }
-       }
-       else if (!strncmp(result->section, ZRAM_SECTION, strlen(ZRAM_SECTION)+1)) {
-               if (!strncmp(result->name, COMP_ALGORITHM_NAME_CONF, strlen(COMP_ALGORITHM_NAME_CONF)+1)) {
-                       if (strlen(result->value) + 1 > sizeof(swap_conf->zram.algorithm)) {
-                               _E("Size of swap_conf->zram.algorithm is not enough");
-                               return RESOURCED_ERROR_OUT_OF_MEMORY;
-                       }
-                       strncpy(swap_conf->zram.algorithm, result->value,
-                                       sizeof(swap_conf->zram.algorithm) - 1);
-               }
-               else if (!strncmp(result->name, ZRAM_RATIO_NAME_CONF, strlen(ZRAM_RATIO_NAME_CONF)+1)) {
-                       swap_conf->zram.ratio = atof(result->value);
-               }
-               else {
-                       _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
-                                       result->name, result->value, result->section);
-               }
-       }
-       else if (!strncmp(result->section, ZSWAP_SECTION, strlen(ZSWAP_SECTION)+1)) {
-               if (!strncmp(result->name, POOL_RATIO_NAME_CONF, strlen(POOL_RATIO_NAME_CONF)+1)) {
-                       swap_conf->zswap.pool_ratio = atof(result->value);
-               }
-               else if (!strncmp(result->name, POOL_TYPE_NAME_CONF, strlen(POOL_TYPE_NAME_CONF)+1)) {
-                       if (strlen(result->value) + 1 > sizeof(swap_conf->zswap.pool_type)) {
-                               _E("Size of swap_conf->zswap.pool_type is not enough");
-                               return RESOURCED_ERROR_OUT_OF_MEMORY;
-                       }
-                       strncpy(swap_conf->zswap.pool_type, result->value,
-                                       sizeof(swap_conf->zswap.pool_type) - 1);
-               }
-               else {
-                       _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
-                                       result->name, result->value, result->section);
-               }
-       }
-       else if (!strncmp(result->section, DEDUP_SECTION, strlen(DEDUP_SECTION)+1)) {
-               if (!dedup_conf->enable)
-                       dedup_conf->enable = true;
-/*             if (!strncmp(result->name, DEDUP_ENABLE_NAME_CONF, strlen(DEDUP_ENABLE_NAME_CONF)+1)) {
-                               dedup_conf->enable = config_parse_bool(result->value);
-               }*/
-               if (!strncmp(result->name, DEDUP_AT_BOOT_NAME_CONF, strlen(DEDUP_AT_BOOT_NAME_CONF)+1)) {
-                       dedup_conf->boot_dedup_enable = config_parse_bool(result->value);
-               }
-               else if (!strncmp(result->name, SCAN_ON_LOWMEM_NAME_CONF, strlen(SCAN_ON_LOWMEM_NAME_CONF)+1)) {
-                       dedup_conf->scan_on_lowmem = config_parse_bool(result->value);
-               }
-               else {
-                       _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
-                                       result->name, result->value, result->section);
-               }
-       }
-       else if (!strncmp(result->section, KSM_SECTION, strlen(KSM_SECTION)+1)) {
-               if (!strncmp(result->name, KSM_MODE_NAME_CONF, strlen(KSM_MODE_NAME_CONF)+1)) {
-                       if (strlen(result->value) + 1 > sizeof(dedup_conf->ksm.mode)) {
-                               _E("Size of swap_conf->type is not enough");
-                               return RESOURCED_ERROR_OUT_OF_MEMORY;
-                       }
-                       strncpy(dedup_conf->ksm.mode, result->value,
-                                       sizeof(dedup_conf->ksm.mode) - 1);
-               }
-               else if (!strncmp(result->name, PAGES_TO_SCAN_NAME_CONF, strlen(PAGES_TO_SCAN_NAME_CONF)+1)) {
-                       dedup_conf->ksm.pages = atoi(result->value);
-               }
-               else if (!strncmp(result->name, PAGES_TO_SCAN_WITH_BOOST_NAME_CONF,
-                                       strlen(PAGES_TO_SCAN_WITH_BOOST_NAME_CONF)+1)) {
-                       dedup_conf->ksm.boost_pages = atoi(result->value);
-               }
-               else {
-                       _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
-                                       result->name, result->value, result->section);
-               }
-       }
-       else if (!strncmp(result->section, COMPACTION_SECTION, strlen(COMPACTION_SECTION)+1)) {
-               if (!compact_conf->enable)
-                       compact_conf->enable = true;
-/*             if (!strncmp(result->name, COMPACTION_ENABLE_NAME_CONF,
-                                       strlen(COMPACTION_ENABLE_NAME_CONF)+1)) {
-                       compact_conf->enable = config_parse_bool(result->value);
-               }*/
-               if (!strncmp(result->name, FRAG_LEVEL_NAME_CONF, strlen(FRAG_LEVEL_NAME_CONF)+1)) {
-                       compact_conf->frag_level = atoi(result->value);
-               }
-               else {
-                       _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
-                                       result->name, result->value, result->section);
-               }
-       }
-       else if (!strncmp(result->section, CPU_SCHED_SECTION,
-                               strlen(CPU_SCHED_SECTION)+1)) {
-               if (!strncmp(result->name, CPU_SCHED_FEATURE_NAME_CONF,
-                                       strlen(CPU_SCHED_FEATURE_NAME_CONF) + 1)) {
-                       cpu_sched_conf->cpu_sched_flag = config_parse_cpu_sched_features(result->value);
-               }
-               else if (!strncmp(result->name, CPU_RT_RUN_TIME_NAME_CONF,
-                                       strlen(CPU_RT_RUN_TIME_NAME_CONF) + 1)) {
-                       cpu_sched_conf->cpu_cgroup_info.rt_runtime_us = config_parse_ll_time_us(result->value);
-               }
-               else if (!strncmp(result->name, CPU_RT_PERIOD_NAME_CONF,
-                                       strlen(CPU_RT_PERIOD_NAME_CONF) + 1)) {
-                       cpu_sched_conf->cpu_cgroup_info.rt_period_us = config_parse_ull_time_us(result->value);
-               }
-               else {
-                       _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
-                                       result->name, result->value, result->section);
-               }
-       }
-       else if (!strncmp(result->section, CPU_AFFINITY_SECTION,
-                               strlen(CPU_AFFINITY_SECTION)+1)) {
-               int error = RESOURCED_ERROR_NONE;
-
-               if (!strncmp(result->name, FOREGROUND_APPS_NAME_CONF,
-                                       strlen(FOREGROUND_APPS_NAME_CONF) + 1)) {
-                       error = set_cpu_affinity_conf(result->name, result->value);
-               }
-               else {
-                       _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
-                                       result->name, result->value, result->section);
-               }
-
-               return error;
-       }
-       else if (!strncmp(result->section, CPU_BOOSTING_LEVEL_STRONG_SECTION,
-                               strlen(CPU_BOOSTING_LEVEL_STRONG_SECTION)+1)) {
-               struct cpu_boosting_conf *cpu_boosting_conf =
-                       get_cpu_boosting_conf(CPU_BOOSTING_LEVEL_STRONG);
-               if (cpu_boosting_conf == NULL) {
-                       _E("[CONFIG] cpu_boosting configuration is NULL");
-                       return RESOURCED_ERROR_FAIL;
-               }
-
-               if (!cpu_boosting_conf->enable)
-                       cpu_boosting_conf->enable = true;
-
-               if (!strncmp(result->name, CPU_SCHED_NAME_CONF,
-                                       strlen(CPU_SCHED_NAME_CONF) + 1)) {
-                       cpu_boosting_conf->cpu_sched_info.cpu_sched_type =
-                               config_parse_sched_type(result->value);
-               }
-               else if (!strncmp(result->name, CPU_NICE_NAME_CONF,
-                                       strlen(CPU_NICE_NAME_CONF) + 1)) {
-                       cpu_boosting_conf->cpu_sched_info.cpu_nice =
-                               atoi(result->value);
-               }
-               else if (!strncmp(result->name, CPU_RT_PRIORITY_NAME_CONF,
-                                       strlen(CPU_RT_PRIORITY_NAME_CONF) + 1)) {
-                       cpu_boosting_conf->cpu_sched_info.cpu_rt_priority =
-                               atoi(result->value);
-               }
-               else {
-                       _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
-                                       result->name, result->value, result->section);
-               }
-       }
-       else if (!strncmp(result->section, CPU_BOOSTING_LEVEL_MEDIUM_SECTION,
-                               strlen(CPU_BOOSTING_LEVEL_MEDIUM_SECTION)+1)) {
-               struct cpu_boosting_conf *cpu_boosting_conf =
-                       get_cpu_boosting_conf(CPU_BOOSTING_LEVEL_MEDIUM);
-               if (cpu_boosting_conf == NULL) {
-                       _E("[CONFIG] cpu_boosting configuration is NULL");
-                       return RESOURCED_ERROR_FAIL;
-               }
-
-               if (!cpu_boosting_conf->enable)
-                       cpu_boosting_conf->enable = true;
-
-               if (!strncmp(result->name, CPU_SCHED_NAME_CONF,
-                                       strlen(CPU_SCHED_NAME_CONF) + 1)) {
-                       cpu_boosting_conf->cpu_sched_info.cpu_sched_type =
-                               config_parse_sched_type(result->value);
-               }
-               else if (!strncmp(result->name, CPU_NICE_NAME_CONF,
-                                       strlen(CPU_NICE_NAME_CONF) + 1)) {
-                       cpu_boosting_conf->cpu_sched_info.cpu_nice =
-                               atoi(result->value);
-               }
-               else if (!strncmp(result->name, CPU_RT_PRIORITY_NAME_CONF,
-                                       strlen(CPU_RT_PRIORITY_NAME_CONF) + 1)) {
-                       cpu_boosting_conf->cpu_sched_info.cpu_rt_priority =
-                               atoi(result->value);
-               }
-               else {
-                       _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
-                                       result->name, result->value, result->section);
-               }
-       }
-       else if (!strncmp(result->section, CPU_BOOSTING_LEVEL_WEAK_SECTION,
-                               strlen(CPU_BOOSTING_LEVEL_WEAK_SECTION)+1)) {
-               struct cpu_boosting_conf *cpu_boosting_conf =
-                       get_cpu_boosting_conf(CPU_BOOSTING_LEVEL_WEAK);
-               if (cpu_boosting_conf == NULL) {
-                       _E("[CONFIG] cpu_boosting configuration is NULL");
-                       return RESOURCED_ERROR_FAIL;
-               }
-
-               if (!cpu_boosting_conf->enable)
-                       cpu_boosting_conf->enable = true;
-
-               if (!strncmp(result->name, CPU_SCHED_NAME_CONF,
-                                       strlen(CPU_SCHED_NAME_CONF) + 1)) {
-                       cpu_boosting_conf->cpu_sched_info.cpu_sched_type =
-                               config_parse_sched_type(result->value);
-               }
-               else if (!strncmp(result->name, CPU_NICE_NAME_CONF,
-                                       strlen(CPU_NICE_NAME_CONF) + 1)) {
-                       cpu_boosting_conf->cpu_sched_info.cpu_nice =
-                               atoi(result->value);
-               }
-               else if (!strncmp(result->name, CPU_RT_PRIORITY_NAME_CONF,
-                                       strlen(CPU_RT_PRIORITY_NAME_CONF) + 1)) {
-                       cpu_boosting_conf->cpu_sched_info.cpu_rt_priority =
-                               atoi(result->value);
-               }
-               else {
-                       _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
-                                       result->name, result->value, result->section);
-               }
-       }
-       else {
-               _E("[CONFIG] Unknown section name (%s) and value (%s) on section (%s)",
-                               result->name, result->value, result->section);
-       }
-
-       return RESOURCED_ERROR_NONE;
-}
-
-
-static int limiter_config(struct parse_result *result, void *user_data)
-{
-       if (!result)
-               return RESOURCED_ERROR_INVALID_PARAMETER;
-
-       struct memcg_conf *memcg_conf = get_memcg_conf();
-       if (memcg_conf == NULL) {
-               _E("[CONFIG] memory cgroup configuration is NULL");
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       struct cpu_throttling_conf *cpu_throttling_conf = get_cpu_throttling_conf();
-       if (cpu_throttling_conf == NULL) {
-               _E("[CONFIG] cpu_throttling configuration is NULL");
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       if (!strncmp(result->section, MEMORY_THROTTLING_SECTION,
-                               strlen(MEMORY_THROTTLING_SECTION)+1)) {
-               char *ptr = strchr(result->value, '%');
-               if (ptr == NULL) {
-                       _E("[CONFIG] Cannot find '%%' in the string (%s)", result->value);
-                       return RESOURCED_ERROR_FAIL;
-               }
-               else
-                       *ptr = '\0';
-
-               if (!strncmp(result->name, THROTTLING_LIMIT_NAME_CONF,
-                                       strlen(THROTTLING_LIMIT_NAME_CONF) + 1)) {
-                       memcg_conf->cgroup_limit[MEMCG_THROTTLING] = atof(result->value);
-               }
-               else {
-                       _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
-                                       result->name, result->value, result->section);
-               }
-       }
-       else if (!strncmp(result->section, MEMORY_LEVEL_THRESHOLD_SECTION,
-                               strlen(MEMORY_LEVEL_THRESHOLD_SECTION)+1)) {
-
-               if (!strncmp(result->name, OOM_POPUP_NAME_CONF,
-                                       strlen(OOM_POPUP_NAME_CONF) + 1)) {
-                       memcg_conf->oom_popup = config_parse_bool(result->value);
-               }
-               else {
-                       char temp = '\0';
-                       int error = RESOURCED_ERROR_NONE;
-                       bool percent;
-                       char *ptr = strchr(result->value, '%');
-                       if (ptr == NULL) {
-                               ptr = strchr(result->value, 'B');
-                               if (ptr == NULL) {
-                                       _E("[CONFIG] Cannot find 'B' in the string (%s)", result->value);
-                                       return RESOURCED_ERROR_FAIL;
-                               }
-
-                               if (result->value > (ptr - 1)) {
-                                       _E("[CONFIG] Size of string should be larger than 1");
-                                       return RESOURCED_ERROR_FAIL;
-                               }
-
-                               temp = *(ptr - 1);
-                               *(ptr - 1) = '\0';
-                               percent = false;
-                       }
-                       else {
-                               *ptr = '\0';
-                               percent = true;
-                       }
-
-                       if (!strncmp(result->name, MEDIUM_LEVEL_NAME_CONF,
-                                               strlen(MEDIUM_LEVEL_NAME_CONF) + 1)) {
-                               error = set_memcg_conf_threshold(percent, temp, MEM_LEVEL_MEDIUM, result->value);
-                       }
-                       else if (!strncmp(result->name, LOW_LEVEL_NAME_CONF,
-                                               strlen(LOW_LEVEL_NAME_CONF) + 1)) {
-                               error = set_memcg_conf_threshold(percent, temp, MEM_LEVEL_LOW, result->value);
-                       }
-                       else if (!strncmp(result->name, CRITICAL_LEVEL_NAME_CONF,
-                                               strlen(CRITICAL_LEVEL_NAME_CONF) + 1)) {
-                               error = set_memcg_conf_threshold(percent, temp, MEM_LEVEL_CRITICAL, result->value);
-                       }
-                       else if (!strncmp(result->name, OOM_LEVEL_NAME_CONF,
-                                               strlen(OOM_LEVEL_NAME_CONF) + 1)) {
-                               error = set_memcg_conf_threshold(percent, temp, MEM_LEVEL_OOM, result->value);
-                       }
-                       else {
-                               _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
-                                               result->name, result->value, result->section);
-                       }
-
-                       return error;
-               }
-       }
-       else if (!strncmp(result->section, MEMORY_APP_TYPE_LIMIT_SECTION,
-                               strlen(MEMORY_APP_TYPE_LIMIT_SECTION)+1)) {
-               int error = RESOURCED_ERROR_NONE;
-
-               if (!strncmp(result->name, SERVICE_PER_APP_LIMIT_ACTION_NAME_CONF,
-                                       strlen(SERVICE_PER_APP_LIMIT_ACTION_NAME_CONF) + 1)) {
-                       error = set_mem_action_conf(&memcg_conf->service, result->value);
-               }
-               else if (!strncmp(result->name, WIDGET_PER_APP_LIMIT_ACTION_NAME_CONF,
-                                       strlen(WIDGET_PER_APP_LIMIT_ACTION_NAME_CONF) + 1)) {
-                       error = set_mem_action_conf(&memcg_conf->widget, result->value);
-               }
-               else if (!strncmp(result->name, GUI_PER_APP_LIMIT_ACTION_NAME_CONF,
-                                       strlen(GUI_PER_APP_LIMIT_ACTION_NAME_CONF) + 1)) {
-                       error = set_mem_action_conf(&memcg_conf->guiapp, result->value);
-               }
-               else {
-                       _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
-                                       result->name, result->value, result->section);
-               }
-
-               return error;
-       }
-       else if (!strncmp(result->section, MEMORY_APP_STATUS_LIMIT_SECTION,
-                               strlen(MEMORY_APP_STATUS_LIMIT_SECTION)+1)) {
-               int error = RESOURCED_ERROR_NONE;
-
-               if (!strncmp(result->name, BACKGROUND_PER_APP_LIMIT_ACTION_NAME_CONF,
-                                       strlen(BACKGROUND_PER_APP_LIMIT_ACTION_NAME_CONF) + 1)) {
-                       error = set_mem_action_conf(&memcg_conf->background, result->value);
-               }
-               else {
-                       _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
-                                       result->name, result->value, result->section);
-               }
-
-               return error;
-       }
-       else if (!strncmp(result->section, CPU_THROTTLING_SECTION,
-                               strlen(CPU_THROTTLING_SECTION)+1)) {
-               if (!cpu_throttling_conf->enable)
-                       cpu_throttling_conf->enable = true;
-
-               if (!strncmp(result->name, CPU_SCHED_NAME_CONF,
-                                       strlen(CPU_SCHED_NAME_CONF)+1)) {
-                       cpu_throttling_conf->cpu_sched_info.cpu_sched_type =
-                               config_parse_sched_type(result->value);
-               }
-               else if (!strncmp(result->name, CPU_NICE_NAME_CONF,
-                                       strlen(CPU_NICE_NAME_CONF)+1)) {
-                       cpu_throttling_conf->cpu_sched_info.cpu_nice =
-                               atoi(result->value);
-               }
-               else if (!strncmp(result->name, CPU_SHARE_NAME_CONF,
-                                       strlen(CPU_SHARE_NAME_CONF)+1)) {
-                       cpu_throttling_conf->cpu_cgroup_info.cpu_share =
-                               strtoull(result->value, NULL, 10);
-               }
-               else if (!strncmp(result->name, CPU_CFS_RUN_TIME_NAME_CONF,
-                                       strlen(CPU_CFS_RUN_TIME_NAME_CONF)+1)) {
-                       cpu_throttling_conf->cpu_cgroup_info.cfs_runtime_us =
-                               config_parse_ll_time_us(result->value);
-               }
-               else if (!strncmp(result->name, CPU_CFS_PERIOD_NAME_CONF,
-                                       strlen(CPU_CFS_PERIOD_NAME_CONF)+1)) {
-                       cpu_throttling_conf->cpu_cgroup_info.cfs_period_us =
-                               config_parse_ull_time_us(result->value);
-               }
-               else {
-                       _E("[CONFIG] Unknown configuration name (%s) and value (%s) on section (%s)",
-                                       result->name, result->value, result->section);
-               }
-       }
-       else {
-               _E("[CONFIG] Unknown section name (%s) and value (%s) on section (%s)",
-                               result->name, result->value, result->section);
-       }
-
-       return RESOURCED_ERROR_NONE;
-}
-
-static int vendor_config(struct parse_result *result, void *user_data)
-{
-       int *config_type = (int *)user_data;
-       static struct proc_conf_info *pci = NULL;
-
-       if (!result || !user_data)
-               return RESOURCED_ERROR_INVALID_PARAMETER;
-
-       if (strncmp(result->section, PRIVATE_SECTION, strlen(PRIVATE_SECTION)+1)) {
-               if (strncmp(result->section, OLD_VIP_GROUP_SECTION, strlen(OLD_VIP_GROUP_SECTION)+1)) {
-                       return RESOURCED_ERROR_NONE;
-               }
-       }
-
-       /* common(App or Service or Process) */
-       if (!strncmp(result->name, APP_NAME_CONF, strlen(APP_NAME_CONF)+1)                 ||
-               !strncmp(result->name, SERVICE_NAME_CONF, strlen(SERVICE_NAME_CONF)+1)         ||
-           !strncmp(result->name, OLD_SERVICE_NAME_CONF, strlen(OLD_SERVICE_NAME_CONF)+1) ||
-               !strncmp(result->name, PROCESS_NAME_CONF, strlen(PROCESS_NAME_CONF)+1)         ||
-               !strncmp(result->name, OLD_PROCESS_NAME_CONF, strlen(OLD_PROCESS_NAME_CONF)+1)) {
-               pci = fixed_app_and_service_exist_check(result->value,
-                               result->name[0] == 'A' ? APP_TYPE :
-                               result->name[0] == 'S' ? SERVICE_TYPE : PROCESS_TYPE);
-               if (pci == NULL) {
-                       pci = (struct proc_conf_info *)calloc(1, sizeof(struct proc_conf_info));
-                       if (pci == NULL) {
-                               _E("Failed to allocate memory during parsing vendor configurations");
-                               return RESOURCED_ERROR_OUT_OF_MEMORY;
-                       }
-                       pci->cpu_sched_info.cpu_sched_type = CPU_SCHED_NONE;
-                       pci->cpu_sched_info.cpu_rt_priority = CPU_INIT_PRIO;
-                       pci->cpu_sched_info.cpu_nice = CPU_INIT_NICE;
-                       pci->watchdog_action = PROC_ACTION_KILL;
-                       pci->fail_action = PROC_ACTION_IGNORE;
-                       pci->cpu_boosting_level = CPU_BOOSTING_LEVEL_NONE;
-                       strncpy(pci->name, result->value, sizeof(pci->name)-1);
-
-                       if (result->name[0] == 'A')
-                               fixed_app_list_insert(pci);
-                       else if (result->name[0] == 'S')
-                               fixed_service_list_insert(pci);
-                       else
-                               fixed_process_list_insert(pci);
-               }
-       }
-       /* limiter.conf.d */
-/*     else if (!strncmp(result->name, MEM_CGROUP_NAME_CONF, strlen(MEM_CGROUP_NAME_CONF)+1) &&
-                       *config_type == LIMITER_CONFIG) {
-               if (!pci) {
-                       _E("process configuration information pointer should not be NULL");
-                       return RESOURCED_ERROR_FAIL;
-               }
-
-               if (!strncmp(result->value, CGROUP_HIGH_VALUE_CONF,
-                       strlen(CGROUP_HIGH_VALUE_CONF) +1)) {
-                       pci->mem_type = MEMCG_HIGH;
-               }
-               else if (!strncmp(result->value, CGROUP_MEDIUM_VALUE_CONF,
-                       strlen(CGROUP_MEDIUM_VALUE_CONF) +1)) {
-                       pci->mem_type = MEMCG_MEDIUM;
-               }
-               else if (!strncmp(result->value, CGROUP_LOW_VALUE_CONF,
-                       strlen(CGROUP_LOW_VALUE_CONF) +1)) {
-                       pci->mem_type = MEMCG_LOW;
-               }
-               else {
-                       _E("invalid parameter (%s)", result->value);
-                       return RESOURCED_ERROR_INVALID_PARAMETER;
-               }
-       }*/
-       else if (!strncmp(result->name, MEM_LIMIT_ACTION_NAME_CONF,
-               strlen(MEM_LIMIT_ACTION_NAME_CONF)+1) && *config_type == LIMITER_CONFIG) {
-               int error;
-
-               if (!pci) {
-                       _E("process configuration information pointer should not be NULL");
-                       return RESOURCED_ERROR_FAIL;
-               }
-
-               error = set_mem_action_conf(&pci->mem_action, result->value);
-               return error;
-       }
-       else if (!strncmp(result->name, MEMORY_THROTTLING_NAME_CONF,
-               strlen(MEMORY_THROTTLING_NAME_CONF)+1) && *config_type == LIMITER_CONFIG) {
-
-               if (!pci) {
-                       _E("process configuration information pointer should not be NULL");
-                       return RESOURCED_ERROR_FAIL;
-               }
-
-               /* Enable throttling of a service */
-               pci->memory_throttling_enable = config_parse_bool(result->value);
-       }
-       else if (!strncmp(result->name, CPU_THROTTLING_NAME_CONF,
-               strlen(CPU_THROTTLING_NAME_CONF)+1) && *config_type == LIMITER_CONFIG) {
-
-               if (!pci) {
-                       _E("process configuration information pointer should not be NULL");
-                       return RESOURCED_ERROR_FAIL;
-               }
-
-               /* Enable throttling of an app (or a service) */
-               pci->cpu_throttling_enable = config_parse_bool(result->value);
-       }
-       /* optimizer.conf.d */
-       else if (!strncmp(result->name, CPU_SCHED_NAME_CONF, strlen(CPU_SCHED_NAME_CONF)+1) &&
-                       *config_type == OPTIMIZER_CONFIG) {
-               if (!pci) {
-                       _E("process configuration information pointer should not be NULL");
-                       return RESOURCED_ERROR_FAIL;
-               }
-
-               pci->cpu_sched_info.cpu_sched_type = config_parse_sched_type(result->value);
-
-       }
-       else if (!strncmp(result->name, CPU_NICE_NAME_CONF,
-                               strlen(CPU_NICE_NAME_CONF)+1) && *config_type == OPTIMIZER_CONFIG) {
-               if (!pci) {
-                       _E("process configuration information pointer should not be NULL");
-                       return RESOURCED_ERROR_FAIL;
-               }
-
-               pci->cpu_sched_info.cpu_nice = atoi(result->value);
-       }
-       else if (!strncmp(result->name, CPU_RT_PRIORITY_NAME_CONF,
-                               strlen(CPU_RT_PRIORITY_NAME_CONF)+1) && *config_type == OPTIMIZER_CONFIG) {
-               if (!pci) {
-                       _E("process configuration information pointer should not be NULL");
-                       return RESOURCED_ERROR_FAIL;
-               }
-
-               pci->cpu_sched_info.cpu_rt_priority = atoi(result->value);
-       }
-       else if (!strncmp(result->name, CPU_BOOSTING_LEVEL_NAME_CONF,
-                               strlen(CPU_BOOSTING_LEVEL_NAME_CONF)+1) && *config_type == OPTIMIZER_CONFIG) {
-               if (!pci) {
-                       _E("process configuration information pointer should not be NULL");
-                       return RESOURCED_ERROR_FAIL;
-               }
-
-               pci->cpu_boosting_level = config_parse_boosting_level(result->value);
-       }
-/*     else if (!strncmp(result->name, CPU_RT_RUN_TIME_NAME_CONF,
-                               strlen(CPU_RT_RUN_TIME_NAME_CONF)+1) &&
-                       *config_type == OPTIMIZER_CONFIG) {
-               if (!pci) {
-                       _E("process configuration information pointer should not be NULL");
-                       return RESOURCED_ERROR_FAIL;
-               }
-               pci->cpu_sched_info.rt_runtime_us = config_parse_time_us(result->value);
-       }
-       else if (!strncmp(result->name, CPU_RT_PERIOD_NAME_CONF,
-                               strlen(CPU_RT_PERIOD_NAME_CONF)+1) &&
-                       *config_type == OPTIMIZER_CONFIG) {
-               if (!pci) {
-                       _E("process configuration information pointer should not be NULL");
-                       return RESOURCED_ERROR_FAIL;
-               }
-               pci->cpu_sched_info.rt_period_us = config_parse_time_us(result->value);
-       }*/
-       else if (!strncmp(result->name, ACTION_ON_FAILURE_NAME_CONF,
-                               strlen(ACTION_ON_FAILURE_NAME_CONF)+1) && *config_type == PROCESS_CONFIG) {
-               if (!pci) {
-                       _E("process configuration information pointer should not be NULL");
-                       return RESOURCED_ERROR_FAIL;
-               }
-
-               if (!strncmp(result->value, ACTION_REBOOT_VALUE_CONF,
-                                       strlen(ACTION_REBOOT_VALUE_CONF) +1)) {
-                       pci->fail_action = PROC_ACTION_REBOOT;
-               }
-               else {
-                       _E("invalid parameter (%s)", result->value);
-                       return RESOURCED_ERROR_INVALID_PARAMETER;
-               }
-       }
-       else if (!strncmp(result->name, WATCHDOG_ACTION_NAME_CONF,
-                               strlen(WATCHDOG_ACTION_NAME_CONF)+1) && *config_type == PROCESS_CONFIG) {
-               if (!pci) {
-                       _E("process configuration information pointer should not be NULL");
-                       return RESOURCED_ERROR_FAIL;
-               }
-
-               if (!strncmp(result->value, ACTION_IGNORE_VALUE_CONF,
-                                       strlen(ACTION_IGNORE_VALUE_CONF) +1)) {
-                       pci->watchdog_action = PROC_ACTION_IGNORE;
-               }
-               else if (!strncmp(result->value, ACTION_KILL_VALUE_CONF,
-                                       strlen(ACTION_KILL_VALUE_CONF) +1)) {
-                       pci->watchdog_action = PROC_ACTION_KILL;
-               }
-               else {
-                       _E("invalid parameter (%s)", result->value);
-                       return RESOURCED_ERROR_INVALID_PARAMETER;
-               }
-       }
-       /* old style */
-       else if (!strncmp(result->name, OLD_ACTION_ON_FAILURE_NAME_CONF,
-                               strlen(OLD_ACTION_ON_FAILURE_NAME_CONF)+1) && *config_type == VIP_CONFIG) {
-               if (!pci) {
-                       _E("process configuration information pointer should not be NULL");
-                       return RESOURCED_ERROR_FAIL;
-               }
-
-               if (!strncmp(result->value, ACTION_REBOOT_VALUE_CONF,
-                                       strlen(ACTION_REBOOT_VALUE_CONF) +1)) {
-                       pci->fail_action = PROC_ACTION_REBOOT;
-               }
-               else {
-                       _E("invalid parameter (%s)", result->value);
-                       return RESOURCED_ERROR_INVALID_PARAMETER;
-               }
-       }
-       else {
-               _E("Unknown configuration name (%s) and value (%s) on section (%s)",
-                               result->name, result->value, result->section);
-       }
-
-       return RESOURCED_ERROR_NONE;
-}
-
-static void load_per_vendor_configs(const char *dir, int func(struct parse_result *result,
-                                                               void *user_data), void *user_data)
-{
-       int count;
-       int idx;
-       struct dirent **namelist;
-
-       if ((count = scandir(dir, &namelist, NULL, alphasort)) == -1) {
-               _I("(%s) conf dir does not exist", dir);
-               return;
-       }
-
-       for (idx = 0; idx < count; idx++) {
-               char path[PATH_MAX] = {0, };
-
-               if (!strstr(namelist[idx]->d_name, CONF_FILE_SUFFIX))
-                       continue;
-
-               snprintf(path, sizeof(path), "%s/%s", dir, namelist[idx]->d_name);
-               config_parse(path, func, user_data);
-               free(namelist[idx]);
-       }
-
-       free(namelist);
-}
-
-void resourced_parse_vendor_configs(void)
-{
-       int config_type;
-
-       fixed_app_and_service_list_init();
-
-       /* Load configurations in limiter.conf and limiter.conf.d/ */
-       config_parse(LIMITER_CONF_FILE, limiter_config, NULL);
-       config_type = LIMITER_CONFIG;
-       load_per_vendor_configs(LIMITER_CONF_DIR, vendor_config, &config_type);
-
-       /* Load configurations in optimizer.conf and optimizer.conf.d */
-       config_parse(OPTIMIZER_CONF_FILE, optimizer_config, NULL);
-       config_type = OPTIMIZER_CONFIG;
-       load_per_vendor_configs(OPTIMIZER_CONF_DIR, vendor_config, &config_type);
-
-       /* Load configuration in process.conf */
-       config_type = PROCESS_CONFIG;
-       load_per_vendor_configs(PROC_CONF_DIR, vendor_config, &config_type);
-
-       /* old style */
-       config_type = VIP_CONFIG;
-       load_per_vendor_configs(VIP_CONF_DIR, vendor_config, &config_type);
-}
-
-void resourced_free_vendor_configs(void)
-{
-       fixed_app_and_service_list_exit();
-}
-
-int config_parse(const char *file_name, int cb(struct parse_result *result,
-                       void *user_data), void *user_data)
-{
-       FILE *f = NULL;
-       struct parse_result result;
-       /* use stack for parsing */
-       char line[LINE_MAX];
-       char section[MAX_SECTION];
-       char *start, *end, *name, *value;
-       int lineno = 0, ret = 0;
-
-       if (!file_name || !cb) {
-               ret = -EINVAL;
-               goto error;
-       }
-
-       /* open conf file */
-       f = fopen(file_name, "r");
-       if (!f) {
-               _E("Failed to open file %s", file_name);
-               ret = -EIO;
-               goto error;
-       }
-
-       /* parsing line by line */
-       while (fgets(line, LINE_MAX, f) != NULL) {
-               lineno++;
-
-               start = line;
-               truncate_nl(start);
-               start = strstrip(start);
-
-               if (*start == COMMENT) {
-                       continue;
-               } else if (*start == '[') {
-                       /* parse section */
-                       end = strchr(start, ']');
-                       if (!end || *end != ']') {
-                               ret = -EBADMSG;
-                               goto error;
-                       }
-
-                       *end = '\0';
-                       strncpy(section, start + 1, sizeof(section)-1);
-                       section[MAX_SECTION-1] = '\0';
-               } else if (*start) {
-                       /* parse name & value */
-                       end = strchr(start, '=');
-                       if (!end || *end != '=') {
-                               ret = -EBADMSG;
-                               goto error;
-                       }
-                       *end = '\0';
-                       name = strstrip(start);
-                       value = strstrip(end + 1);
-                       end = strchr(value, COMMENT);
-                       if (end && *end == COMMENT) {
-                               *end = '\0';
-                               value = strstrip(value);
-                       }
-
-                       result.section = section;
-                       result.name = name;
-                       result.value = value;
-                       /* callback with parse result */
-                       ret = cb(&result, user_data);
-                       if (ret < 0) {
-                               ret = -EBADMSG;
-                               goto error;
-                       }
-               }
-       }
-       _D("Success to load %s", file_name);
-       fclose(f);
-       return 0;
-
-error:
-       if (f)
-               fclose(f);
-       _E("Failed to read %s:%d!", file_name, lineno);
-       return ret;
-}
diff --git a/src/common/config-parser.h b/src/common/config-parser.h
deleted file mode 100644 (file)
index 66787d7..0000000
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * resourced
- *
- * Copyright (c) 2013 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#ifndef __CONFIG_PARSER_H__
-#define __CONFIG_PARSER_H__
-
-#include <stdio.h>
-#include <stdbool.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
-#define CONF_FILE_SUFFIX                    ".conf"
-
-#define LIMITER_CONF_FILE                   RD_CONFIG_FILE(limiter)
-#define OPTIMIZER_CONF_FILE                 RD_CONFIG_FILE(optimizer)
-#define LIMITER_CONF_DIR                    RD_CONFIG_PATH"/limiter.conf.d"
-#define OPTIMIZER_CONF_DIR                  RD_CONFIG_PATH"/optimizer.conf.d"
-#define PROC_CONF_DIR                       RD_CONFIG_PATH"/process.conf.d"
-/* old style */
-#define VIP_CONF_DIR                        RD_CONFIG_PATH"/vip-process.d"
-
-/* section name */
-/* limiter.conf */
-#define        PRIVATE_SECTION                     "Private"
-#define MEMORY_LEVEL_THRESHOLD_SECTION      "MemoryLevelThreshold"
-#define MEMORY_APP_TYPE_LIMIT_SECTION       "MemoryAppTypeLimit"
-#define MEMORY_APP_STATUS_LIMIT_SECTION     "MemoryAppStatusLimit"
-#define MEMORY_THROTTLING_SECTION           "MemoryThrottling"
-#define CPU_THROTTLING_SECTION              "CpuThrottling"
-#define OLD_VIP_GROUP_SECTION               "VIP_GROUP"
-
-/* optimizer.conf */
-#define SWAP_SECTION                        "MemorySwap"
-#define ZRAM_SECTION                        "MemoryZram"
-#define ZSWAP_SECTION                       "MemoryZswap"
-#define DEDUP_SECTION                       "MemoryDedup"
-#define KSM_SECTION                         "MemoryKsm"
-#define COMPACTION_SECTION                  "MemoryCompaction"
-#define CPU_SCHED_SECTION                   "CpuSched"
-#define CPU_AFFINITY_SECTION                "CpuAffinity"
-#define CPU_BOOSTING_LEVEL_STRONG_SECTION   "CpuBoostingLevelStrong"
-#define CPU_BOOSTING_LEVEL_MEDIUM_SECTION   "CpuBoostingLevelMedium"
-#define CPU_BOOSTING_LEVEL_WEAK_SECTION     "CpuBoostingLevelWeak"
-
-/* configuration name */
-/* limiter.conf */
-#define APP_NAME_CONF                                "App"
-#define SERVICE_NAME_CONF                            "Service"
-#define OLD_SERVICE_NAME_CONF                        "SERVICE"  /* old style */
-#define PROCESS_NAME_CONF                            "Process"
-#define OLD_PROCESS_NAME_CONF                        "PROCESS" /* old style */
-#define MEM_CGROUP_NAME_CONF                         "MemGroup"
-#define MEM_LIMIT_ACTION_NAME_CONF                   "MemLimitAction"
-#define ACTION_ON_FAILURE_NAME_CONF                  "ActionOnFailure"
-#define OLD_ACTION_ON_FAILURE_NAME_CONF              "ACTION_ON_FAILURE"
-#define        WATCHDOG_ACTION_NAME_CONF                    "WatchdogAction"
-#define THROTTLING_LIMIT_NAME_CONF                   "ThrottlingLimit"
-#define MEDIUM_LEVEL_NAME_CONF                       "MediumLevel"
-#define LOW_LEVEL_NAME_CONF                          "LowLevel"
-#define CRITICAL_LEVEL_NAME_CONF                     "CriticalLevel"
-#define OOM_LEVEL_NAME_CONF                          "OomLevel"
-#define OOM_POPUP_NAME_CONF                          "OomPopup"
-#define SERVICE_PER_APP_LIMIT_ACTION_NAME_CONF       "ServicePerAppLimitAction"
-#define WIDGET_PER_APP_LIMIT_ACTION_NAME_CONF        "WidgetPerAppLimitAction"
-#define GUI_PER_APP_LIMIT_ACTION_NAME_CONF           "GUIPerAppLimitAction"
-#define BACKGROUND_PER_APP_LIMIT_ACTION_NAME_CONF    "BackgroundPerAppLimitAction"
-
-/* CPU specific configuration name */
-#define CPU_SCHED_NAME_CONF                          "CpuSched"
-#define CPU_NICE_NAME_CONF                           "CpuNice"
-#define CPU_SHARE_NAME_CONF                          "CpuShare"
-#define CPU_RT_PRIORITY_NAME_CONF                    "CpuRTPriority"
-#define CPU_SCHED_FEATURE_NAME_CONF                  "CpuSchedFeature"
-#define CPU_RT_RUN_TIME_NAME_CONF                    "CpuRTRuntime"
-#define CPU_RT_PERIOD_NAME_CONF                      "CpuRTPeriod"
-#define CPU_CFS_RUN_TIME_NAME_CONF                   "CpuCFSRuntime"
-#define CPU_CFS_PERIOD_NAME_CONF                     "CpuCFSPeriod"
-#define CPU_BOOSTING_LEVEL_NAME_CONF                 "CpuBoostingLevel"
-#define MEMORY_THROTTLING_NAME_CONF                  "MemoryThrottling"
-#define CPU_THROTTLING_NAME_CONF                     "CpuThrottling"
-
-/* optimizer.conf */
-#define        SWAP_ENABLE_NAME_CONF                        "SwapEnable"
-#define RECLAIM_AT_BOOT_NAME_CONF                    "ReclaimAtBoot"
-#define SWAP_TYPE_NAME_CONF                          "SwapType"
-#define THROTTLING_SWAPPINESS_NAME_CONF              "ThrottlingSwappiness"
-#define COMP_ALGORITHM_NAME_CONF                     "CompAlgorithm"
-#define ZRAM_RATIO_NAME_CONF                         "ZramRatio"
-#define POOL_RATIO_NAME_CONF                         "PoolRatio"
-#define POOL_TYPE_NAME_CONF                          "PoolType"
-#define        DEDUP_ENABLE_NAME_CONF                       "DedupEnable"
-#define DEDUP_AT_BOOT_NAME_CONF                      "DedupAtBoot"
-#define        SCAN_ON_LOWMEM_NAME_CONF                     "ScanOnLowmem"
-#define KSM_MODE_NAME_CONF                           "KsmMode"
-#define        PAGES_TO_SCAN_NAME_CONF                      "PagesToScan"
-#define PAGES_TO_SCAN_WITH_BOOST_NAME_CONF           "PagesToScanWithBoost"
-#define        COMPACTION_ENABLE_NAME_CONF                  "CompactionEnable"
-#define FRAG_LEVEL_NAME_CONF                         "FragLevel"
-#define FOREGROUND_APPS_NAME_CONF                    "ForegroundApps"
-
-/* configuration value */
-#define CGROUP_LOW_VALUE_CONF                        "lowest"
-#define ACTION_BROADCAST_VALUE_CONF                  "broadcast"
-#define ACTION_RECLAIM_VALUE_CONF                    "reclaim"
-#define ACTION_KILL_VALUE_CONF                       "kill"
-#define ACTION_REBOOT_VALUE_CONF                     "reboot"
-#define ACTION_IGNORE_VALUE_CONF                     "ignore"
-
-/* CPU specific configuration name */
-#define RT_RUNTIME_SHARE_VALUE_CONF                  "rt_runtime_share"
-#define NO_RT_RUNTIME_SHARE_VALUE_CONF               "no_rt_runtime_share"
-#define CPU_SCHED_DEADLINE_VALUE_CONF                "deadline"
-#define CPU_SCHED_FIFO_VALUE_CONF                    "fifo"
-#define CPU_SCHED_RR_VALUE_CONF                      "rr"
-#define CPU_SCHED_OTHER_VALUE_CONF                   "other"
-#define CPU_SCHED_IDLE_VALUE_CONF                    "idle"
-#define CPU_SCHED_BATCH_VALUE_CONF                   "batch"
-#define CPU_BOOSTING_LEVEL_STRONG_VALUE_CONF         "strong"
-#define CPU_BOOSTING_LEVEL_MEDIUM_VALUE_CONF         "medium"
-#define CPU_BOOSTING_LEVEL_WEAK_VALUE_CONF           "weak"
-
-#define MATCH(a, b)    (!strncmp(a, b, strlen(a) + 1) ? 1 : 0)
-#define SET_CONF(a, b) (a = (b > 0.0 ? b : a))
-
-enum config_type {
-       LIMITER_CONFIG,
-       OPTIMIZER_CONFIG,
-       MONITOR_CONFIG,
-       PROCESS_CONFIG,
-       VIP_CONFIG, /* old style */
-};
-
-struct parse_result {
-       char *section;
-       char *name;
-       char *value;
-};
-
-/**
- * @brief Parse config file and call callback\n
- * @param[in] file_name conf file.
- * @param[in] cb cb is called when conf file is parsed line by line.
- * @param[in] user_data user data is passed to cb.
- * @return 0 on success, negative if failed
- */
-int config_parse(const char *file_name, int cb(struct parse_result *result,
-                       void *user_data), void *user_data);
-
-/* Prototype for a parser for a specific configuration setting */
-typedef int (*ConfigParserCallback)(
-               const char *filename,
-               unsigned line,
-               const char *section,
-               const char *lvalue,
-               int ltype,
-               const char *rvalue,
-               void *data);
-
-typedef int (*ConfigParseFunc)(const char *path, void *data);
-
-/* Wraps information for parsing a specific configuration variable, to
- * be stored in a simple array */
-typedef struct ConfigTableItem {
-       const char *section;            /* Section */
-       const char *lvalue;             /* Name of the variable */
-       ConfigParserCallback cb;        /* Function that is called to
-                                        * parse the variable's
-                                        * value */
-       int ltype;                      /* Distinguish different
-                                        * variables passed to the
-                                        * same callback */
-       void *data;                     /* Where to store the
-                                        * variable's data */
-} ConfigTableItem;
-
-void remove_app_conf_info_list(void);
-void remove_service_conf_info_list(void);
-GSList *get_app_conf_info_list(void);
-GSList *get_service_conf_info_list(void);
-void resourced_parse_vendor_configs(void);
-void resourced_free_vendor_configs(void);
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif
diff --git a/src/common/config.h.in b/src/common/config.h.in
deleted file mode 100644 (file)
index 15d12d1..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef _CONFIG_H_GENERATED
-#define _CONFIG_H_GENERATED
-
-#cmakedefine EXCLUDE_LIST_RO_PATH "@EXCLUDE_LIST_RO_PATH@"
-#cmakedefine EXCLUDE_LIST_RW_PATH "@EXCLUDE_LIST_RW_PATH@"
-/* It's command line arguments*/
-
-#cmakedefine CONFIG_DATAUSAGE_NFACCT @CONFIG_DATAUSAGE_NFACCT@
-#cmakedefine TETHERING_FEATURE  @TETHERING_FEATURE@
-
-#endif /* _CONFIG_H_GENERATED*/
diff --git a/src/common/cpu-common.c b/src/common/cpu-common.c
deleted file mode 100644 (file)
index f264360..0000000
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * resourced
- *
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "macro.h"
-#include "cpu-common.h"
-#include "trace.h"
-#include "resourced.h"
-
-static struct cpu_sched_conf *cpu_sched_conf = NULL;
-static struct cpu_affinity_conf *cpu_affinity_conf = NULL;
-static struct cpu_throttling_conf *cpu_throttling_conf = NULL;
-static struct cpu_boosting_conf *cpu_boosting_conf[CPU_BOOSTING_LEVEL_END] = {NULL, };
-
-struct cpu_sched_conf *get_cpu_sched_conf(void)
-{
-       if (!cpu_sched_conf) {
-               cpu_sched_conf = (struct cpu_sched_conf *)calloc(1, sizeof (struct cpu_sched_conf));
-               if (!cpu_sched_conf) {
-                       _E("Failed to alloc memory for cpu scheduler configuration");
-                       return NULL;
-               }
-               else {
-                       cpu_sched_conf->cpu_sched_flag = CPU_SCHED_UNINITIALIZED;
-                       cpu_sched_conf->cpu_cgroup_info.rt_runtime_us = 0;
-                       cpu_sched_conf->cpu_cgroup_info.rt_period_us = 0;
-               }
-       }
-
-       return cpu_sched_conf;
-}
-
-void free_cpu_sched_conf(void)
-{
-       if (cpu_sched_conf)
-               free(cpu_sched_conf);
-}
-
-char *get_cpu_affinity_conf_name(void)
-{
-       if (cpu_affinity_conf)
-               return cpu_affinity_conf->cpuset_cgroup_info.name;
-       else
-               return NULL;
-}
-
-char *get_cpu_affinity_conf_value(void)
-{
-       if (cpu_affinity_conf)
-               return cpu_affinity_conf->cpuset_cgroup_info.value;
-       else
-               return NULL;
-}
-
-int set_cpu_affinity_conf(const char *name, const char *value)
-{
-       if (!cpu_affinity_conf) {
-               cpu_affinity_conf = (struct cpu_affinity_conf *)calloc(1, sizeof (struct cpu_affinity_conf));
-               if (!cpu_affinity_conf) {
-                       _E("Failed to alloc memory for cpu affinity configuration");
-                       return RESOURCED_ERROR_OUT_OF_MEMORY;
-               }
-       }
-
-       if (strlen(name) + 1 > sizeof(cpu_affinity_conf->cpuset_cgroup_info.name)) {
-               _E("Size of cpu configuration for name is not enough");
-               return RESOURCED_ERROR_OUT_OF_MEMORY;
-       }
-       strncpy(cpu_affinity_conf->cpuset_cgroup_info.name, name, sizeof(cpu_affinity_conf->cpuset_cgroup_info.name) - 1);
-
-       if (strlen(value) + 1 > sizeof(cpu_affinity_conf->cpuset_cgroup_info.value)) {
-               _E("Size of cpu configuration for value is not enough");
-               return RESOURCED_ERROR_OUT_OF_MEMORY;
-       }
-       strncpy(cpu_affinity_conf->cpuset_cgroup_info.value, value, sizeof(cpu_affinity_conf->cpuset_cgroup_info.value) - 1);
-
-       return RESOURCED_ERROR_NONE;
-}
-
-void free_cpu_affinity_conf(void)
-{
-       if (cpu_affinity_conf)
-               free(cpu_affinity_conf);
-}
-
-struct cpu_throttling_conf *get_cpu_throttling_conf(void)
-{
-       if (!cpu_throttling_conf) {
-               cpu_throttling_conf = (struct cpu_throttling_conf *)calloc(1, sizeof (struct cpu_throttling_conf));
-               if (!cpu_throttling_conf) {
-                       _E("Failed to alloc memory for cpu throttling configuration");
-                       return NULL;
-               }
-               else {
-                       cpu_throttling_conf->enable = false;
-                       cpu_throttling_conf->cpu_sched_info.cpu_sched_type = CPU_SCHED_NONE;
-                       cpu_throttling_conf->cpu_sched_info.cpu_nice = CPU_INIT_NICE;
-                       cpu_throttling_conf->cpu_cgroup_info.cfs_runtime_us = 0;
-                       cpu_throttling_conf->cpu_cgroup_info.cfs_period_us = 0;
-                       cpu_throttling_conf->cpu_cgroup_info.cpu_share = 0;
-               }
-       }
-
-       return cpu_throttling_conf;
-}
-
-void free_cpu_throttling_conf(void)
-{
-       if (cpu_throttling_conf)
-               free(cpu_throttling_conf);
-}
-
-struct cpu_boosting_conf *get_cpu_boosting_conf(cpu_boosting_level_e level)
-{
-       if (!cpu_boosting_conf[level]) {
-               cpu_boosting_conf[level] = (struct cpu_boosting_conf *)
-                       calloc(1, sizeof (struct cpu_boosting_conf));
-
-               if (!cpu_boosting_conf[level]) {
-                       _E("Failed to alloc memory for cpu boosting (level = %d) configuration", level);
-                       return NULL;
-               }
-               else {
-                       cpu_boosting_conf[level]->enable = false;
-                       cpu_boosting_conf[level]->cpu_sched_info.cpu_sched_type = CPU_SCHED_NONE;
-                       cpu_boosting_conf[level]->cpu_sched_info.cpu_nice = CPU_INIT_NICE;
-                       cpu_boosting_conf[level]->cpu_sched_info.cpu_rt_priority = CPU_INIT_PRIO;
-               }
-       }
-
-       return cpu_boosting_conf[level];
-}
-
-void free_cpu_boosting_conf(cpu_boosting_level_e level)
-{
-       if (cpu_boosting_conf[level])
-               free(cpu_boosting_conf[level]);
-}
diff --git a/src/common/cpu-common.h b/src/common/cpu-common.h
deleted file mode 100644 (file)
index bd549b8..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-#ifndef __CPU_COMMON_H__
-#define __CPU_COMMON_H__
-
-#include <stdbool.h>
-
-#include <cpu-boosting-type.h>
-#include <cpu-boosting-private.h>
-
-#include "util.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-#define CPU_INIT_NICE         100
-#define CPU_MAX_NICE          19
-#define CPU_MIN_NICE          -20
-#define CPU_DEFAULT_NICE      0
-
-#define CPU_INIT_PRIO         0
-#define CPU_MAX_PRIO          99
-#define CPU_MIN_PRIO          1
-
-#define CPU_DEFAULT_SHARE     1024
-#define CPU_THROTTLING_SHARE  64
-
-enum cpu_sched_flag {
-       CPU_SCHED_UNINITIALIZED = 0,
-       CPU_SCHED_RUNTIME_SHARE = 1,
-       CPU_SCHED_NO_RUNTIME_SHARE = 2,
-       CPU_SCHED_RUNTIME_GREED = 4,
-};
-
-enum cpu_sched_type {
-       CPU_SCHED_NONE = 0,
-       CPU_SCHED_IDLE = 1,
-       CPU_SCHED_BATCH,
-       CPU_SCHED_OTHER,
-       CPU_SCHED_FIFO,
-       CPU_SCHED_RR,
-       CPU_SCHED_DEADLINE,
-};
-
-struct cpu_boosting_info {
-       pid_t tid;
-       int level;                     /* current boosting level */
-       guint gsource_id;              /* timer id */
-};
-
-struct cpu_boosting_input {
-       cpu_boosting_input_t client_input;
-       int sock;
-       guint *gsource_id;
-       bool remove_input;
-};
-
-struct cpu_sched_info {
-       enum cpu_sched_type cpu_sched_type;
-       int cpu_nice;                        /* fixed cpu nice */
-       int cpu_rt_priority;                 /* fixed cpu priority for rt schedulers */
-};
-
-struct cpuset_cgroup_info {
-       char name[64];
-       char value[64];
-};
-
-struct cpu_cgroup_info {
-       long long cfs_runtime_us;
-       long long rt_runtime_us;
-       unsigned long long cfs_period_us;
-       unsigned long long rt_period_us;
-       unsigned long long cpu_share;
-};
-
-struct cpu_sched_conf {
-       enum cpu_sched_flag cpu_sched_flag;
-       struct cpu_cgroup_info cpu_cgroup_info;
-};
-
-struct cpu_affinity_conf {
-       struct cpuset_cgroup_info cpuset_cgroup_info;
-};
-
-struct cpu_throttling_conf {
-       bool enable;
-       struct cpu_sched_info cpu_sched_info;
-       struct cpu_cgroup_info cpu_cgroup_info;
-};
-
-struct cpu_boosting_conf {
-       bool enable;
-       struct cpu_sched_info cpu_sched_info;
-};
-
-struct cpu_sched_conf *get_cpu_sched_conf(void);
-void free_cpu_sched_conf(void);
-
-char *get_cpu_affinity_conf_name(void);
-char *get_cpu_affinity_conf_value(void);
-int set_cpu_affinity_conf(const char *name, const char *value);
-void free_cpu_affinity_conf(void);
-
-struct cpu_throttling_conf *get_cpu_throttling_conf(void);
-void free_cpu_throttling_conf(void);
-
-struct cpu_boosting_conf *get_cpu_boosting_conf(cpu_boosting_level_e level);
-void free_cpu_boosting_conf(cpu_boosting_level_e level);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __CPU_COMMON_H__ */
diff --git a/src/common/dbus-handler.c b/src/common/dbus-handler.c
deleted file mode 100644 (file)
index cc80344..0000000
+++ /dev/null
@@ -1,448 +0,0 @@
-/*
- * resourced
- *
- * Copyright (c) 2000 - 2019 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-/*
- * @file dbus-handler.c
- *
- * @desc dbus handler using libdbus
- *
- */
-
-#include <glib.h>
-#include <gio/gio.h>
-#include <stdint.h>
-
-#include "trace.h"
-#include "dbus-handler.h"
-#include "macro.h"
-#include "resourced.h"
-#include "util.h"
-#include "fd-handler.h"
-
-static guint owner_id;
-static GList *dbus_signal_list;
-static GList *dbus_method_handle_list;
-
-GDBusConnection *d_bus_get_connection(void)
-{
-       static GDBusConnection *g_dbus_conn = NULL;
-
-       if (g_dbus_conn)
-               return g_dbus_conn;
-
-       g_dbus_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL);
-       g_assert(g_dbus_conn);
-
-       g_dbus_connection_set_exit_on_close(g_dbus_conn, FALSE);
-       return g_dbus_conn;
-}
-
-static struct d_bus_signal *d_bus_find_signal(const char *path, const char *interface, const char *name)
-{
-       size_t path_len, interface_len, name_len;
-       GList *iter;
-       struct d_bus_signal *signal;
-
-       path_len = strlen(path) + 1;
-       interface_len = strlen(interface) + 1;
-       name_len = strlen(name) + 1;
-
-       for (iter = dbus_signal_list; iter; iter = g_list_next(iter)) {
-               signal = (struct d_bus_signal *)iter->data;
-               if (strncmp(signal->path, path, path_len))
-                       continue;
-               if (strncmp(signal->interface, interface, interface_len))
-                       continue;
-               if (strncmp(signal->name, name, name_len))
-                       continue;
-               return signal;
-       }
-
-       return NULL;
-}
-
-/* Find appropriate method and call its callback */
-static void d_bus_method_handler(GDBusConnection *connection,
-               const gchar *sender, const gchar *object_path,
-               const gchar *interface_name, const gchar *method_name,
-               GVariant *parameters, GDBusMethodInvocation *invocation,
-               gpointer user_data)
-{
-       int i;
-       struct d_bus_method_handle *handle;
-       int name_len;
-
-       if (!user_data) {
-               _E("There is no handle about received gdbus method");
-               return;
-       }
-       handle = (struct d_bus_method_handle *)user_data;
-
-       name_len = strlen(method_name) + 1;
-       for (i = 0; i < handle->num_methods; i++) {
-               if (strncmp(handle->methods[i].name, method_name, name_len))
-                       continue;
-
-               handle->methods[i].callback(invocation, parameters);
-               break;
-       }
-}
-
-static const GDBusInterfaceVTable vtable = { d_bus_method_handler, NULL, NULL };
-
-static void d_bus_signal_handler(GDBusConnection *connection,
-               const gchar *sender, const gchar *object_path,
-               const gchar *interface_name, const gchar *signal_name,
-               GVariant *parameters, gpointer user_data)
-{
-       struct d_bus_signal *signal = (struct d_bus_signal *)user_data;
-       if (!signal || !signal->callback)
-               return;
-
-       signal->callback(parameters);
-}
-
-struct dbus_int {
-       int *list;
-       int size;
-};
-
-static GVariant *append_variant(const char *sig, char *param[])
-{
-       GVariantBuilder builder;
-       GVariantBuilder *sub_builder;
-       GVariant *var;
-       struct dbus_int *array_int;
-       char *ch;
-       int i, j;
-
-       if (!sig || !param)
-               return NULL;
-
-       g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
-
-       for (ch = (char *)sig, i = 0; *ch != '\0'; ++i, ++ch) {
-               switch (*ch) {
-               case 'i':
-                       g_variant_builder_add(&builder, "i", atoi(param[i]));
-                       break;
-               case 'u':
-                       g_variant_builder_add(&builder, "u", strtoul(param[i], NULL, 10));
-                       break;
-               case 't':
-                       g_variant_builder_add(&builder, "t", atoll(param[i]));
-                       break;
-               case 's':
-                       g_variant_builder_add(&builder, "s", param[i]);
-                       break;
-               case 'a':
-                       ++ch;
-                       switch (*ch) {
-                       case 'i':
-                               sub_builder = g_variant_builder_new(G_VARIANT_TYPE("ai"));
-                               array_int = (struct dbus_int *)param[i];
-                               for (j = 0; j < array_int->size; j++)
-                                       g_variant_builder_add(sub_builder, "i", array_int->list[j]);
-                               var = g_variant_new("ai", sub_builder);
-                               g_variant_builder_unref(sub_builder);
-                               g_variant_builder_add_value(&builder, var);
-                               break;
-                       default:
-                               break;
-                       }
-                       break;
-               default:
-                       return NULL;
-               }
-       }
-
-       return g_variant_builder_end(&builder);
-}
-
-int d_bus_call_method_sync(const char *dest, const char *path,
-               const char *interface, const char *method,
-               const char *sig, char *param[])
-{
-       GVariant *gv = NULL;
-
-       if (sig || param) {
-               gv = append_variant(sig, param);
-               if (!gv) {
-                       _E("Failed to build g_variant");
-                       return -EINVAL;
-               }
-       }
-
-       return d_bus_call_method_sync_gvariant(dest, path, interface, method, gv);
-}
-
-int d_bus_call_method_sync_gvariant(const char *dest, const char *path,
-               const char *interface, const char *method,
-               GVariant *gv)
-{
-       int ret;
-       GVariant *reply = NULL;
-       GError *err = NULL;
-
-       reply = g_dbus_connection_call_sync(d_bus_get_connection(), dest, path,
-                       interface, method, gv, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
-       if (err || !reply) {
-               /* The case where !err && !reply (i.e. reply type mismatch) can't currently happen
-                * because we don't specify the desired reply type, but it's good to be future-proof */
-               _E("Failed to call D-Bus name %s, objpath %s, iface %s, method %s: %s",
-                       dest, path, interface, method, err ? err->message : "reply signature mismatch");
-               if (err)
-                       g_error_free(err);
-               return -ECOMM;
-       }
-
-       do_expr_unless_g_variant_consume_typechecked(return -EINVAL, reply, "(i)", &ret);
-
-       return ret;
-}
-
-int d_bus_call_method_sync_gvariant_with_reply(const char *dest, const char *path,
-               const char *interface, const char *method,
-               GVariant *gv, GVariant **out_reply)
-{
-       GVariant *reply = NULL;
-       GError *err = NULL;
-
-       reply = g_dbus_connection_call_sync(d_bus_get_connection(), dest, path,
-                       interface, method, gv, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
-       if (err || !reply) {
-               /* The case where !err && !reply (i.e. reply type mismatch) can't currently happen
-                * because we don't specify the desired reply type, but it's good to be future-proof */
-               _E("Failed to call D-Bus name %s, objpath %s, iface %s, method %s: %s",
-                       dest, path, interface, method, err ? err->message : "reply signature mismatch");
-               if (err)
-                       g_error_free(err);
-               return -ECOMM;
-       }
-
-       *out_reply = reply;
-
-       return 0;
-}
-
-int d_bus_call_method_async(const char *dest, const char *path,
-               const char *interface, const char *method,
-               const char *sig, char *param[])
-{
-       GVariant *gv = append_variant(sig, param);
-       if (!gv) {
-               _E("Failed to build g_variant");
-               return -EINVAL;
-       }
-       return d_bus_call_method_async_gvariant(dest, path, interface, method, gv);
-}
-
-int d_bus_call_method_async_gvariant(const char *dest, const char *path,
-               const char *interface, const char *method, GVariant *gv)
-{
-       g_dbus_connection_call(d_bus_get_connection(), dest, path, interface, method,
-                       gv, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
-
-       return 0;
-}
-
-resourced_ret_c d_bus_register_signal(const char *path, const char *interface,
-               const char *name, d_bus_signal_callback callback, void *user_data)
-{
-       struct d_bus_signal *signal;
-
-       if (d_bus_find_signal(path, interface, name)) {
-               _E("Same D-Bus signal is already registered");
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       signal = calloc(1, sizeof(struct d_bus_signal));
-       if (!signal) {
-               _E("Not enough memory!");
-               return RESOURCED_ERROR_OUT_OF_MEMORY;
-       }
-
-       signal->path = path;
-       signal->interface = interface;
-       signal->name = name;
-       signal->callback = callback;
-       signal->user_data = user_data;
-
-       signal->subscription_id = g_dbus_connection_signal_subscribe(d_bus_get_connection(),
-                       NULL, interface, name, path, NULL, G_DBUS_SIGNAL_FLAGS_NONE,
-                       d_bus_signal_handler, signal, NULL);
-       if (!(signal->subscription_id)) {
-               _E("Failed to subscribe signal %s", name);
-               free(signal);
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       dbus_signal_list = g_list_append(dbus_signal_list, signal);
-
-       return RESOURCED_ERROR_NONE;
-}
-
-int d_bus_broadcast_signal_gvariant(const char *path, const char *interface,
-               const char *name, GVariant *gv)
-{
-       int ret;
-
-       ret = g_dbus_connection_emit_signal(d_bus_get_connection(),
-               NULL, path, interface, name, gv, NULL);
-       if (ret != TRUE) {
-               _E("Failed to emit gdbus signal(%s:%s-%s)", path, interface, name);
-               return -ECOMM;
-       }
-
-       return RESOURCED_ERROR_NONE;
-}
-
-int d_bus_broadcast_signal(const char *path, const char *interface,
-               const char *name, const char *sig, char *param[])
-{
-       GVariant *gv = append_variant(sig, param);
-       if (!gv) {
-               _E("Failed to build g_variant");
-               return -EINVAL;
-       }
-       return d_bus_broadcast_signal_gvariant(path, interface, name, gv);
-}
-
-resourced_ret_c d_bus_register_methods(const char *path, const char *xml,
-               const struct d_bus_method *methods, const size_t num_methods)
-{
-       struct d_bus_method_handle *handle = NULL;
-       GError *err = NULL;
-
-       if (!path || !xml || !methods) {
-               _E("You must input path, introspection xml and method list");
-               return RESOURCED_ERROR_INVALID_PARAMETER;
-       }
-
-       handle = (struct d_bus_method_handle *)calloc(1, sizeof(struct d_bus_method_handle));
-       if (!handle) {
-               _E("Not enough memory!");
-               return RESOURCED_ERROR_OUT_OF_MEMORY;
-       }
-
-       handle->path = path;
-       handle->methods = methods;
-       handle->num_methods = num_methods;
-
-       handle->node_info = g_dbus_node_info_new_for_xml(xml, &err);
-       if (!handle->node_info) {
-               _E("Failed to make node_info : %s", err->message);
-               goto on_error;
-       }
-
-       handle->subscription_id = g_dbus_connection_register_object(d_bus_get_connection(),
-                       path, handle->node_info->interfaces[0], &vtable, (gpointer)handle, NULL, &err);
-       if (!handle->subscription_id) {
-               _E("Failed to register gdbus methods with path %s : %s", path, err->message);
-               g_dbus_node_info_unref(handle->node_info);
-               goto on_error;
-       } else
-               dbus_method_handle_list = g_list_append(dbus_method_handle_list, (gpointer)handle);
-
-       return RESOURCED_ERROR_NONE;
-
-on_error:
-       g_clear_error(&err);
-       free(handle);
-
-       return RESOURCED_ERROR_FAIL;
-}
-
-resourced_ret_c d_bus_register_signals(const struct d_bus_signal *signals, const size_t size)
-{
-       int i;
-       int ret;
-
-       for (i = 0; i < size; i++) {
-               if (!signals[i].path || !signals[i].interface || !signals[i].name || !signals[i].callback)
-                       continue;
-
-               ret = d_bus_register_signal(
-                               signals[i].path,
-                               signals[i].interface,
-                               signals[i].name,
-                               signals[i].callback,
-                               signals[i].user_data);
-               if (ret != RESOURCED_ERROR_NONE) {
-                       _E("Fail to add signal %s, %s!\n", signals[i].path, signals[i].name);
-                       return RESOURCED_ERROR_FAIL;
-               }
-       }
-
-       return RESOURCED_ERROR_NONE;
-}
-
-resourced_ret_c d_bus_reply_message(GDBusMessage *msg)
-{
-       GError *err = NULL;
-
-       if (!g_dbus_connection_send_message(d_bus_get_connection(), msg,
-                               G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &err)) {
-               _E("Fail to reply gdbus message");
-               g_clear_error(&err);
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       g_clear_error(&err);
-       return RESOURCED_ERROR_NONE;
-}
-
-void d_bus_init(void)
-{
-       owner_id = g_bus_own_name_on_connection(d_bus_get_connection(), RESOURCED_BUS_NAME,
-                       G_BUS_NAME_OWNER_FLAGS_NONE, NULL, NULL, NULL, NULL);
-       if (owner_id == 0) {
-               _E("Failed to get gdbus own name");
-       }
-}
-
-void d_bus_exit(void)
-{
-       GList *iter;
-       struct d_bus_signal *signal;
-       struct d_bus_method_handle *method_handle;
-       GDBusConnection *conn = d_bus_get_connection();
-
-       if (owner_id != 0)
-               g_bus_unown_name(owner_id);
-
-       /* Remove D-Bus signal list */
-       for (iter = dbus_signal_list; iter; iter = g_list_next(iter)) {
-               signal = (struct d_bus_signal *)iter->data;
-               g_dbus_connection_signal_unsubscribe(conn, signal->subscription_id);
-               dbus_signal_list = g_list_remove(dbus_signal_list, signal);
-               free(signal);
-       }
-
-       /* Remove D-Bus method list */
-       for (iter = dbus_method_handle_list; iter; iter = g_list_next(iter)) {
-               method_handle = (struct d_bus_method_handle *)iter->data;
-               g_dbus_connection_unregister_object(conn, method_handle->subscription_id);
-               g_dbus_node_info_unref(method_handle->node_info);
-               dbus_method_handle_list = g_list_remove(dbus_method_handle_list, method_handle);
-               free(method_handle);
-       }
-
-       g_object_unref(conn);
-}
diff --git a/src/common/dbus-handler.h b/src/common/dbus-handler.h
deleted file mode 100644 (file)
index 46f81c2..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * resourced
- *
- * Copyright (c) 2013 - 2019 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-/**
- * @file dbus-handler.h
- * @desc  dbus handler using libdbus
- **/
-
-#ifndef __DBUS_HANDLER_H__
-#define __DBUS_HANDLER_H__
-
-#include <dbus-names-local.h>
-#include <dbus-names-external.h>
-#include <gio/gio.h>
-#include <resourced.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-typedef void (*d_bus_method_callback)(GDBusMethodInvocation *invocation, GVariant *params);
-typedef void (*d_bus_signal_callback)(GVariant *params);
-
-struct d_bus_method {
-       const char *name;
-       d_bus_method_callback callback;
-};
-
-struct d_bus_method_handle {
-       const char *path;
-       const struct d_bus_method *methods;
-       size_t num_methods;
-       GDBusNodeInfo *node_info;
-       guint subscription_id;
-};
-
-struct d_bus_signal {
-       const char *path;
-       const char *interface;
-       const char *name;
-       d_bus_signal_callback callback;
-       void *user_data;
-       guint subscription_id;
-};
-
-/*
- * If reply signature is existed, GDBus allows the return type
- * to declared type or error.
- *
- * However, before GDBus is applied, resourced returns NULL
- * when error is occurred.
- *
- * Therefore, for backward compatibility, we don't use the function
- * g_dbus_method_invocation_return_error and return NULL with sending new message
- *
- * cf) Process resource usage functions use return_error because
- *     it is only for Runtime-info (we can control this package)
- */
-#define D_BUS_REPLY_EMPTY_TUPLE(ivc, signature)        \
-{      \
-       GDBusMessage *re = g_dbus_message_new_method_reply(g_dbus_method_invocation_get_message(ivc));  \
-       d_bus_reply_message(re);        \
-       g_object_unref(re);     \
-       g_object_unref(ivc);    \
-}
-
-#define D_BUS_REPLY_NULL(ivc, signature)       \
-{      \
-       g_dbus_method_invocation_return_value(ivc, g_variant_new(signature));   \
-}
-
-#define D_BUS_REPLY_ERR(ivc)   \
-{      \
-       g_dbus_method_invocation_return_error(ivc,      \
-                                       G_DBUS_ERROR, G_DBUS_ERROR_FAILED,      \
-                                       "%s failed", g_dbus_method_invocation_get_method_name(ivc));    \
-}
-
-GDBusConnection *d_bus_get_connection(void);
-
-int d_bus_call_method_sync_gvariant(const char *dest, const char *path,
-               const char *interface, const char *method,
-               GVariant *gv);
-
-int d_bus_call_method_sync(const char *dest, const char *path,
-               const char *interface, const char *method,
-               const char *sig, char *param[]);
-
-int d_bus_call_method_async_gvariant(const char *dest, const char *path,
-               const char *interface, const char *method,
-               GVariant *gv);
-
-int d_bus_call_method_sync_gvariant_with_reply(const char *dest, const char *path,
-               const char *interface, const char *method,
-               GVariant *gv, GVariant **out_reply);
-
-int d_bus_call_method_async(const char *dest, const char *path,
-               const char *interface, const char *method,
-               const char *sig, char *param[]);
-
-resourced_ret_c d_bus_register_signal(const char *path, const char *interface,
-               const char *name, d_bus_signal_callback callback, void *user_data);
-
-int d_bus_broadcast_signal_gvariant(const char *path, const char *interface,
-               const char *name, GVariant *gv);
-
-int d_bus_broadcast_signal(const char *path, const char *interface,
-               const char *name, const char *sig, char *param[]);
-
-resourced_ret_c d_bus_register_methods(const char *path, const char *xml,
-               const struct d_bus_method *methods, const size_t num_methods);
-
-resourced_ret_c d_bus_register_signals(const struct d_bus_signal *signals,
-               const size_t size);
-
-resourced_ret_c d_bus_reply_message(GDBusMessage *msg);
-
-int launch_system_app_by_dbus(const char *dest, const char *path,
-               const char *iface, const char *method, const char *arg_type, ...);
-
-void d_bus_init(void);
-void d_bus_exit(void);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __DBUS_HANDLER_H__ */
diff --git a/src/common/dbus-names-external.h b/src/common/dbus-names-external.h
deleted file mode 100644 (file)
index 91d932d..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * resourced
- *
- * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#ifndef DBUS_NAMES_EXTERNAL_H_INCLUDE_GUARD
-#define DBUS_NAMES_EXTERNAL_H_INCLUDE_GUARD
-
-/*
- * System popup
- */
-#define SYSTEM_POPUP_BUS_NAME         "org.tizen.system.popup"
-#define SYSTEM_POPUP_PATH_NAME        "/Org/Tizen/System/Popup"
-
-#define SYSTEM_POPUP_PATH_SYSTEM      SYSTEM_POPUP_PATH_NAME"/System"
-#define SYSTEM_POPUP_IFACE_SYSTEM     SYSTEM_POPUP_BUS_NAME".System"
-
-/*
- * Deviced
- */
-/*#define DEVICED_BUS_NAME            "org.tizen.system.deviced"
-#define DEVICED_OBJECT_PATH         "/Org/Tizen/System/DeviceD"
-
-#define DEVICED_PATH_PROCESS        DEVICED_OBJECT_PATH"/Process"
-#define DEVICED_INTERFACE_PROCESS   DEVICED_BUS_NAME".Process"
-
-#define DEVICED_PATH_DISPLAY        DEVICED_OBJECT_PATH"/Display"
-#define DEVICED_INTERFACE_DISPLAY   DEVICED_BUS_NAME".display"
-
-#define DEVICED_PATH_BATTERY        DEVICED_OBJECT_PATH"/Battery"
-#define DEVICED_INTERFACE_BATTERY   DEVICED_BUS_NAME".Battery"
-
-#define DEVICED_PATH_POWEROFF       DEVICED_OBJECT_PATH"/PowerOff"
-#define DEVICED_INTERFACE_POWEROFF  DEVICED_BUS_NAME".PowerOff"
-
-#define DEVICED_PATH_TIME           DEVICED_OBJECT_PATH"/Time"
-#define DEVICED_INTERFACE_TIME      DEVICED_BUS_NAME".Time"*/
-
-
-#define SIGNAL_DEVICED_LCDON               "LCDOn"
-#define SIGNAL_DEVICED_LCDOFF              "LCDOff"
-#define SIGNAL_DEVICED_LCDONCOMPLETE       "LCDOnCompleted"
-#define SIGNAL_DEVICED_POWEROFF_STATE      "ChangeState"
-#define SIGNAL_DEVICED_SYSTEMTIME_CHANGED  "SystemTimeChanged"
-#define SIGNAL_DEVICED_LOW_BATTERY                "BatteryStatusLow"
-#define SIGNAL_DEVICED_SUSPEND             "sleep"
-#define SIGNAL_DEVICED_WAKEUP              "wakeup"
-
-/*
- * dump service
- */
-#define DUMP_SERVICE_BUS_NAME        "org.tizen.system.dumpservice"
-#define DUMP_SERVICE_OBJECT_PATH     "/Org/Tizen/System/DumpService"
-#define DUMP_SERVICE_INTERFACE_NAME  DUMP_SERVICE_BUS_NAME
-
-#define SIGNAL_DUMP         "Dump"
-#define SIGNAL_DUMP_START   "Start"
-#define SIGNAL_DUMP_FINISH  "Finish"
-
-/*
- * Crash
- */
-#define CRASH_BUS_NAME         "org.tizen.system.crash"
-#define CRASH_OBJECT_PATH      "/Org/Tizen/System/Crash"
-#define CRASH_INTERFACE_NAME   CRASH_BUS_NAME
-#define CRASH_PATH_CRASH       CRASH_OBJECT_PATH"/Crash"
-#define CRASH_INTERFACE_CRASH  CRASH_INTERFACE_NAME".Crash"
-#define PROCESS_CRASHED        "ProcessCrashed"
-
-/*
- * AMD
- */
-#define AUL_APPSTATUS_BUS_NAME        "org.tizen.aul.AppStatus"
-#define AUL_APPSTATUS_OBJECT_PATH     "/Org/Tizen/Aul/AppStatus"
-#define AUL_APPSTATUS_INTERFACE_NAME  AUL_APPSTATUS_BUS_NAME
-
-#define AUL_SUSPEND_BUS_NAME          "org.tizen.appfw.SuspendHint"
-#define AUL_SUSPEND_OBJECT_PATH       "/Org/Tizen/Appfw/SuspendHint"
-#define AUL_SUSPEND_INTERFACE_NAME    AUL_SUSPEND_BUS_NAME
-
-#define SIGNAL_AMD_LAUNCH      "AppLaunch"
-#define SIGNAL_AMD_RESUME      "AppResume"
-#define SIGNAL_AMD_TERMINATE   "AppTerminate"
-#define SIGNAL_AMD_STATE       "AppStatusChange"
-#define SIGNAL_AMD_GROUP       "AppGroup"
-#define SIGNAL_AMD_TERMINATED  "AppTerminated"
-#define SIGNAL_AMD_SUSPNED     "SuspendHint"
-
-/*
- * D-Bus daemon
- */
-#define DBUS_BUS_NAME        "org.freedesktop.DBus"
-#define DBUS_OBJECT_PATH     "/org/freedesktop/DBus"
-#define DBUS_INTERFACE_NAME  DBUS_BUS_NAME
-
-/*
- * booting
- */
-#define BOOTING_DONE_PATH      "/org/tizen/system"
-#define BOOTING_DONE_INTERFACE "org.tizen.system.Booting"
-#define SIGNAL_BOOTING_DONE    "BootingDone"
-
-#endif
diff --git a/src/common/dbus-names-local.h b/src/common/dbus-names-local.h
deleted file mode 100644 (file)
index d8b2c96..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * resourced
- *
- * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#ifndef DBUS_NAMES_LOCAL_H_INCLUDE_GUARD
-#define DBUS_NAMES_LOCAL_H_INCLUDE_GUARD
-
-#include <libsyscommon/libsystemd.h>
-
-/*#define RESOURCED_DBUS_BUS_NAME        "org.tizen.resourced"
-#define RESOURCED_DBUS_OBJECT_PATH     "/Org/Tizen/ResourceD"
-#define RESOURCED_DBUS_INTERFACE_NAME  RESOURCED_DBUS_BUS_NAME*/
-
-/*
- * Core service
- *   get/set swap status
- *   operations about swap
- */
-#define RESOURCED_PATH_SWAP             RESOURCED_OBJECT_PATH"/Swap"
-#define RESOURCED_INTERFACE_SWAP        RESOURCED_INTERFACE_NAME".swap"
-
-/*#define RESOURCED_PATH_FREEZER          RESOURCED_DBUS_OBJECT_PATH"/Freezer"
-#define RESOURCED_INTERFACE_FREEZER     RESOURCED_DBUS_INTERFACE_NAME".freezer"*/
-
-#define RESOURCED_PATH_OOM              RESOURCED_OBJECT_PATH"/Oom"
-#define RESOURCED_INTERFACE_OOM         RESOURCED_INTERFACE_NAME".oom"
-
-/*#define RESOURCED_PATH_PROCESS          RESOURCED_DBUS_OBJECT_PATH"/Process"
-#define RESOURCED_INTERFACE_PROCESS     RESOURCED_DBUS_INTERFACE_NAME".process"*/
-
-#define RESOURCED_PATH_WATCHDOG         RESOURCED_OBJECT_PATH"/Watchdog"
-#define RESOURCED_INTERFACE_WATCHDOG    RESOURCED_INTERFACE_NAME".watchdog"
-
-
-#define SIGNAL_PROC_ACTIVE              "Active"
-#define SIGNAL_PROC_EXCLUDE             "ProcExclude"
-#define SIGNAL_PROC_PRELAUNCH           "ProcPrelaunch"
-#define SIGNAL_PROC_SWEEP               "ProcSweep"
-#define SIGNAL_APP_WATCHDOG             "AppWatchdog"
-#define SIGNAL_PROC_SYSTEMSERVICE       "SystemService"
-#define SIGNAL_PROC_EXCLUDEAPPID        "ProcExcludeByAppid"
-#define SIGNAL_PROC_SET_PRIORITY        "ProcSetPriority"
-
-#define SIGNAL_OOM_SET_THRESHOLD        "SetThreshold"
-#define SIGNAL_OOM_SET_LEAVE_THRESHOLD  "SetLeaveThreshold"
-#define SIGNAL_OOM_TRIGGER              "Trigger"
-#define SIGNAL_OOM_SET_PERCEPTIBLE      "SetPerceptible"
-#define SIGNAL_OOM_SET_PLATFORM         "SetPlatformSwap"
-#define SIGNAL_OOM_SET_MEMLIMIT         "SetMemLimit"
-#define SIGNAL_OOM_MEMLIMIT_EVENT       "MemLimitEvent"
-
-#define SIGNAL_NAME_SWAP_START_PID      "SwapStartPid"
-/*
- * Logging
- */
-/*#define RESOURCED_PATH_LOGGING       RESOURCED_DBUS_OBJECT_PATH"/Logging"
-#define RESOURCED_INTERFACE_LOGGING  RESOURCED_DBUS_INTERFACE_NAME".logging"*/
-
-#endif
diff --git a/src/common/dedup-common.c b/src/common/dedup-common.c
deleted file mode 100644 (file)
index c45be8c..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * resourced
- *
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "macro.h"
-#include "dedup-common.h"
-#include "trace.h"
-
-static struct dedup_conf *dedup_conf = NULL;
-
-static enum dedup_state dedup_state;
-
-struct dedup_conf *get_dedup_conf(void)
-{
-       if (!dedup_conf) {
-               dedup_conf = (struct dedup_conf *)calloc(1, sizeof (struct dedup_conf));
-               if (!dedup_conf) {
-                       _E("Failed to alloc memory for cpu configuration");
-                       return NULL;
-               }
-               else {
-                       dedup_conf->enable = false;
-                       dedup_conf->boot_dedup_enable = false;
-                       dedup_conf->scan_on_lowmem = false;
-               }
-       }
-
-       return dedup_conf;
-}
-
-void free_dedup_conf(void)
-{
-       if (dedup_conf)
-               free(dedup_conf);
-}
-
-enum dedup_state dedup_get_state(void)
-{
-       return dedup_state;
-}
-
-void dedup_set_state(enum dedup_state state)
-{
-       if ((state != DEDUP_ON) && (state != DEDUP_OFF) &&
-                       state != DEDUP_ONE_SHOT)
-               return;
-
-       dedup_state = state;
-}
diff --git a/src/common/dedup-common.h b/src/common/dedup-common.h
deleted file mode 100644 (file)
index be10294..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * resourced
- *
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-/**
- * @file dedup-common.h
- * @desc dedup common process
- **/
-
-#ifndef __DEDUP_COMMON_H__
-#define __DEDUP_COMMON_H__
-
-#include <stdio.h>
-#include "resourced.h"
-#include "memory-cgroup.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-#define DEDUP_CONF_FILE                RD_CONFIG_FILE(optimizer)
-#define DEDUP_SYSFS_KSM_PATH   "/sys/kernel/mm/ksm"
-
-/* KSM operations */
-#define DEDUP_SYSFS_KSM_RUN    "/sys/kernel/mm/ksm/run"
-#define DEDUP_SYSFS_KSM_ONESHOT "/sys/kernel/mm/ksm/one_shot_scanning"
-
-enum dedup_state {
-       DEDUP_ARG_START = -1,
-       DEDUP_OFF,
-       DEDUP_ON,
-       DEDUP_ONE_SHOT,
-       DEDUP_ARG_END,
-};
-
-enum dedup_mode {
-       DEDUP_MODE_NONE = 0,
-       DEDUP_MODE_PERIODIC,
-       DEDUP_MODE_ONESHOT,
-       DEDUP_MODE_MAX,
-};
-
-enum ksm_stat {
-       KSM_STAT_PAGES_SHARING = 0,
-       KSM_STAT_PAGES_SHARED,
-       KSM_STAT_MAX,
-};
-
-enum ksm_scan_mode {
-       KSM_SCAN_NONE = 0,
-       KSM_SCAN_PARTIAL,
-       KSM_SCAN_FULL,
-};
-
-struct ksm {
-       char mode[MAX_TYPE_LENGTH];
-       int pages;
-       int boost_pages;
-};
-
-struct dedup_conf {
-       bool enable;
-       bool boot_dedup_enable;
-       bool scan_on_lowmem;
-       struct ksm ksm;
-};
-
-struct dedup_conf *get_dedup_conf(void);
-void free_dedup_conf(void);
-
-enum dedup_state dedup_get_state(void);
-void dedup_set_state(enum dedup_state state);
-unsigned int dedup_get_ksm_stat(enum ksm_stat stat_type);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __DEDUP_COMMON_H__ */
diff --git a/src/common/ipc/dbus-handler.c b/src/common/ipc/dbus-handler.c
new file mode 100644 (file)
index 0000000..cc80344
--- /dev/null
@@ -0,0 +1,448 @@
+/*
+ * resourced
+ *
+ * Copyright (c) 2000 - 2019 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * @file dbus-handler.c
+ *
+ * @desc dbus handler using libdbus
+ *
+ */
+
+#include <glib.h>
+#include <gio/gio.h>
+#include <stdint.h>
+
+#include "trace.h"
+#include "dbus-handler.h"
+#include "macro.h"
+#include "resourced.h"
+#include "util.h"
+#include "fd-handler.h"
+
+static guint owner_id;
+static GList *dbus_signal_list;
+static GList *dbus_method_handle_list;
+
+GDBusConnection *d_bus_get_connection(void)
+{
+       static GDBusConnection *g_dbus_conn = NULL;
+
+       if (g_dbus_conn)
+               return g_dbus_conn;
+
+       g_dbus_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL);
+       g_assert(g_dbus_conn);
+
+       g_dbus_connection_set_exit_on_close(g_dbus_conn, FALSE);
+       return g_dbus_conn;
+}
+
+static struct d_bus_signal *d_bus_find_signal(const char *path, const char *interface, const char *name)
+{
+       size_t path_len, interface_len, name_len;
+       GList *iter;
+       struct d_bus_signal *signal;
+
+       path_len = strlen(path) + 1;
+       interface_len = strlen(interface) + 1;
+       name_len = strlen(name) + 1;
+
+       for (iter = dbus_signal_list; iter; iter = g_list_next(iter)) {
+               signal = (struct d_bus_signal *)iter->data;
+               if (strncmp(signal->path, path, path_len))
+                       continue;
+               if (strncmp(signal->interface, interface, interface_len))
+                       continue;
+               if (strncmp(signal->name, name, name_len))
+                       continue;
+               return signal;
+       }
+
+       return NULL;
+}
+
+/* Find appropriate method and call its callback */
+static void d_bus_method_handler(GDBusConnection *connection,
+               const gchar *sender, const gchar *object_path,
+               const gchar *interface_name, const gchar *method_name,
+               GVariant *parameters, GDBusMethodInvocation *invocation,
+               gpointer user_data)
+{
+       int i;
+       struct d_bus_method_handle *handle;
+       int name_len;
+
+       if (!user_data) {
+               _E("There is no handle about received gdbus method");
+               return;
+       }
+       handle = (struct d_bus_method_handle *)user_data;
+
+       name_len = strlen(method_name) + 1;
+       for (i = 0; i < handle->num_methods; i++) {
+               if (strncmp(handle->methods[i].name, method_name, name_len))
+                       continue;
+
+               handle->methods[i].callback(invocation, parameters);
+               break;
+       }
+}
+
+static const GDBusInterfaceVTable vtable = { d_bus_method_handler, NULL, NULL };
+
+static void d_bus_signal_handler(GDBusConnection *connection,
+               const gchar *sender, const gchar *object_path,
+               const gchar *interface_name, const gchar *signal_name,
+               GVariant *parameters, gpointer user_data)
+{
+       struct d_bus_signal *signal = (struct d_bus_signal *)user_data;
+       if (!signal || !signal->callback)
+               return;
+
+       signal->callback(parameters);
+}
+
+struct dbus_int {
+       int *list;
+       int size;
+};
+
+static GVariant *append_variant(const char *sig, char *param[])
+{
+       GVariantBuilder builder;
+       GVariantBuilder *sub_builder;
+       GVariant *var;
+       struct dbus_int *array_int;
+       char *ch;
+       int i, j;
+
+       if (!sig || !param)
+               return NULL;
+
+       g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
+
+       for (ch = (char *)sig, i = 0; *ch != '\0'; ++i, ++ch) {
+               switch (*ch) {
+               case 'i':
+                       g_variant_builder_add(&builder, "i", atoi(param[i]));
+                       break;
+               case 'u':
+                       g_variant_builder_add(&builder, "u", strtoul(param[i], NULL, 10));
+                       break;
+               case 't':
+                       g_variant_builder_add(&builder, "t", atoll(param[i]));
+                       break;
+               case 's':
+                       g_variant_builder_add(&builder, "s", param[i]);
+                       break;
+               case 'a':
+                       ++ch;
+                       switch (*ch) {
+                       case 'i':
+                               sub_builder = g_variant_builder_new(G_VARIANT_TYPE("ai"));
+                               array_int = (struct dbus_int *)param[i];
+                               for (j = 0; j < array_int->size; j++)
+                                       g_variant_builder_add(sub_builder, "i", array_int->list[j]);
+                               var = g_variant_new("ai", sub_builder);
+                               g_variant_builder_unref(sub_builder);
+                               g_variant_builder_add_value(&builder, var);
+                               break;
+                       default:
+                               break;
+                       }
+                       break;
+               default:
+                       return NULL;
+               }
+       }
+
+       return g_variant_builder_end(&builder);
+}
+
+int d_bus_call_method_sync(const char *dest, const char *path,
+               const char *interface, const char *method,
+               const char *sig, char *param[])
+{
+       GVariant *gv = NULL;
+
+       if (sig || param) {
+               gv = append_variant(sig, param);
+               if (!gv) {
+                       _E("Failed to build g_variant");
+                       return -EINVAL;
+               }
+       }
+
+       return d_bus_call_method_sync_gvariant(dest, path, interface, method, gv);
+}
+
+int d_bus_call_method_sync_gvariant(const char *dest, const char *path,
+               const char *interface, const char *method,
+               GVariant *gv)
+{
+       int ret;
+       GVariant *reply = NULL;
+       GError *err = NULL;
+
+       reply = g_dbus_connection_call_sync(d_bus_get_connection(), dest, path,
+                       interface, method, gv, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
+       if (err || !reply) {
+               /* The case where !err && !reply (i.e. reply type mismatch) can't currently happen
+                * because we don't specify the desired reply type, but it's good to be future-proof */
+               _E("Failed to call D-Bus name %s, objpath %s, iface %s, method %s: %s",
+                       dest, path, interface, method, err ? err->message : "reply signature mismatch");
+               if (err)
+                       g_error_free(err);
+               return -ECOMM;
+       }
+
+       do_expr_unless_g_variant_consume_typechecked(return -EINVAL, reply, "(i)", &ret);
+
+       return ret;
+}
+
+int d_bus_call_method_sync_gvariant_with_reply(const char *dest, const char *path,
+               const char *interface, const char *method,
+               GVariant *gv, GVariant **out_reply)
+{
+       GVariant *reply = NULL;
+       GError *err = NULL;
+
+       reply = g_dbus_connection_call_sync(d_bus_get_connection(), dest, path,
+                       interface, method, gv, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
+       if (err || !reply) {
+               /* The case where !err && !reply (i.e. reply type mismatch) can't currently happen
+                * because we don't specify the desired reply type, but it's good to be future-proof */
+               _E("Failed to call D-Bus name %s, objpath %s, iface %s, method %s: %s",
+                       dest, path, interface, method, err ? err->message : "reply signature mismatch");
+               if (err)
+                       g_error_free(err);
+               return -ECOMM;
+       }
+
+       *out_reply = reply;
+
+       return 0;
+}
+
+int d_bus_call_method_async(const char *dest, const char *path,
+               const char *interface, const char *method,
+               const char *sig, char *param[])
+{
+       GVariant *gv = append_variant(sig, param);
+       if (!gv) {
+               _E("Failed to build g_variant");
+               return -EINVAL;
+       }
+       return d_bus_call_method_async_gvariant(dest, path, interface, method, gv);
+}
+
+int d_bus_call_method_async_gvariant(const char *dest, const char *path,
+               const char *interface, const char *method, GVariant *gv)
+{
+       g_dbus_connection_call(d_bus_get_connection(), dest, path, interface, method,
+                       gv, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
+
+       return 0;
+}
+
+resourced_ret_c d_bus_register_signal(const char *path, const char *interface,
+               const char *name, d_bus_signal_callback callback, void *user_data)
+{
+       struct d_bus_signal *signal;
+
+       if (d_bus_find_signal(path, interface, name)) {
+               _E("Same D-Bus signal is already registered");
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       signal = calloc(1, sizeof(struct d_bus_signal));
+       if (!signal) {
+               _E("Not enough memory!");
+               return RESOURCED_ERROR_OUT_OF_MEMORY;
+       }
+
+       signal->path = path;
+       signal->interface = interface;
+       signal->name = name;
+       signal->callback = callback;
+       signal->user_data = user_data;
+
+       signal->subscription_id = g_dbus_connection_signal_subscribe(d_bus_get_connection(),
+                       NULL, interface, name, path, NULL, G_DBUS_SIGNAL_FLAGS_NONE,
+                       d_bus_signal_handler, signal, NULL);
+       if (!(signal->subscription_id)) {
+               _E("Failed to subscribe signal %s", name);
+               free(signal);
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       dbus_signal_list = g_list_append(dbus_signal_list, signal);
+
+       return RESOURCED_ERROR_NONE;
+}
+
+int d_bus_broadcast_signal_gvariant(const char *path, const char *interface,
+               const char *name, GVariant *gv)
+{
+       int ret;
+
+       ret = g_dbus_connection_emit_signal(d_bus_get_connection(),
+               NULL, path, interface, name, gv, NULL);
+       if (ret != TRUE) {
+               _E("Failed to emit gdbus signal(%s:%s-%s)", path, interface, name);
+               return -ECOMM;
+       }
+
+       return RESOURCED_ERROR_NONE;
+}
+
+int d_bus_broadcast_signal(const char *path, const char *interface,
+               const char *name, const char *sig, char *param[])
+{
+       GVariant *gv = append_variant(sig, param);
+       if (!gv) {
+               _E("Failed to build g_variant");
+               return -EINVAL;
+       }
+       return d_bus_broadcast_signal_gvariant(path, interface, name, gv);
+}
+
+resourced_ret_c d_bus_register_methods(const char *path, const char *xml,
+               const struct d_bus_method *methods, const size_t num_methods)
+{
+       struct d_bus_method_handle *handle = NULL;
+       GError *err = NULL;
+
+       if (!path || !xml || !methods) {
+               _E("You must input path, introspection xml and method list");
+               return RESOURCED_ERROR_INVALID_PARAMETER;
+       }
+
+       handle = (struct d_bus_method_handle *)calloc(1, sizeof(struct d_bus_method_handle));
+       if (!handle) {
+               _E("Not enough memory!");
+               return RESOURCED_ERROR_OUT_OF_MEMORY;
+       }
+
+       handle->path = path;
+       handle->methods = methods;
+       handle->num_methods = num_methods;
+
+       handle->node_info = g_dbus_node_info_new_for_xml(xml, &err);
+       if (!handle->node_info) {
+               _E("Failed to make node_info : %s", err->message);
+               goto on_error;
+       }
+
+       handle->subscription_id = g_dbus_connection_register_object(d_bus_get_connection(),
+                       path, handle->node_info->interfaces[0], &vtable, (gpointer)handle, NULL, &err);
+       if (!handle->subscription_id) {
+               _E("Failed to register gdbus methods with path %s : %s", path, err->message);
+               g_dbus_node_info_unref(handle->node_info);
+               goto on_error;
+       } else
+               dbus_method_handle_list = g_list_append(dbus_method_handle_list, (gpointer)handle);
+
+       return RESOURCED_ERROR_NONE;
+
+on_error:
+       g_clear_error(&err);
+       free(handle);
+
+       return RESOURCED_ERROR_FAIL;
+}
+
+resourced_ret_c d_bus_register_signals(const struct d_bus_signal *signals, const size_t size)
+{
+       int i;
+       int ret;
+
+       for (i = 0; i < size; i++) {
+               if (!signals[i].path || !signals[i].interface || !signals[i].name || !signals[i].callback)
+                       continue;
+
+               ret = d_bus_register_signal(
+                               signals[i].path,
+                               signals[i].interface,
+                               signals[i].name,
+                               signals[i].callback,
+                               signals[i].user_data);
+               if (ret != RESOURCED_ERROR_NONE) {
+                       _E("Fail to add signal %s, %s!\n", signals[i].path, signals[i].name);
+                       return RESOURCED_ERROR_FAIL;
+               }
+       }
+
+       return RESOURCED_ERROR_NONE;
+}
+
+resourced_ret_c d_bus_reply_message(GDBusMessage *msg)
+{
+       GError *err = NULL;
+
+       if (!g_dbus_connection_send_message(d_bus_get_connection(), msg,
+                               G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &err)) {
+               _E("Fail to reply gdbus message");
+               g_clear_error(&err);
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       g_clear_error(&err);
+       return RESOURCED_ERROR_NONE;
+}
+
+void d_bus_init(void)
+{
+       owner_id = g_bus_own_name_on_connection(d_bus_get_connection(), RESOURCED_BUS_NAME,
+                       G_BUS_NAME_OWNER_FLAGS_NONE, NULL, NULL, NULL, NULL);
+       if (owner_id == 0) {
+               _E("Failed to get gdbus own name");
+       }
+}
+
+void d_bus_exit(void)
+{
+       GList *iter;
+       struct d_bus_signal *signal;
+       struct d_bus_method_handle *method_handle;
+       GDBusConnection *conn = d_bus_get_connection();
+
+       if (owner_id != 0)
+               g_bus_unown_name(owner_id);
+
+       /* Remove D-Bus signal list */
+       for (iter = dbus_signal_list; iter; iter = g_list_next(iter)) {
+               signal = (struct d_bus_signal *)iter->data;
+               g_dbus_connection_signal_unsubscribe(conn, signal->subscription_id);
+               dbus_signal_list = g_list_remove(dbus_signal_list, signal);
+               free(signal);
+       }
+
+       /* Remove D-Bus method list */
+       for (iter = dbus_method_handle_list; iter; iter = g_list_next(iter)) {
+               method_handle = (struct d_bus_method_handle *)iter->data;
+               g_dbus_connection_unregister_object(conn, method_handle->subscription_id);
+               g_dbus_node_info_unref(method_handle->node_info);
+               dbus_method_handle_list = g_list_remove(dbus_method_handle_list, method_handle);
+               free(method_handle);
+       }
+
+       g_object_unref(conn);
+}
diff --git a/src/common/ipc/dbus-handler.h b/src/common/ipc/dbus-handler.h
new file mode 100644 (file)
index 0000000..46f81c2
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * resourced
+ *
+ * Copyright (c) 2013 - 2019 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * @file dbus-handler.h
+ * @desc  dbus handler using libdbus
+ **/
+
+#ifndef __DBUS_HANDLER_H__
+#define __DBUS_HANDLER_H__
+
+#include <dbus-names-local.h>
+#include <dbus-names-external.h>
+#include <gio/gio.h>
+#include <resourced.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef void (*d_bus_method_callback)(GDBusMethodInvocation *invocation, GVariant *params);
+typedef void (*d_bus_signal_callback)(GVariant *params);
+
+struct d_bus_method {
+       const char *name;
+       d_bus_method_callback callback;
+};
+
+struct d_bus_method_handle {
+       const char *path;
+       const struct d_bus_method *methods;
+       size_t num_methods;
+       GDBusNodeInfo *node_info;
+       guint subscription_id;
+};
+
+struct d_bus_signal {
+       const char *path;
+       const char *interface;
+       const char *name;
+       d_bus_signal_callback callback;
+       void *user_data;
+       guint subscription_id;
+};
+
+/*
+ * If reply signature is existed, GDBus allows the return type
+ * to declared type or error.
+ *
+ * However, before GDBus is applied, resourced returns NULL
+ * when error is occurred.
+ *
+ * Therefore, for backward compatibility, we don't use the function
+ * g_dbus_method_invocation_return_error and return NULL with sending new message
+ *
+ * cf) Process resource usage functions use return_error because
+ *     it is only for Runtime-info (we can control this package)
+ */
+#define D_BUS_REPLY_EMPTY_TUPLE(ivc, signature)        \
+{      \
+       GDBusMessage *re = g_dbus_message_new_method_reply(g_dbus_method_invocation_get_message(ivc));  \
+       d_bus_reply_message(re);        \
+       g_object_unref(re);     \
+       g_object_unref(ivc);    \
+}
+
+#define D_BUS_REPLY_NULL(ivc, signature)       \
+{      \
+       g_dbus_method_invocation_return_value(ivc, g_variant_new(signature));   \
+}
+
+#define D_BUS_REPLY_ERR(ivc)   \
+{      \
+       g_dbus_method_invocation_return_error(ivc,      \
+                                       G_DBUS_ERROR, G_DBUS_ERROR_FAILED,      \
+                                       "%s failed", g_dbus_method_invocation_get_method_name(ivc));    \
+}
+
+GDBusConnection *d_bus_get_connection(void);
+
+int d_bus_call_method_sync_gvariant(const char *dest, const char *path,
+               const char *interface, const char *method,
+               GVariant *gv);
+
+int d_bus_call_method_sync(const char *dest, const char *path,
+               const char *interface, const char *method,
+               const char *sig, char *param[]);
+
+int d_bus_call_method_async_gvariant(const char *dest, const char *path,
+               const char *interface, const char *method,
+               GVariant *gv);
+
+int d_bus_call_method_sync_gvariant_with_reply(const char *dest, const char *path,
+               const char *interface, const char *method,
+               GVariant *gv, GVariant **out_reply);
+
+int d_bus_call_method_async(const char *dest, const char *path,
+               const char *interface, const char *method,
+               const char *sig, char *param[]);
+
+resourced_ret_c d_bus_register_signal(const char *path, const char *interface,
+               const char *name, d_bus_signal_callback callback, void *user_data);
+
+int d_bus_broadcast_signal_gvariant(const char *path, const char *interface,
+               const char *name, GVariant *gv);
+
+int d_bus_broadcast_signal(const char *path, const char *interface,
+               const char *name, const char *sig, char *param[]);
+
+resourced_ret_c d_bus_register_methods(const char *path, const char *xml,
+               const struct d_bus_method *methods, const size_t num_methods);
+
+resourced_ret_c d_bus_register_signals(const struct d_bus_signal *signals,
+               const size_t size);
+
+resourced_ret_c d_bus_reply_message(GDBusMessage *msg);
+
+int launch_system_app_by_dbus(const char *dest, const char *path,
+               const char *iface, const char *method, const char *arg_type, ...);
+
+void d_bus_init(void);
+void d_bus_exit(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __DBUS_HANDLER_H__ */
diff --git a/src/common/ipc/dbus-names-external.h b/src/common/ipc/dbus-names-external.h
new file mode 100644 (file)
index 0000000..91d932d
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * resourced
+ *
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef DBUS_NAMES_EXTERNAL_H_INCLUDE_GUARD
+#define DBUS_NAMES_EXTERNAL_H_INCLUDE_GUARD
+
+/*
+ * System popup
+ */
+#define SYSTEM_POPUP_BUS_NAME         "org.tizen.system.popup"
+#define SYSTEM_POPUP_PATH_NAME        "/Org/Tizen/System/Popup"
+
+#define SYSTEM_POPUP_PATH_SYSTEM      SYSTEM_POPUP_PATH_NAME"/System"
+#define SYSTEM_POPUP_IFACE_SYSTEM     SYSTEM_POPUP_BUS_NAME".System"
+
+/*
+ * Deviced
+ */
+/*#define DEVICED_BUS_NAME            "org.tizen.system.deviced"
+#define DEVICED_OBJECT_PATH         "/Org/Tizen/System/DeviceD"
+
+#define DEVICED_PATH_PROCESS        DEVICED_OBJECT_PATH"/Process"
+#define DEVICED_INTERFACE_PROCESS   DEVICED_BUS_NAME".Process"
+
+#define DEVICED_PATH_DISPLAY        DEVICED_OBJECT_PATH"/Display"
+#define DEVICED_INTERFACE_DISPLAY   DEVICED_BUS_NAME".display"
+
+#define DEVICED_PATH_BATTERY        DEVICED_OBJECT_PATH"/Battery"
+#define DEVICED_INTERFACE_BATTERY   DEVICED_BUS_NAME".Battery"
+
+#define DEVICED_PATH_POWEROFF       DEVICED_OBJECT_PATH"/PowerOff"
+#define DEVICED_INTERFACE_POWEROFF  DEVICED_BUS_NAME".PowerOff"
+
+#define DEVICED_PATH_TIME           DEVICED_OBJECT_PATH"/Time"
+#define DEVICED_INTERFACE_TIME      DEVICED_BUS_NAME".Time"*/
+
+
+#define SIGNAL_DEVICED_LCDON               "LCDOn"
+#define SIGNAL_DEVICED_LCDOFF              "LCDOff"
+#define SIGNAL_DEVICED_LCDONCOMPLETE       "LCDOnCompleted"
+#define SIGNAL_DEVICED_POWEROFF_STATE      "ChangeState"
+#define SIGNAL_DEVICED_SYSTEMTIME_CHANGED  "SystemTimeChanged"
+#define SIGNAL_DEVICED_LOW_BATTERY                "BatteryStatusLow"
+#define SIGNAL_DEVICED_SUSPEND             "sleep"
+#define SIGNAL_DEVICED_WAKEUP              "wakeup"
+
+/*
+ * dump service
+ */
+#define DUMP_SERVICE_BUS_NAME        "org.tizen.system.dumpservice"
+#define DUMP_SERVICE_OBJECT_PATH     "/Org/Tizen/System/DumpService"
+#define DUMP_SERVICE_INTERFACE_NAME  DUMP_SERVICE_BUS_NAME
+
+#define SIGNAL_DUMP         "Dump"
+#define SIGNAL_DUMP_START   "Start"
+#define SIGNAL_DUMP_FINISH  "Finish"
+
+/*
+ * Crash
+ */
+#define CRASH_BUS_NAME         "org.tizen.system.crash"
+#define CRASH_OBJECT_PATH      "/Org/Tizen/System/Crash"
+#define CRASH_INTERFACE_NAME   CRASH_BUS_NAME
+#define CRASH_PATH_CRASH       CRASH_OBJECT_PATH"/Crash"
+#define CRASH_INTERFACE_CRASH  CRASH_INTERFACE_NAME".Crash"
+#define PROCESS_CRASHED        "ProcessCrashed"
+
+/*
+ * AMD
+ */
+#define AUL_APPSTATUS_BUS_NAME        "org.tizen.aul.AppStatus"
+#define AUL_APPSTATUS_OBJECT_PATH     "/Org/Tizen/Aul/AppStatus"
+#define AUL_APPSTATUS_INTERFACE_NAME  AUL_APPSTATUS_BUS_NAME
+
+#define AUL_SUSPEND_BUS_NAME          "org.tizen.appfw.SuspendHint"
+#define AUL_SUSPEND_OBJECT_PATH       "/Org/Tizen/Appfw/SuspendHint"
+#define AUL_SUSPEND_INTERFACE_NAME    AUL_SUSPEND_BUS_NAME
+
+#define SIGNAL_AMD_LAUNCH      "AppLaunch"
+#define SIGNAL_AMD_RESUME      "AppResume"
+#define SIGNAL_AMD_TERMINATE   "AppTerminate"
+#define SIGNAL_AMD_STATE       "AppStatusChange"
+#define SIGNAL_AMD_GROUP       "AppGroup"
+#define SIGNAL_AMD_TERMINATED  "AppTerminated"
+#define SIGNAL_AMD_SUSPNED     "SuspendHint"
+
+/*
+ * D-Bus daemon
+ */
+#define DBUS_BUS_NAME        "org.freedesktop.DBus"
+#define DBUS_OBJECT_PATH     "/org/freedesktop/DBus"
+#define DBUS_INTERFACE_NAME  DBUS_BUS_NAME
+
+/*
+ * booting
+ */
+#define BOOTING_DONE_PATH      "/org/tizen/system"
+#define BOOTING_DONE_INTERFACE "org.tizen.system.Booting"
+#define SIGNAL_BOOTING_DONE    "BootingDone"
+
+#endif
diff --git a/src/common/ipc/dbus-names-local.h b/src/common/ipc/dbus-names-local.h
new file mode 100644 (file)
index 0000000..d8b2c96
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * resourced
+ *
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef DBUS_NAMES_LOCAL_H_INCLUDE_GUARD
+#define DBUS_NAMES_LOCAL_H_INCLUDE_GUARD
+
+#include <libsyscommon/libsystemd.h>
+
+/*#define RESOURCED_DBUS_BUS_NAME        "org.tizen.resourced"
+#define RESOURCED_DBUS_OBJECT_PATH     "/Org/Tizen/ResourceD"
+#define RESOURCED_DBUS_INTERFACE_NAME  RESOURCED_DBUS_BUS_NAME*/
+
+/*
+ * Core service
+ *   get/set swap status
+ *   operations about swap
+ */
+#define RESOURCED_PATH_SWAP             RESOURCED_OBJECT_PATH"/Swap"
+#define RESOURCED_INTERFACE_SWAP        RESOURCED_INTERFACE_NAME".swap"
+
+/*#define RESOURCED_PATH_FREEZER          RESOURCED_DBUS_OBJECT_PATH"/Freezer"
+#define RESOURCED_INTERFACE_FREEZER     RESOURCED_DBUS_INTERFACE_NAME".freezer"*/
+
+#define RESOURCED_PATH_OOM              RESOURCED_OBJECT_PATH"/Oom"
+#define RESOURCED_INTERFACE_OOM         RESOURCED_INTERFACE_NAME".oom"
+
+/*#define RESOURCED_PATH_PROCESS          RESOURCED_DBUS_OBJECT_PATH"/Process"
+#define RESOURCED_INTERFACE_PROCESS     RESOURCED_DBUS_INTERFACE_NAME".process"*/
+
+#define RESOURCED_PATH_WATCHDOG         RESOURCED_OBJECT_PATH"/Watchdog"
+#define RESOURCED_INTERFACE_WATCHDOG    RESOURCED_INTERFACE_NAME".watchdog"
+
+
+#define SIGNAL_PROC_ACTIVE              "Active"
+#define SIGNAL_PROC_EXCLUDE             "ProcExclude"
+#define SIGNAL_PROC_PRELAUNCH           "ProcPrelaunch"
+#define SIGNAL_PROC_SWEEP               "ProcSweep"
+#define SIGNAL_APP_WATCHDOG             "AppWatchdog"
+#define SIGNAL_PROC_SYSTEMSERVICE       "SystemService"
+#define SIGNAL_PROC_EXCLUDEAPPID        "ProcExcludeByAppid"
+#define SIGNAL_PROC_SET_PRIORITY        "ProcSetPriority"
+
+#define SIGNAL_OOM_SET_THRESHOLD        "SetThreshold"
+#define SIGNAL_OOM_SET_LEAVE_THRESHOLD  "SetLeaveThreshold"
+#define SIGNAL_OOM_TRIGGER              "Trigger"
+#define SIGNAL_OOM_SET_PERCEPTIBLE      "SetPerceptible"
+#define SIGNAL_OOM_SET_PLATFORM         "SetPlatformSwap"
+#define SIGNAL_OOM_SET_MEMLIMIT         "SetMemLimit"
+#define SIGNAL_OOM_MEMLIMIT_EVENT       "MemLimitEvent"
+
+#define SIGNAL_NAME_SWAP_START_PID      "SwapStartPid"
+/*
+ * Logging
+ */
+/*#define RESOURCED_PATH_LOGGING       RESOURCED_DBUS_OBJECT_PATH"/Logging"
+#define RESOURCED_INTERFACE_LOGGING  RESOURCED_DBUS_INTERFACE_NAME".logging"*/
+
+#endif
diff --git a/src/common/ipc/safe-kill.c b/src/common/ipc/safe-kill.c
new file mode 100644 (file)
index 0000000..7b95e1e
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * resourced
+ *
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * @file safe-kill.c
+ *
+ * @desc check if process is dumping core before sending a signal
+ *
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ */
+
+#include "safe-kill.h"
+#include "trace.h"
+#include "util.h"
+#include "macro.h"
+#include <signal.h>
+#include <stdio.h>
+#include <limits.h>
+#include <stdbool.h>
+
+EXPORT_TEST bool is_process_coredumping(pid_t pid)
+{
+       char buf[LINE_MAX];
+       _cleanup_fclose_ FILE *fp = NULL;
+       int val = 0;
+
+       snprintf(buf, sizeof buf, "/proc/%d/status", pid);
+       fp = fopen(buf, "r");
+       if (!fp)
+               return false;
+
+       while (fgets(buf, sizeof(buf), fp)) {
+               /* Skip the lines, until first match */
+               if (!strstart_with(buf, "CoreDumping:"))
+                       continue;
+
+               if (sscanf(buf, "CoreDumping: %d", &val) == 1)
+                       break;
+
+               return false;
+       }
+
+       return (val == 1);
+}
+
+int safe_kill(pid_t pid, int sig)
+{
+       /* Pass signals other than SIGKILL, as other signals are not delivered to
+        * a process that's dumping a core anyway, and SIGKILL is the only one that
+        * can potentially break that process.
+        * Alternatively, with SIGKILL check if process is coredumping.
+        */
+       if (sig != SIGKILL || !is_process_coredumping(pid)) {
+               _D("safe-kill: delivering signal %d to process %d immediately", sig, pid);
+               return kill(pid, sig);
+       }
+
+       _I("safe-kill: process %d is coredumping - signal SIGKILL not sent", pid);
+       return 0;
+}
diff --git a/src/common/ipc/safe-kill.h b/src/common/ipc/safe-kill.h
new file mode 100644 (file)
index 0000000..7f0de4b
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * resourced
+ *
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef SAFE_KILL_H
+#define SAFE_KILL_H
+
+#include <sys/types.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+int safe_kill(pid_t pid, int sig);
+
+#ifdef _UNIT_TEST
+bool is_process_coredumping(pid_t pid);
+#endif
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* SAFE_KILL_H */
diff --git a/src/common/meminfo-lookup.c b/src/common/meminfo-lookup.c
deleted file mode 100644 (file)
index 99a4f07..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-/* NOTE: this file was dynamically generated by gperf but is included verbatim
- * (instead of being regenerated) due to various build environment issues */
-
-/* ANSI-C code produced by gperf version 3.0.4 */
-/* Command-line: gperf /home/abuild/rpmbuild/BUILD/resourced-6.0.2/src/common/meminfo-lookup.gperf  */
-/* Computed positions: -k'1-2,10' */
-
-#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
-      && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
-      && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
-      && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
-      && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
-      && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
-      && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
-      && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
-      && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
-      && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
-      && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
-      && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
-      && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
-      && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
-      && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
-      && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
-      && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
-      && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
-      && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
-      && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
-      && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
-      && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
-      && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
-/* The character set is not based on ISO-646.  */
-#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
-#endif
-
-#include "procfs.h"
-#include <string.h>
-
-#define TOTAL_KEYWORDS 38
-#define MIN_WORD_LENGTH 4
-#define MAX_WORD_LENGTH 14
-#define MIN_HASH_VALUE 4
-#define MAX_HASH_VALUE 67
-/* maximum key range = 64, duplicates = 0 */
-
-#ifdef __GNUC__
-__inline
-#else
-#ifdef __cplusplus
-inline
-#endif
-#endif
-static unsigned int
-meminfo_mapping_hash (register const char *str, register unsigned int len)
-{
-  static const unsigned char asso_values[] =
-    {
-      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
-      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
-      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
-      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
-      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
-      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
-      68, 68, 68, 68, 68,  5, 25, 10, 20, 68,
-      15, 68, 25, 10, 68, 25, 15,  0, 10, 68,
-       5, 68, 20,  0, 35, 10, 15,  5, 68, 68,
-      68, 68, 68, 68, 68, 25, 68,  0, 30,  0,
-       0,  5,  5, 68,  0,  0, 68, 68,  0,  0,
-       0,  5, 68, 68,  5,  0, 15,  5, 68,  0,
-      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
-      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
-      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
-      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
-      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
-      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
-      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
-      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
-      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
-      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
-      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
-      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
-      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
-      68, 68, 68, 68, 68, 68
-    };
-  register int hval = len;
-
-  switch (hval)
-    {
-      default:
-        hval += asso_values[(unsigned char)str[9]];
-      /*FALLTHROUGH*/
-      case 9:
-      case 8:
-      case 7:
-      case 6:
-      case 5:
-      case 4:
-      case 3:
-      case 2:
-        hval += asso_values[(unsigned char)str[1]];
-      /*FALLTHROUGH*/
-      case 1:
-        hval += asso_values[(unsigned char)str[0]];
-        break;
-    }
-  return hval;
-}
-
-#ifdef __GNUC__
-__inline
-#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
-__attribute__ ((__gnu_inline__))
-#endif
-#endif
-const meminfo_mapping *
-meminfo_mapping_lookup (register const char *str, register unsigned int len)
-{
-  static const meminfo_mapping wordlist[] =
-    {
-      {""}, {""}, {""}, {""},
-      {"Slab",           MEMINFO_ID_SLAB},
-      {"Shmem",          MEMINFO_ID_SHMEM},
-      {"Mapped",         MEMINFO_ID_MAPPED},
-      {"Mlocked",        MEMINFO_ID_MLOCKED},
-      {"SwapFree",       MEMINFO_ID_SWAP_FREE},
-      {"SwapTotal",      MEMINFO_ID_SWAP_TOTAL},
-      {"SwapCached",     MEMINFO_ID_SWAP_CACHED},
-      {"Active",         MEMINFO_ID_ACTIVE},
-      {"MemFree",        MEMINFO_ID_MEM_FREE},
-      {"MemTotal",       MEMINFO_ID_MEM_TOTAL},
-      {"AnonPages",      MEMINFO_ID_ANON_PAGES},
-      {"PageTables",     MEMINFO_ID_PAGE_TABLES},
-      {"Cached",         MEMINFO_ID_CACHED},
-      {"Active(file)",   MEMINFO_ID_ACTIVE_FILE},
-      {"Inactive",       MEMINFO_ID_INACTIVE},
-      {"Writeback",      MEMINFO_ID_WRITEBACK},
-      {"SUnreclaim",     MEMINFO_ID_SUNRECLAIM},
-      {"Unevictable",    MEMINFO_ID_UNEVICTABLE},
-      {"Active(anon)",   MEMINFO_ID_ACTIVE_ANON},
-      {""},
-      {"Inactive(anon)", MEMINFO_ID_INACTIVE_ANON},
-      {"Dirty",          MEMINFO_ID_DIRTY},
-      {"CommitLimit",    MEMINFO_ID_COMMIT_LIMIT},
-      {"LowFree",        MEMINFO_ID_LOW_FREE},
-      {"LowTotal",       MEMINFO_ID_LOW_TOTAL},
-      {"Inactive(file)", MEMINFO_ID_INACTIVE_FILE},
-      {""},
-      {"VmallocUsed",    MEMINFO_ID_VMALLOC_USED},
-      {"VmallocChunk",   MEMINFO_ID_VMALLOC_CHUNK},
-      {"HighFree",       MEMINFO_ID_HIGH_FREE},
-      {"HighTotal",      MEMINFO_ID_HIGH_TOTAL},
-      {""},
-      {"Bounce",         MEMINFO_ID_BOUNCE},
-      {"Buffers",        MEMINFO_ID_BUFFERS},
-      {""}, {""}, {""},
-      {"KernelStack",    MEMINFO_ID_KERNEL_STACK},
-      {"VmallocTotal",   MEMINFO_ID_VMALLOC_TOTAL},
-      {""}, {""}, {""}, {""},
-      {"MemAvailable",   MEMINFO_ID_MEM_AVAILABLE},
-      {""}, {""}, {""}, {""},
-      {"Committed_AS",   MEMINFO_ID_COMMITTED_AS},
-      {""}, {""}, {""}, {""},
-      {"WritebackTmp",   MEMINFO_ID_WRITEBACK_TMP},
-      {""}, {""}, {""}, {""},
-      {"SReclaimable",   MEMINFO_ID_SRECLAIMABLE},
-      {""}, {""}, {""}, {""},
-      {"NFS_Unstable",   MEMINFO_ID_NFS_UNSTABLE}
-    };
-
-  if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
-    {
-      register int key = meminfo_mapping_hash (str, len);
-
-      if (key <= MAX_HASH_VALUE && key >= 0)
-        {
-          register const char *s = wordlist[key].name;
-
-          if (*str == *s && !strcmp (str + 1, s + 1))
-            return &wordlist[key];
-        }
-    }
-  return 0;
-}
diff --git a/src/common/meminfo-lookup.gperf b/src/common/meminfo-lookup.gperf
deleted file mode 100644 (file)
index 749f259..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-%{
-#include "procfs.h"
-%}
-meminfo_mapping;
-%language=ANSI-C
-%define slot-name name
-%define hash-function-name meminfo_mapping_hash
-%define lookup-function-name meminfo_mapping_lookup
-%readonly-tables
-%omit-struct-type
-%struct-type
-%includes
-%%
-MemTotal,       MEMINFO_ID_MEM_TOTAL
-MemFree,        MEMINFO_ID_MEM_FREE
-MemAvailable,   MEMINFO_ID_MEM_AVAILABLE
-Buffers,        MEMINFO_ID_BUFFERS
-Cached,         MEMINFO_ID_CACHED
-SwapCached,     MEMINFO_ID_SWAP_CACHED
-Active,         MEMINFO_ID_ACTIVE
-Inactive,       MEMINFO_ID_INACTIVE
-Active(anon),   MEMINFO_ID_ACTIVE_ANON
-Inactive(anon), MEMINFO_ID_INACTIVE_ANON
-Active(file),   MEMINFO_ID_ACTIVE_FILE
-Inactive(file), MEMINFO_ID_INACTIVE_FILE
-Unevictable,    MEMINFO_ID_UNEVICTABLE
-Mlocked,        MEMINFO_ID_MLOCKED
-HighTotal,      MEMINFO_ID_HIGH_TOTAL
-HighFree,       MEMINFO_ID_HIGH_FREE
-LowTotal,       MEMINFO_ID_LOW_TOTAL
-LowFree,        MEMINFO_ID_LOW_FREE
-SwapTotal,      MEMINFO_ID_SWAP_TOTAL
-SwapFree,       MEMINFO_ID_SWAP_FREE
-Dirty,          MEMINFO_ID_DIRTY
-Writeback,      MEMINFO_ID_WRITEBACK
-AnonPages,      MEMINFO_ID_ANON_PAGES
-Mapped,         MEMINFO_ID_MAPPED
-Shmem,          MEMINFO_ID_SHMEM
-Slab,           MEMINFO_ID_SLAB
-SReclaimable,   MEMINFO_ID_SRECLAIMABLE
-SUnreclaim,     MEMINFO_ID_SUNRECLAIM
-KernelStack,    MEMINFO_ID_KERNEL_STACK
-PageTables,     MEMINFO_ID_PAGE_TABLES
-NFS_Unstable,   MEMINFO_ID_NFS_UNSTABLE
-Bounce,         MEMINFO_ID_BOUNCE
-WritebackTmp,   MEMINFO_ID_WRITEBACK_TMP
-CommitLimit,    MEMINFO_ID_COMMIT_LIMIT
-Committed_AS,   MEMINFO_ID_COMMITTED_AS
-VmallocTotal,   MEMINFO_ID_VMALLOC_TOTAL
-VmallocUsed,    MEMINFO_ID_VMALLOC_USED
-VmallocChunk,   MEMINFO_ID_VMALLOC_CHUNK
diff --git a/src/common/module-data.c b/src/common/module-data.c
deleted file mode 100644 (file)
index 2ac2145..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * resourced
- *
- * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-/**
- * @file module-data.c
- * @desc Module data features
- **/
-
-#include "macro.h"
-#include "module-data.h"
-#include "trace.h"
-
-static struct shared_modules_data modules_data;
-
-struct shared_modules_data *get_shared_modules_data(void)
-{
-       return &modules_data;
-}
-
-void init_modules_arg(struct daemon_arg *darg)
-{
-       ret_msg_if(darg == NULL,
-                  "Init modules argument failed\n");
-       modules_data.darg = darg;
-}
diff --git a/src/common/module-data.h b/src/common/module-data.h
deleted file mode 100644 (file)
index a2caa64..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * resourced
- *
- * Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-/**
- * @file module-data.h
- * @desc Module data features
- **/
-
-#ifndef __MODULE_DATA_HANDLE_H__
-#define __MODULE_DATA_HANDLE_H__
-
-#include "init.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-struct swap_module_data {
-       int swap_state;                 /* swap SWAP_ON/SWAP_OFF */
-};
-
-struct shared_modules_data {
-       struct daemon_arg *darg;
-       struct swap_module_data swap_data;
-};
-
-struct shared_modules_data *get_shared_modules_data(void);
-
-void init_modules_arg(struct daemon_arg *darg);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __MODULE_DATA_HANDLE_H__ */
diff --git a/src/common/module.c b/src/common/module.c
deleted file mode 100644 (file)
index 32f32f8..0000000
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * resourced
- *
- * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-/**
- * @file module.c
- * @desc Module helper functions
- **/
-
-#include "macro.h"
-#include "module.h"
-#include "resourced.h"
-#include "trace.h"
-#include "dbus-handler.h"
-
-#include <glib.h>
-
-static GSList *modules_list;
-
-void add_module(const struct module_ops *module)
-{
-       ret_msg_if(!module, "Invalid module handler\n");
-
-       if (module->priority == MODULE_PRIORITY_EARLY)
-               modules_list = g_slist_prepend(modules_list, (gpointer)module);
-       else
-               modules_list = g_slist_append(modules_list, (gpointer)module);
-}
-
-void remove_module(const struct module_ops *module)
-{
-       modules_list = g_slist_remove(modules_list, (gpointer)module);
-}
-
-const struct module_ops *find_module(const char *name)
-{
-       GSList *iter;
-       const struct module_ops *module;
-
-       gslist_for_each_item(iter, modules_list) {
-               module = (struct module_ops *)iter->data;
-               if (!strncmp(module->name, name, strlen(module->name) + 1) &&
-                  (module->initalized == MODULE_INITIALIZED))
-                       return module;
-       }
-       return NULL;
-}
-
-void modules_check_runtime_support(void UNUSED *data)
-{
-       GSList *iter, *next;
-       const struct module_ops *module;
-       int ret;
-
-       gslist_for_each_safe(modules_list, iter, next, module) {
-               module = (const struct module_ops *)iter->data;
-               _D("check runtime support [%s] module\n", module->name);
-
-               if (!module->check_runtime_support)
-                       continue;
-
-               ret = module->check_runtime_support((void *)module);
-               if (ret != RESOURCED_ERROR_NONE) {
-                       _I("%s module is not supported in this environment", module->name);
-                       remove_module(module);
-                       continue;
-               }
-       }
-}
-
-static void module_initcall_level(void *data, int priority)
-{
-       GSList *iter;
-       struct module_ops *module;
-       int ret;
-
-       gslist_for_each_item(iter, modules_list) {
-               module = (struct module_ops *)iter->data;
-
-               assert(module);
-
-               if (module->priority < priority)
-                       continue;
-
-               if (module->initalized != MODULE_NONINITIALIZED)
-                       continue;
-
-               if (!module->init)
-                       continue;
-
-               ret = module->init(data);
-               /* Module disabled on runtime or just failed to start. */
-               if (ret < 0) {
-                       module->initalized = MODULE_DROPPED;
-                       _I("Fail to initialize [%s] module, dropped.", module->name);
-                       continue;
-               }
-
-               module->initalized = MODULE_INITIALIZED;
-       }
-}
-
-void modules_init(void *data)
-{
-       module_initcall_level(data, MODULE_PRIORITY_HIGH);
-}
-
-void modules_init_late(void *data)
-{
-       module_initcall_level(data, MODULE_PRIORITY_NORMAL);
-       module_initcall_level(data, MODULE_PRIORITY_LATE);
-}
-
-void modules_exit(void *data)
-{
-       GSList *iter;
-       struct module_ops *module;
-       int ret;
-
-       gslist_for_each_item(iter, modules_list) {
-               module = (struct module_ops *)iter->data;
-               if (module->exit && (module->initalized == MODULE_INITIALIZED)) {
-                       module->initalized = MODULE_NONINITIALIZED;
-                       ret = module->exit(data);
-                       if (ret < 0)
-                               _E("Fail to deinitialize [%s] module\n", module->name);
-                       else
-                               _D("Deinitialize [%s] module\n", module->name);
-               }
-       }
-       g_slist_free(modules_list);
-       modules_list = NULL;
-}
-
-void modules_restore(void *data)
-{
-       struct module_ops *module;
-       GSList *iter;
-       int ret;
-
-       gslist_for_each_item(iter, modules_list) {
-               module = (struct module_ops *)iter->data;
-
-               assert(module);
-
-               if (module->initalized != MODULE_INITIALIZED)
-                       continue;
-
-               if (!module->restore)
-                       continue;
-
-               ret = module->restore(data);
-               if (ret < 0) {
-                       _E("Fail to restore [%s] module", module->name);
-                       continue;
-               }
-
-               _I("Restored [%s] module", module->name);
-       }
-}
-
-void modules_dump(FILE *fp, int mode)
-{
-       GSList *iter;
-       const struct module_ops *module;
-
-       gslist_for_each_item(iter, modules_list) {
-               module = (struct module_ops *)iter->data;
-               if (module->initalized != MODULE_INITIALIZED)
-                       continue;
-
-               _D("dump [%s] module\n", module->name);
-               if (module->dump)
-                       module->dump(fp, mode, module->dump_data);
-       }
-}
-
-static void dbus_list_active_modules_handler(GDBusMethodInvocation *invocation, GVariant *params)
-{
-       struct module_ops *module;
-       GSList *list_iter;
-       GVariantBuilder builder, *sub_builder;
-
-       g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
-       sub_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
-
-       gslist_for_each_item(list_iter, modules_list) {
-               module = (struct module_ops *)list_iter->data;
-               if (module->initalized != MODULE_INITIALIZED)
-                       continue;
-
-               g_variant_builder_add(sub_builder, "s", module->name);
-       }
-       g_variant_builder_add_value(&builder, g_variant_new("as", sub_builder));
-       g_variant_builder_unref(sub_builder);
-
-       g_dbus_method_invocation_return_value(invocation,
-                       g_variant_builder_end(&builder));
-}
-
-static const char resourced_module_methods_xml[] =
-"<node>"
-"      <interface name ='"RESOURCED_INTERFACE_NAME"'>"
-"              <method name='ListActiveModuels'>"
-"                      <arg type='as' name='ActiveModules' direction='out'/>"
-"              </method>"
-"      </interface>"
-"</node>";
-
-static struct d_bus_method resourced_module_methods[] = {
-       { "ListActiveModuels", dbus_list_active_modules_handler },
-       /* Add methods here */
-};
-
-int modules_add_methods(void)
-{
-       return d_bus_register_methods(RESOURCED_OBJECT_PATH, resourced_module_methods_xml,
-               resourced_module_methods, ARRAY_SIZE(resourced_module_methods));
-}
diff --git a/src/common/module.h b/src/common/module.h
deleted file mode 100644 (file)
index 0cf1aa0..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * resourced
- *
- * Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-/**
- * @file module.h
- * @desc Module helper functions
- **/
-
-#ifndef __MODULE_HANDLE_H__
-#define __MODULE_HANDLE_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/**
- * @brief module_priority is used to initialization order of each
- * modules.
- */
-enum module_priority {
-       /**
-        * MODULE_PRIORITY_LATE is default priority of modules.
-        * These modules are initialized after other modules
-        * are initialized.
-        */
-       MODULE_PRIORITY_LATE = 0,
-
-       /**
-        * MODULE_PRIORITY_NORMAL modules are initialized after
-        * booting is done.
-        */
-       MODULE_PRIORITY_NORMAL,
-
-       /**
-        * MODULE_PRIORITY_HIGH modules are initialized
-        * as soon as resourced is started.
-        */
-       MODULE_PRIORITY_HIGH,
-
-       /**
-        * MODULE_PRIORITY_EARLY modules are initialized
-        * before MODULE_PRIORITY_NORMAL modules.
-        */
-       MODULE_PRIORITY_EARLY,
-};
-
-enum module_state {
-       MODULE_NONINITIALIZED,
-       MODULE_INITIALIZED,
-       MODULE_DROPPED,
-};
-
-/*
- * Each module must have at least those field defined:
- *  .priority (default : MODULE_PRIORITY_LATE)
- *  .name (name of the module, as string)
- *  .init (must return RESOURCED_ERROR_NONE on success)
- *  .exit (must return RESOURCED_ERROR_NONE on success)
- *  .restore (optional handler to calls on resourced is
- *  restarted. must return RESOURCED_ERROR_NONE on success))
- *
- *  All rest of callbacks are optional for module to work.
- *
- */
-struct module_ops {
-       enum module_priority priority;
-       enum module_state initalized;
-       const char *name;
-       int (*init) (void *data);
-       int (*exit) (void *data);
-       int (*restore) (void *data);
-       int (*check_runtime_support) (void *data);
-       int (*control) (void *data);
-       int (*status) (void *data);
-       int (*dump) (FILE *fp, int mode, void *dump_data);
-       void *dump_data;
-};
-
-void add_module(const struct module_ops *module);
-void remove_module(const struct module_ops *module);
-
-void modules_check_runtime_support(void *data);
-void modules_init(void *data);
-void modules_init_late(void *data);
-void modules_exit(void *data);
-void modules_restore(void *data);
-void modules_dump(FILE *fp, int mode);
-int modules_add_methods(void);
-
-const struct module_ops *find_module(const char *name);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __MODULE_HANDLE_H__ */
diff --git a/src/common/module/module-data.c b/src/common/module/module-data.c
new file mode 100644 (file)
index 0000000..2ac2145
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * resourced
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * @file module-data.c
+ * @desc Module data features
+ **/
+
+#include "macro.h"
+#include "module-data.h"
+#include "trace.h"
+
+static struct shared_modules_data modules_data;
+
+struct shared_modules_data *get_shared_modules_data(void)
+{
+       return &modules_data;
+}
+
+void init_modules_arg(struct daemon_arg *darg)
+{
+       ret_msg_if(darg == NULL,
+                  "Init modules argument failed\n");
+       modules_data.darg = darg;
+}
diff --git a/src/common/module/module-data.h b/src/common/module/module-data.h
new file mode 100644 (file)
index 0000000..a2caa64
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * resourced
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * @file module-data.h
+ * @desc Module data features
+ **/
+
+#ifndef __MODULE_DATA_HANDLE_H__
+#define __MODULE_DATA_HANDLE_H__
+
+#include "init.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+struct swap_module_data {
+       int swap_state;                 /* swap SWAP_ON/SWAP_OFF */
+};
+
+struct shared_modules_data {
+       struct daemon_arg *darg;
+       struct swap_module_data swap_data;
+};
+
+struct shared_modules_data *get_shared_modules_data(void);
+
+void init_modules_arg(struct daemon_arg *darg);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __MODULE_DATA_HANDLE_H__ */
diff --git a/src/common/module/module.c b/src/common/module/module.c
new file mode 100644 (file)
index 0000000..32f32f8
--- /dev/null
@@ -0,0 +1,234 @@
+/*
+ * resourced
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * @file module.c
+ * @desc Module helper functions
+ **/
+
+#include "macro.h"
+#include "module.h"
+#include "resourced.h"
+#include "trace.h"
+#include "dbus-handler.h"
+
+#include <glib.h>
+
+static GSList *modules_list;
+
+void add_module(const struct module_ops *module)
+{
+       ret_msg_if(!module, "Invalid module handler\n");
+
+       if (module->priority == MODULE_PRIORITY_EARLY)
+               modules_list = g_slist_prepend(modules_list, (gpointer)module);
+       else
+               modules_list = g_slist_append(modules_list, (gpointer)module);
+}
+
+void remove_module(const struct module_ops *module)
+{
+       modules_list = g_slist_remove(modules_list, (gpointer)module);
+}
+
+const struct module_ops *find_module(const char *name)
+{
+       GSList *iter;
+       const struct module_ops *module;
+
+       gslist_for_each_item(iter, modules_list) {
+               module = (struct module_ops *)iter->data;
+               if (!strncmp(module->name, name, strlen(module->name) + 1) &&
+                  (module->initalized == MODULE_INITIALIZED))
+                       return module;
+       }
+       return NULL;
+}
+
+void modules_check_runtime_support(void UNUSED *data)
+{
+       GSList *iter, *next;
+       const struct module_ops *module;
+       int ret;
+
+       gslist_for_each_safe(modules_list, iter, next, module) {
+               module = (const struct module_ops *)iter->data;
+               _D("check runtime support [%s] module\n", module->name);
+
+               if (!module->check_runtime_support)
+                       continue;
+
+               ret = module->check_runtime_support((void *)module);
+               if (ret != RESOURCED_ERROR_NONE) {
+                       _I("%s module is not supported in this environment", module->name);
+                       remove_module(module);
+                       continue;
+               }
+       }
+}
+
+static void module_initcall_level(void *data, int priority)
+{
+       GSList *iter;
+       struct module_ops *module;
+       int ret;
+
+       gslist_for_each_item(iter, modules_list) {
+               module = (struct module_ops *)iter->data;
+
+               assert(module);
+
+               if (module->priority < priority)
+                       continue;
+
+               if (module->initalized != MODULE_NONINITIALIZED)
+                       continue;
+
+               if (!module->init)
+                       continue;
+
+               ret = module->init(data);
+               /* Module disabled on runtime or just failed to start. */
+               if (ret < 0) {
+                       module->initalized = MODULE_DROPPED;
+                       _I("Fail to initialize [%s] module, dropped.", module->name);
+                       continue;
+               }
+
+               module->initalized = MODULE_INITIALIZED;
+       }
+}
+
+void modules_init(void *data)
+{
+       module_initcall_level(data, MODULE_PRIORITY_HIGH);
+}
+
+void modules_init_late(void *data)
+{
+       module_initcall_level(data, MODULE_PRIORITY_NORMAL);
+       module_initcall_level(data, MODULE_PRIORITY_LATE);
+}
+
+void modules_exit(void *data)
+{
+       GSList *iter;
+       struct module_ops *module;
+       int ret;
+
+       gslist_for_each_item(iter, modules_list) {
+               module = (struct module_ops *)iter->data;
+               if (module->exit && (module->initalized == MODULE_INITIALIZED)) {
+                       module->initalized = MODULE_NONINITIALIZED;
+                       ret = module->exit(data);
+                       if (ret < 0)
+                               _E("Fail to deinitialize [%s] module\n", module->name);
+                       else
+                               _D("Deinitialize [%s] module\n", module->name);
+               }
+       }
+       g_slist_free(modules_list);
+       modules_list = NULL;
+}
+
+void modules_restore(void *data)
+{
+       struct module_ops *module;
+       GSList *iter;
+       int ret;
+
+       gslist_for_each_item(iter, modules_list) {
+               module = (struct module_ops *)iter->data;
+
+               assert(module);
+
+               if (module->initalized != MODULE_INITIALIZED)
+                       continue;
+
+               if (!module->restore)
+                       continue;
+
+               ret = module->restore(data);
+               if (ret < 0) {
+                       _E("Fail to restore [%s] module", module->name);
+                       continue;
+               }
+
+               _I("Restored [%s] module", module->name);
+       }
+}
+
+void modules_dump(FILE *fp, int mode)
+{
+       GSList *iter;
+       const struct module_ops *module;
+
+       gslist_for_each_item(iter, modules_list) {
+               module = (struct module_ops *)iter->data;
+               if (module->initalized != MODULE_INITIALIZED)
+                       continue;
+
+               _D("dump [%s] module\n", module->name);
+               if (module->dump)
+                       module->dump(fp, mode, module->dump_data);
+       }
+}
+
+static void dbus_list_active_modules_handler(GDBusMethodInvocation *invocation, GVariant *params)
+{
+       struct module_ops *module;
+       GSList *list_iter;
+       GVariantBuilder builder, *sub_builder;
+
+       g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
+       sub_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
+
+       gslist_for_each_item(list_iter, modules_list) {
+               module = (struct module_ops *)list_iter->data;
+               if (module->initalized != MODULE_INITIALIZED)
+                       continue;
+
+               g_variant_builder_add(sub_builder, "s", module->name);
+       }
+       g_variant_builder_add_value(&builder, g_variant_new("as", sub_builder));
+       g_variant_builder_unref(sub_builder);
+
+       g_dbus_method_invocation_return_value(invocation,
+                       g_variant_builder_end(&builder));
+}
+
+static const char resourced_module_methods_xml[] =
+"<node>"
+"      <interface name ='"RESOURCED_INTERFACE_NAME"'>"
+"              <method name='ListActiveModuels'>"
+"                      <arg type='as' name='ActiveModules' direction='out'/>"
+"              </method>"
+"      </interface>"
+"</node>";
+
+static struct d_bus_method resourced_module_methods[] = {
+       { "ListActiveModuels", dbus_list_active_modules_handler },
+       /* Add methods here */
+};
+
+int modules_add_methods(void)
+{
+       return d_bus_register_methods(RESOURCED_OBJECT_PATH, resourced_module_methods_xml,
+               resourced_module_methods, ARRAY_SIZE(resourced_module_methods));
+}
diff --git a/src/common/module/module.h b/src/common/module/module.h
new file mode 100644 (file)
index 0000000..0cf1aa0
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * resourced
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * @file module.h
+ * @desc Module helper functions
+ **/
+
+#ifndef __MODULE_HANDLE_H__
+#define __MODULE_HANDLE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @brief module_priority is used to initialization order of each
+ * modules.
+ */
+enum module_priority {
+       /**
+        * MODULE_PRIORITY_LATE is default priority of modules.
+        * These modules are initialized after other modules
+        * are initialized.
+        */
+       MODULE_PRIORITY_LATE = 0,
+
+       /**
+        * MODULE_PRIORITY_NORMAL modules are initialized after
+        * booting is done.
+        */
+       MODULE_PRIORITY_NORMAL,
+
+       /**
+        * MODULE_PRIORITY_HIGH modules are initialized
+        * as soon as resourced is started.
+        */
+       MODULE_PRIORITY_HIGH,
+
+       /**
+        * MODULE_PRIORITY_EARLY modules are initialized
+        * before MODULE_PRIORITY_NORMAL modules.
+        */
+       MODULE_PRIORITY_EARLY,
+};
+
+enum module_state {
+       MODULE_NONINITIALIZED,
+       MODULE_INITIALIZED,
+       MODULE_DROPPED,
+};
+
+/*
+ * Each module must have at least those field defined:
+ *  .priority (default : MODULE_PRIORITY_LATE)
+ *  .name (name of the module, as string)
+ *  .init (must return RESOURCED_ERROR_NONE on success)
+ *  .exit (must return RESOURCED_ERROR_NONE on success)
+ *  .restore (optional handler to calls on resourced is
+ *  restarted. must return RESOURCED_ERROR_NONE on success))
+ *
+ *  All rest of callbacks are optional for module to work.
+ *
+ */
+struct module_ops {
+       enum module_priority priority;
+       enum module_state initalized;
+       const char *name;
+       int (*init) (void *data);
+       int (*exit) (void *data);
+       int (*restore) (void *data);
+       int (*check_runtime_support) (void *data);
+       int (*control) (void *data);
+       int (*status) (void *data);
+       int (*dump) (FILE *fp, int mode, void *dump_data);
+       void *dump_data;
+};
+
+void add_module(const struct module_ops *module);
+void remove_module(const struct module_ops *module);
+
+void modules_check_runtime_support(void *data);
+void modules_init(void *data);
+void modules_init_late(void *data);
+void modules_exit(void *data);
+void modules_restore(void *data);
+void modules_dump(FILE *fp, int mode);
+int modules_add_methods(void);
+
+const struct module_ops *find_module(const char *name);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __MODULE_HANDLE_H__ */
diff --git a/src/common/procfs.c b/src/common/procfs.c
deleted file mode 100644 (file)
index 4caead1..0000000
+++ /dev/null
@@ -1,1102 +0,0 @@
-/*
- * resourced
- *
- * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-/**
- * @file procfs.c
- *
- * @desc communicate with procfs in resourced
- *
- * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
- *
- */
-
-#include <assert.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include "resourced.h"
-#include "trace.h"
-#include "macro.h"
-#include "util.h"
-#include "procfs.h"
-#include "proc-common.h"
-#include "memory-cgroup.h"
-#include "module.h"
-#include "file-helper.h"
-#include "swap-common.h"
-#include "smaps.h"
-#include "notifier.h"
-#include "lowmem-handler.h"
-
-#define MEM_SWAP_RATIO                 0.5
-
-static struct sys_node_table sys_node_tables[] = {
-       { SYS_VM_SHRINK_MEMORY, "/proc/sys/vm/shrink_memory", 1, 1 },
-       { SYS_VM_COMPACT_MEMORY, "/proc/sys/vm/compact_memory", 1, 1 },
-       { },
-};
-
-int proc_get_cmdline(pid_t pid, char *cmdline, size_t maxcmdline)
-{
-       assert(cmdline);
-       assert(maxcmdline > 0);
-
-       char buf[PROC_BUF_MAX];
-       char cmdline_buf[PROC_NAME_MAX];
-       char *filename;
-       FILE *fp;
-
-       if (pid == 0)
-               snprintf(buf, sizeof(buf), "/proc/cmdline");
-       else
-               snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid);
-
-       fp = fopen(buf, "r");
-       if (fp == NULL)
-               return RESOURCED_ERROR_FAIL;
-
-       if (fgets(cmdline_buf, sizeof cmdline_buf, fp) == NULL) {
-               fclose(fp);
-               return RESOURCED_ERROR_FAIL;
-       }
-       fclose(fp);
-
-       filename = strrchr(cmdline_buf, '/');
-       if (filename == NULL)
-               filename = cmdline_buf;
-       else
-               filename = filename + 1;
-
-       strncpy(cmdline, filename, maxcmdline - 1);
-       cmdline[maxcmdline - 1] = '\0';
-
-       return RESOURCED_ERROR_NONE;
-}
-
-pid_t find_pid_from_cmdline(char *cmdline)
-{
-       pid_t pid = -1, foundpid = -1;
-       int ret = 0;
-       DIR *dp;
-       struct dirent *dentry;
-       char appname[PROC_NAME_MAX];
-
-       dp = opendir("/proc");
-       if (!dp) {
-               _E("BACKGRD MANAGE : fail to open /proc");
-               return RESOURCED_ERROR_FAIL;
-       }
-       while ((dentry = readdir(dp))) {
-               if (!isdigit(dentry->d_name[0]))
-                       continue;
-
-               pid = atoi(dentry->d_name);
-               if (!pid)
-                       continue;
-               ret = proc_get_cmdline(pid, appname, sizeof appname);
-               if (ret == RESOURCED_ERROR_NONE) {
-                       if (!strncmp(cmdline, appname, strlen(appname)+1)) {
-                               foundpid = pid;
-                               break;
-                       }
-               }
-       }
-       closedir(dp);
-       return foundpid;
-}
-
-int proc_get_oom_score_adj(int pid, int *oom_score_adj)
-{
-       char buf[sizeof(PROC_OOM_SCORE_ADJ_PATH) + MAX_DEC_SIZE(int)] = {0};
-       FILE *fp = NULL;
-
-       if (pid <= 0)
-               return RESOURCED_ERROR_FAIL;
-
-       snprintf(buf, sizeof(buf), PROC_OOM_SCORE_ADJ_PATH, pid);
-       fp = fopen(buf, "r");
-
-       if (fp == NULL) {
-               _E("fopen %s failed", buf);
-               return RESOURCED_ERROR_FAIL;
-       }
-       if (fgets(buf, sizeof(buf), fp) == NULL) {
-               fclose(fp);
-               return RESOURCED_ERROR_FAIL;
-       }
-       (*oom_score_adj) = atoi(buf);
-       fclose(fp);
-       return RESOURCED_ERROR_NONE;
-}
-
-int proc_set_oom_score_adj(int pid, int oom_score_adj, struct proc_app_info *pai)
-{
-       FILE *fp;
-       struct lowmem_control_data lowmem_data;
-       char buf[sizeof(PROC_OOM_SCORE_ADJ_PATH) + MAX_DEC_SIZE(int)] = {0};
-
-       snprintf(buf, sizeof(buf), PROC_OOM_SCORE_ADJ_PATH, pid);
-       fp = fopen(buf, "r+");
-       if (fp == NULL)
-               return RESOURCED_ERROR_FAIL;
-       if (fgets(buf, sizeof(buf), fp) == NULL) {
-               fclose(fp);
-               return RESOURCED_ERROR_FAIL;
-       }
-       fprintf(fp, "%d", oom_score_adj);
-       fclose(fp);
-
-       if (oom_score_adj >= OOMADJ_SU) {
-               lowmem_data.control_type = LOWMEM_MOVE_CGROUP;
-               lowmem_data.pid = pid;
-               lowmem_data.oom_score_adj = oom_score_adj;
-               lowmem_data.pai = pai;
-               resourced_notify(RESOURCED_NOTIFIER_MEM_CONTROL, &lowmem_data);
-       }
-
-       return RESOURCED_ERROR_NONE;
-}
-
-int proc_get_label(pid_t pid, char *label)
-{
-       char buf[PROC_BUF_MAX];
-       FILE *fp;
-
-       snprintf(buf, sizeof(buf), "/proc/%d/attr/current", pid);
-       fp = fopen(buf, "r");
-       if (fp == NULL)
-               return RESOURCED_ERROR_FAIL;
-
-       if (fgets(label, PROC_NAME_MAX-1, fp) == NULL) {
-               fclose(fp);
-               return RESOURCED_ERROR_FAIL;
-       }
-       fclose(fp);
-       return RESOURCED_ERROR_NONE;
-}
-
-int proc_get_mem_status(pid_t pid, unsigned int *vmswap_kb, unsigned int *vmrss_kb)
-{
-       char filename[PROC_BUF_MAX];
-       _cleanup_fclose_ FILE *fp = NULL;
-       unsigned int swap_kb = 0, rss_kb = 0;
-
-       snprintf(filename, PROC_BUF_MAX, "/proc/%d/status", pid);
-       fp = fopen(filename, "r");
-       if (!fp)
-               return RESOURCED_ERROR_FAIL;
-
-       if (vmrss_kb != NULL) {
-               while (fgets(filename, sizeof(filename), fp)) {
-                       /* Skip the lines, until first match */
-                       if (!strstart_with(filename, "VmRSS:"))
-                               continue;
-
-                       /* Read RSS value and end this loop. */
-                       if (sscanf(filename, "VmRSS: %u kB", &rss_kb) == 1)
-                               break;
-
-                       return RESOURCED_ERROR_NO_DATA;
-               }
-               *vmrss_kb = rss_kb;
-       }
-
-       if (vmswap_kb != NULL) {
-               /* Interate over rest of Vm* values */
-               while (fgets(filename, sizeof(filename), fp)) {
-                       /* Read VmSwap and return with positive result */
-                       if (sscanf(filename, "VmSwap: %d kB", &swap_kb) == 1)
-                               break;
-
-                       /* End of file before VmSwap read, return with error */
-                       if (feof(fp))
-                               return RESOURCED_ERROR_NO_DATA;
-               }
-               *vmswap_kb = swap_kb;
-       }
-
-       return RESOURCED_ERROR_NONE;
-}
-
-int proc_get_uss(pid_t pid, unsigned int *uss)
-{
-       _cleanup_smaps_free_ struct smaps *smaps = NULL;
-       int ret;
-
-       *uss = 0;
-
-       /*
-        * USS memory usage is number of KB accounted to a process
-        * where only private (non-shared) data are accounted.
-        *
-        * USS provides the value how much memory will be freed after
-        * termination of process.
-        */
-       ret = smaps_get(pid, &smaps,
-                       (SMAPS_MASK_PRIVATE_CLEAN | SMAPS_MASK_PRIVATE_DIRTY));
-
-       if (ret < 0) {
-               _E("Error while reading smaps or totmaps for pid %d", pid);
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       *uss += smaps->sum[SMAPS_ID_PRIVATE_CLEAN];
-       *uss += smaps->sum[SMAPS_ID_PRIVATE_DIRTY];
-
-       return RESOURCED_ERROR_NONE;
-}
-
-int proc_get_zram_usage(pid_t pid, unsigned int *usage_kb)
-{
-       int ret;
-       struct meminfo mi;
-       static unsigned int swap_total_kb = 0;
-       unsigned int proc_swap_usage_kb;
-       unsigned long long zram_usage_bytes;
-
-       /* Read total swap size just once and cache it */
-       if (!swap_total_kb) {
-               ret = proc_get_meminfo(&mi, MEMINFO_MASK_SWAP_TOTAL);
-               if (ret < 0) {
-                       _E("Failed to get %s: %m",
-                          meminfo_id_to_string(MEMINFO_ID_SWAP_TOTAL));
-                       return RESOURCED_ERROR_FAIL;
-               }
-               swap_total_kb = mi.value[MEMINFO_ID_SWAP_TOTAL];
-       }
-
-       /* Read usage of Swap (VmSwap) of interested process */
-       ret = proc_get_mem_status(pid, &proc_swap_usage_kb, NULL);
-       if (ret != RESOURCED_ERROR_NONE)
-               return ret;
-
-       /* Read current total memory usage of zram device */
-       ret = fread_nth_ulonglong(SWAP_ZRAM_SYSFILE"mm_stat", 2, &zram_usage_bytes);
-       if (ret == -ENOENT) {
-               ret = fread_ulonglong(SWAP_ZRAM_SYSFILE"mem_used_total", &zram_usage_bytes);
-       }
-
-       if (ret < 0)
-               return RESOURCED_ERROR_FAIL;
-
-       /*
-        * Calculate aproximated value of zram usage for selected process
-        * by formula: proc_zram_usage = ( VmSwap x ZramMemoryUsage )/SwapTotal
-        */
-       *usage_kb = (int)((float)proc_swap_usage_kb * BYTE_TO_KBYTE(zram_usage_bytes) / swap_total_kb);
-
-       return RESOURCED_ERROR_NONE;
-}
-
-int proc_get_approx_mem_usage(pid_t pid, unsigned int *usage_kb)
-{
-       int ret;
-       unsigned long resident_pages = 0, shared_pages = 0;
-       char filename[PROC_BUF_MAX];
-       _cleanup_fclose_ FILE *fp = NULL;
-
-       snprintf(filename, PROC_BUF_MAX, "/proc/%d/statm", pid);
-       fp = fopen(filename, "r");
-       if (!fp)
-               return RESOURCED_ERROR_FAIL;
-
-       /*
-        * For quick read, open code by putting numbers directly
-        * expected format is
-        * seq_printf(m, "%lu %lu %lu %lu 0 %lu 0\n",
-        *               size, resident, shared, text, data);
-        */
-       ret = fscanf(fp, "%*s %lu %lu %*s %*s %*s %*s\n", &resident_pages, &shared_pages);
-       if (ret < 0)
-               return RESOURCED_ERROR_FAIL;
-
-       if (resident_pages < shared_pages) {
-               _E("# resident page should be larger than or equal to # shared page");
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       /*
-        * The value resident - shared is mostly similar to Uss.
-        */
-       *usage_kb = BYTE_TO_KBYTE((unsigned long long)(resident_pages - shared_pages) << PAGE_SHIFT);
-       return RESOURCED_ERROR_NONE;
-}
-
-/**
- * @desc get total memory usage from VmSwap and VmRSS.
- * @return negative value if error or pid doesn't exist
- */
-int proc_get_mem_usage(pid_t pid, unsigned int *usage)
-{
-       int ret;
-       unsigned int vmswap = 0, total = 0;
-
-       ret = proc_get_approx_mem_usage(pid, &total);
-       if (ret < 0) {
-               _E("Failed to get usage : %d", pid);
-               return ret;
-       }
-
-       if (swap_get_state() == SWAP_ON) {
-               ret = proc_get_mem_status(pid, &vmswap, NULL);
-               if (ret != RESOURCED_ERROR_NONE)
-                       goto out;
-
-               total += vmswap;
-       }
-out:
-       *usage = total;
-       return RESOURCED_ERROR_NONE;
-}
-
-/**
- * @desc get how much ram is used in each application
- * @return negative value if error or pid doesn't exist
- */
-int proc_get_ram_usage(pid_t pid, unsigned int *usage_kb)
-{
-       int ret;
-       unsigned int vmswap_kb = 0, total_kb = 0;
-
-       ret = proc_get_approx_mem_usage(pid, &total_kb);
-       if (ret < 0) {
-               _E("Failed to get usage : %d", pid);
-               return ret;
-       }
-
-       if (swap_get_state() == SWAP_ON) {
-               ret = proc_get_mem_status(pid, &vmswap_kb, NULL);
-               if (ret != RESOURCED_ERROR_NONE)
-                       goto out;
-
-               /*
-                * If it is necessary to know real ram size about each application,
-                * it should consider compression ratio.
-                */
-               vmswap_kb *= MEM_SWAP_RATIO;
-               total_kb += vmswap_kb;
-       }
-out:
-       *usage_kb = total_kb;
-       return RESOURCED_ERROR_NONE;
-}
-
-unsigned int proc_get_mem_available(void)
-{
-       struct meminfo mi;
-       int ret;
-
-       ret = proc_get_meminfo(&mi, MEMINFO_MASK_MEM_AVAILABLE);
-       if (ret < 0) {
-               _E("Failed to get %s: %m",
-                               meminfo_id_to_string(MEMINFO_ID_MEM_AVAILABLE));
-               return 0;
-       }
-
-       return KBYTE_TO_MBYTE(mi.value[MEMINFO_ID_MEM_AVAILABLE]);
-}
-
-unsigned int proc_get_swap_free(void)
-{
-       struct meminfo mi;
-       int ret;
-
-       ret = proc_get_meminfo(&mi, MEMINFO_MASK_SWAP_FREE);
-       if (ret < 0) {
-               _E("Failed to get %s: %m",
-                  meminfo_id_to_string(MEMINFO_ID_SWAP_FREE));
-               return 0;
-       }
-
-       return mi.value[MEMINFO_ID_SWAP_FREE];
-}
-
-unsigned int proc_get_swap_total(void)
-{
-       struct meminfo mi;
-       int ret;
-
-       ret = proc_get_meminfo(&mi, MEMINFO_MASK_SWAP_TOTAL);
-       if (ret < 0) {
-               _E("Failed to get %s: %m",
-                  meminfo_id_to_string(MEMINFO_ID_SWAP_TOTAL));
-               return 0;
-       }
-
-       return mi.value[MEMINFO_ID_SWAP_TOTAL];
-}
-
-int proc_get_cpu_time(pid_t pid, unsigned long *utime,
-               unsigned long *stime, unsigned long *starttime)
-{
-       char proc_path[sizeof(PROC_STAT_PATH) + MAX_DEC_SIZE(int)];
-       _cleanup_fclose_ FILE *fp = NULL;
-
-       assert(utime != NULL);
-       assert(stime != NULL);
-
-       snprintf(proc_path, sizeof(proc_path), PROC_STAT_PATH, pid);
-       fp = fopen(proc_path, "r");
-       if (fp == NULL)
-               return RESOURCED_ERROR_FAIL;
-
-       if (fscanf(fp, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s") < 0)
-               return RESOURCED_ERROR_FAIL;
-
-       if (fscanf(fp, "%lu %lu", utime, stime) < 1)
-               return RESOURCED_ERROR_FAIL;
-
-       if (fscanf(fp, "%*s %*s %*s %*s %*s %*s") < 0)
-               return RESOURCED_ERROR_FAIL;
-
-       if (fscanf(fp, "%lu", starttime) < 1)
-               return RESOURCED_ERROR_FAIL;
-
-       return RESOURCED_ERROR_NONE;
-}
-
-unsigned int proc_get_cpu_number(void)
-{
-       char buf[PATH_MAX];
-       FILE *fp;
-       int cpu = 0;
-
-       fp = fopen("/proc/cpuinfo", "r");
-
-       if (!fp) {
-               _E("/proc/cpuinfo open failed");
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       while (fgets(buf, PATH_MAX, fp) != NULL) {
-               if (!strncmp(buf, "processor", 9))
-                       cpu++;
-       }
-
-       fclose(fp);
-       return cpu;
-}
-
-int proc_get_exepath(pid_t pid, char *buf, int len)
-{
-       char path[PROC_BUF_MAX];
-       int ret = 0;
-
-       snprintf(path, sizeof(path), "/proc/%d/exe", pid);
-       ret = readlink(path, buf, len-1);
-       if (ret > 0)
-               buf[ret] = '\0';
-       else
-               buf[0] = '\0';
-       return RESOURCED_ERROR_NONE;
-}
-
-static int proc_get_data(char *path, char *buf, int len)
-{
-       _cleanup_close_ int fd = -1;
-       int ret;
-
-       fd = open(path, O_RDONLY);
-       if (fd < 0)
-               return RESOURCED_ERROR_FAIL;
-
-       ret = read(fd, buf, len-1);
-       if (ret < 0) {
-               buf[0] = '\0';
-               return RESOURCED_ERROR_FAIL;
-       }
-       buf[ret] = '\0';
-       return RESOURCED_ERROR_NONE;
-}
-
-int proc_get_raw_cmdline(pid_t pid, char *buf, int len)
-{
-       char path[PROC_BUF_MAX];
-       snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
-       return proc_get_data(path, buf, len);
-}
-
-int proc_get_stat(pid_t pid, char *buf, int len)
-{
-       char path[PROC_BUF_MAX];
-       snprintf(path, sizeof(path), "/proc/%d/stat", pid);
-       return proc_get_data(path, buf, len);
-}
-
-int proc_get_status(pid_t pid, char *buf, int len)
-{
-       char path[PROC_BUF_MAX];
-       snprintf(path, sizeof(path), "/proc/%d/status", pid);
-       return proc_get_data(path, buf, len);
-}
-
-int proc_sys_node_trigger(enum sys_node_id sys_node_id)
-{
-       FILE *fp = NULL;
-
-       if (sys_node_id >= ARRAY_SIZE(sys_node_tables)) {
-               _E("sys_node_id[%d] is out of range.\n", sys_node_id);
-               return RESOURCED_ERROR_FAIL;
-       }
-       if (!sys_node_tables[sys_node_id].valid) {
-               _E("sys_node_id[%d] is not valid.\n", sys_node_id);
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       /* open and check if the path exists, else return fail */
-       fp = fopen(sys_node_tables[sys_node_id].path, "w");
-       if (fp == NULL) {
-               _E("Failed to open %s: %m\n",
-                       sys_node_tables[sys_node_id].path);
-               sys_node_tables[sys_node_id].valid = 0;
-               return RESOURCED_ERROR_FAIL;
-       }
-       fputc(sys_node_tables[sys_node_id].value, fp);
-       fclose(fp);
-       return RESOURCED_ERROR_NONE;
-}
-
-static const char* const meminfo_string_lookup[MEMINFO_ID_MAX] = {
-       [MEMINFO_ID_MEM_TOTAL]     = "MemTotal",
-       [MEMINFO_ID_MEM_FREE]      = "MemFree",
-       [MEMINFO_ID_MEM_AVAILABLE] = "MemAvailable",
-       [MEMINFO_ID_BUFFERS]       = "Buffers",
-       [MEMINFO_ID_CACHED]        = "Cached",
-       [MEMINFO_ID_SWAP_CACHED]   = "SwapCached",
-       [MEMINFO_ID_ACTIVE]        = "Active",
-       [MEMINFO_ID_INACTIVE]      = "Inactive",
-       [MEMINFO_ID_ACTIVE_ANON]   = "Active(anon)",
-       [MEMINFO_ID_INACTIVE_ANON] = "Inactive(anon)",
-       [MEMINFO_ID_ACTIVE_FILE]   = "Active(file)",
-       [MEMINFO_ID_INACTIVE_FILE] = "Inactive(file)",
-       [MEMINFO_ID_UNEVICTABLE]   = "Unevictable",
-       [MEMINFO_ID_MLOCKED]       = "Mlocked",
-       [MEMINFO_ID_HIGH_TOTAL]    = "HighTotal",
-       [MEMINFO_ID_HIGH_FREE]     = "HighFree",
-       [MEMINFO_ID_LOW_TOTAL]     = "LowTotal",
-       [MEMINFO_ID_LOW_FREE]      = "LowFree",
-       [MEMINFO_ID_SWAP_TOTAL]    = "SwapTotal",
-       [MEMINFO_ID_SWAP_FREE]     = "SwapFree",
-       [MEMINFO_ID_DIRTY]         = "Dirty",
-       [MEMINFO_ID_WRITEBACK]     = "Writeback",
-       [MEMINFO_ID_ANON_PAGES]    = "AnonPages",
-       [MEMINFO_ID_MAPPED]        = "Mapped",
-       [MEMINFO_ID_SHMEM]         = "Shmem",
-       [MEMINFO_ID_SLAB]          = "Slab",
-       [MEMINFO_ID_SRECLAIMABLE]  = "SReclaimable",
-       [MEMINFO_ID_SUNRECLAIM]    = "SUnreclaim",
-       [MEMINFO_ID_KERNEL_STACK]  = "KernelStack",
-       [MEMINFO_ID_PAGE_TABLES]   = "PageTables",
-       [MEMINFO_ID_NFS_UNSTABLE]  = "NFS_Unstable",
-       [MEMINFO_ID_BOUNCE]        = "Bounce",
-       [MEMINFO_ID_WRITEBACK_TMP] = "WritebackTmp",
-       [MEMINFO_ID_COMMIT_LIMIT]  = "CommitLimit",
-       [MEMINFO_ID_COMMITTED_AS]  = "Committed_AS",
-       [MEMINFO_ID_VMALLOC_TOTAL] = "VmallocTotal",
-       [MEMINFO_ID_VMALLOC_USED]  = "VmallocUsed",
-       [MEMINFO_ID_VMALLOC_CHUNK] = "VmallocChunk",
-};
-
-const char *meminfo_id_to_string(enum meminfo_id id)
-{
-       assert(id >= 0 && id < MEMINFO_ID_MAX);
-
-       return meminfo_string_lookup[id];
-}
-
-int proc_get_meminfo(struct meminfo *mi, unsigned long long mask)
-{
-       _cleanup_fclose_ FILE *f = NULL;
-       unsigned long long remain_mask = mask;
-       char buf[LINE_MAX];
-
-       assert(mi);
-
-       memset(mi, 0x0, sizeof(struct meminfo));
-
-       f = fopen("/proc/meminfo", "r");
-       if (!f) {
-               _E("Failed to read /proc/meminfo");
-               return -errno;
-       }
-
-       if (remain_mask & MEMINFO_MASK_MEM_AVAILABLE)
-               remain_mask |= (MEMINFO_MASK_MEM_FREE |
-                               MEMINFO_MASK_CACHED);
-
-       while (remain_mask) {
-               _cleanup_free_ char *k = NULL;
-               unsigned int v = 0;
-               enum meminfo_id id;
-               size_t l;
-
-               if (!fgets(buf, sizeof(buf), f)) {
-                       if (ferror(f))
-                               return -errno;
-                       break;
-               }
-
-               l = strcspn(buf, ":");
-               if (!l)
-                       break;
-
-               k = strndup(buf, l);
-               if (!k)
-                       return -errno;
-
-               id = meminfo_string_to_id(k);
-               if (id < 0 || id >= MEMINFO_ID_MAX)
-                       continue;
-
-               if (!(remain_mask & (1ULL << id)))
-                       continue;
-
-               remain_mask &= ~((1ULL << id));
-
-               if (sscanf(buf + l + 1, "%d", &v) != 1)
-                       break;
-
-               mi->value[id] = v;
-       }
-
-       if (remain_mask & MEMINFO_MASK_MEM_AVAILABLE) {
-               mi->value[MEMINFO_ID_MEM_AVAILABLE] =
-                       mi->value[MEMINFO_ID_MEM_FREE]
-                       + mi->value[MEMINFO_ID_CACHED];
-
-               remain_mask &= ~MEMINFO_MASK_MEM_AVAILABLE;
-       }
-
-       if (remain_mask) {
-               enum meminfo_id i;
-
-               for (i = 0; i < MEMINFO_ID_MAX; i++)
-                       if (remain_mask & (1ULL << i))
-                               _E("Failed to get meminfo: '%s'",
-                                  meminfo_id_to_string(i));
-       }
-
-       return RESOURCED_ERROR_NONE;
-}
-
-static int parse_spanned_pages(const char *s, regmatch_t *match,
-                               unsigned int parse_tag, void *data)
-{
-       char *e;
-       unsigned long v;
-       unsigned long *parse_v = (unsigned long *)data;
-
-       v = strtoul(s + match[1].rm_so, &e, 0);
-       *parse_v += v;
-
-       return 0;
-}
-
-int proc_get_ram_total(unsigned int *total_kb)
-{
-       unsigned long total_spanned = 0;
-       static unsigned int total_ram_kb = 0;
-       int ret;
-       const struct parse_arg args[] = {
-               PARSE_TAG("spanned[[:blank:]]+([0-9]+)\n",
-                         parse_spanned_pages, SPANNED),
-               PARSE_TAG_EMPTY(),
-       };
-
-       if (total_ram_kb > 0) {
-               *total_kb = total_ram_kb;
-               return RESOURCED_ERROR_NONE;
-       }
-
-       ret = proc_parse_zoneinfo(args, &total_spanned);
-       if (ret != RESOURCED_ERROR_NONE)
-               return RESOURCED_ERROR_NO_DATA;
-
-       total_ram_kb = (unsigned int)BYTE_TO_KBYTE((unsigned long long)total_spanned << PAGE_SHIFT);
-       *total_kb = total_ram_kb;
-
-       return RESOURCED_ERROR_NONE;
-}
-
-static inline char *proc_skip_blanks(const char *s)
-{
-       while (s && (isblank(*s) || !isalnum(*s)))
-               ++s;
-       return (char*)s;
-}
-
-#define PROC_MAX_REG_MATCH     6
-
-static int proc_find_match(char *s, const struct parse_arg *parse,
-                               void *data, size_t *parsed)
-{
-       regex_t regex;
-       regmatch_t match[PROC_MAX_REG_MATCH];
-       int result;
-
-       if (!s || !(*s != '\0'))
-               return -EINVAL;
-
-       if (!parse->callback)
-               return 0;
-
-       *parsed = 0;
-
-       result = regcomp(&regex, parse->re_exp, REG_EXTENDED);
-       if (!result) {
-               result = regexec(&regex, s, ARRAY_SIZE(match), match, 0);
-               if (!result) {
-                       regmatch_t *m = match;
-
-                       result =  parse->callback(s, match, parse->tag, data);
-                       if (result)
-                               goto leave;
-                       while ((m - match) < PROC_MAX_REG_MATCH &&
-                           m->rm_so >= 0 && m->rm_eo > 0)
-                               ++m;
-
-                       *parsed = m > match ? (--m)->rm_eo + 1 : 0;
-               }
-leave:
-               regfree(&regex);
-       }
-       return result;
-}
-
-/**
- * @brief  Rather basic parser that relies on provided arguments,
- *         specifying the actual expression to look for.
- *         Note that it does not make any assumptions as to how
- *         the input to be parsed is actual formated and  what is the
- *         layout of the information held within it.
- *         - mind it as badly specified arguments might result in a failure
- *         to identify potential match or finding a match but not one that
- *         has been expected. It is up to the caller to perform
- *         the actual formatting of data.
- *         Parsing is done per line with possible multiple regexes.
- * @return Returns number of found matches against supplied parse arguments
- */
-static int proc_parse_single(const char *buffer,
-                            const struct parse_arg *parse_args,
-                            void *data)
-{
-       char *s = (char*)buffer;
-       size_t size;
-       unsigned int match = 0;
-
-       while (s && *s != '\n' && *s != '\0') {
-               const struct parse_arg *p = parse_args;
-
-               size = 0;
-               s = proc_skip_blanks(s);
-
-               while (proc_find_match(s, p, data, &size))
-                       ++p;
-
-               if (!size)
-                       break;
-               s += size;
-               ++match;
-       }
-       return match;
-}
-
-/**
- * @brief Simplified procfs parser
- *
- *  Reads the procfs entry line by line triggering regex match
- *  function for each supplied argument.
- *  Note: The set of arguments should end with an empty one.
- *
- * @return returns 0 upon successfully calling the actual parsing
- *        procedure at least once, error code otherwise.
- *        Note: it is up to the caller to properly handle
- *        callbacks triggered upon each match found and to determine
- *        if parsing itself actually succeeded.
- */
-int proc_parse_entry(const char *path, const struct parse_arg *parse_args,
-                       void *data)
-{
-       char buf[LINE_MAX];
-       _cleanup_fclose_ FILE *f = NULL;
-
-       f = fopen(path, "r");
-       if (!f)
-               return -errno;
-
-       while (fgets(buf, sizeof(buf), f))
-               proc_parse_single(buf, parse_args, data);
-       return ferror(f) ? -errno : 0;
-}
-
-int proc_get_uptime(unsigned long *uptime)
-{
-       _cleanup_fclose_ FILE *fp = NULL;
-       double stime;
-
-       fp = fopen("/proc/uptime", "r");
-       if (fp == NULL)
-               return RESOURCED_ERROR_FAIL;
-
-       if (fscanf(fp, "%lf %*s", &stime) < 0)
-               return RESOURCED_ERROR_FAIL;
-
-       *uptime = (unsigned long)stime;
-       return RESOURCED_ERROR_NONE;
-}
-
-/**
- * @brief print simple memory info with rss and memtotal
- *
- *  Reads the procfs about all process id and print RSS usage.
- *  Note: If fp is valid, the result is written by desired file.
- *            Otherwise, it printed message through dlog.
- */
-void proc_print_meninfo(FILE *fp)
-{
-       _cleanup_closedir_ DIR *dir = NULL;
-       struct dirent *de;
-       pid_t pid, caller;
-       char cmdline[PATH_MAX];
-       _cleanup_fclose_ FILE *output_file = NULL;
-       int oom_score_adj, ret;
-       unsigned int rss, swap;
-       struct meminfo mi;
-       unsigned int free_kb = 0;
-       unsigned int total_mem_kb = 0, available_kb = 0, used_kb;
-       unsigned int swap_total_kb = 0, swap_free_kb = 0, swap_used_kb;
-       unsigned long long zram_used_bytes;
-
-       dir = opendir("/proc");
-       if (dir == NULL) {
-               _E("cannot read directory /proc.");
-               return;
-       }
-
-       LOG_DUMP(fp, "     PID    RSS    SWAP    OOM_SCORE    COMMAND\n");
-
-       caller = getpid();
-       while ((de = readdir(dir)) != NULL) {
-               pid = atoi(de->d_name);
-
-               /* exclude negative value which means string value and kernel thread */
-               if (pid < 1 || pid == caller)
-                       continue;
-
-               ret = proc_get_cmdline(pid, cmdline, sizeof cmdline);
-               if (ret)
-                       continue;
-
-               ret = proc_get_mem_status(pid, &swap, &rss);
-               if (ret)
-                       continue;
-
-               ret = proc_get_oom_score_adj(pid, &oom_score_adj);
-               if (ret)
-                       continue;
-
-               LOG_DUMP(fp, "%8d %8u  %8u %8d          %s\n",
-                               pid,
-                               rss,
-                               swap,
-                               oom_score_adj,
-                               cmdline);
-
-       } /* end of while */
-
-       ret = proc_get_meminfo(&mi,
-                       (MEMINFO_MASK_MEM_TOTAL |
-                        MEMINFO_MASK_MEM_FREE |
-                        MEMINFO_MASK_MEM_AVAILABLE |
-                        MEMINFO_MASK_CACHED |
-                        MEMINFO_MASK_SWAP_TOTAL |
-                        MEMINFO_MASK_SWAP_FREE));
-       if (ret < 0) {
-               _E("Failed to get meminfo");
-               return;
-       }
-
-       total_mem_kb = mi.value[MEMINFO_ID_MEM_TOTAL];
-       free_kb = mi.value[MEMINFO_ID_MEM_FREE];
-       available_kb = mi.value[MEMINFO_ID_MEM_AVAILABLE];
-       swap_total_kb = mi.value[MEMINFO_ID_SWAP_TOTAL];
-       swap_free_kb = mi.value[MEMINFO_ID_SWAP_FREE];
-
-       used_kb = total_mem_kb - available_kb;
-       swap_used_kb = swap_total_kb - swap_free_kb;
-
-       ret = fread_nth_ulonglong(SWAP_ZRAM_SYSFILE"mm_stat", 2, &zram_used_bytes);
-       if (ret == -ENOENT) {
-               ret = fread_ulonglong(SWAP_ZRAM_SYSFILE"mem_used_total", &zram_used_bytes);
-       }
-
-       if (ret != RESOURCED_ERROR_NONE)
-               zram_used_bytes = 0;
-
-       LOG_DUMP(fp, "====================================================================\n");
-       LOG_DUMP(fp, "Total RAM size: \t%15d MB( %6d kB)\n",
-                       KBYTE_TO_MBYTE(total_mem_kb), total_mem_kb);
-       LOG_DUMP(fp, "Used (Mem+Reclaimable): %15d MB( %6d kB)\n",
-                       KBYTE_TO_MBYTE(total_mem_kb - free_kb), total_mem_kb - free_kb);
-       LOG_DUMP(fp, "Used (Mem+Swap): \t%15d MB( %6d kB)\n",
-                       KBYTE_TO_MBYTE(used_kb), used_kb);
-       LOG_DUMP(fp, "Used (Mem):  \t\t%15d MB( %6d kB)\n",
-                       KBYTE_TO_MBYTE(used_kb), used_kb);
-       LOG_DUMP(fp, "Used (Swap): \t\t%15d MB( %6d kB)\n",
-                       KBYTE_TO_MBYTE(swap_used_kb), swap_used_kb);
-       LOG_DUMP(fp, "Used (Zram block device): %13d MB( %6d kB)\n",
-                       (int)BYTE_TO_MBYTE(zram_used_bytes), (int)BYTE_TO_KBYTE(zram_used_bytes));
-       LOG_DUMP(fp, "Mem Free:\t\t%15d MB( %6d kB)\n",
-                       KBYTE_TO_MBYTE(free_kb), free_kb);
-       LOG_DUMP(fp,  "Available (Free+Reclaimable):%10d MB( %6d kB)\n",
-                       KBYTE_TO_MBYTE(available_kb), available_kb);
-       return;
-}
-
-int proc_get_buddyinfo(const char *zone, struct buddyinfo *bi)
-{
-       _cleanup_fclose_ FILE *f = NULL;
-       char buf[LINE_MAX];
-
-       g_assert(zone);
-       g_assert(bi);
-
-       f = fopen("/proc/buddyinfo", "re");
-       if (!f)
-               return -errno;
-
-       for (;;) {
-               int n;
-               char zonename[32] = { 0, };
-
-               if (!fgets(buf, sizeof(buf), f)) {
-                       if (ferror(f))
-                               return -errno;
-
-                       break;
-               }
-
-               n = sscanf(buf, "Node %d, zone %31s %d %d %d %d %d %d %d %d %d %d %d",
-                          &bi->node,
-                          zonename,
-                          &bi->page[PAGE_4K],
-                          &bi->page[PAGE_8K],
-                          &bi->page[PAGE_16K],
-                          &bi->page[PAGE_32K],
-                          &bi->page[PAGE_64K],
-                          &bi->page[PAGE_128K],
-                          &bi->page[PAGE_256K],
-                          &bi->page[PAGE_512K],
-                          &bi->page[PAGE_1M],
-                          &bi->page[PAGE_2M],
-                          &bi->page[PAGE_4M]);
-               if (n != 13)
-                       break;
-
-               if (!streq(zone, zonename))
-                       continue;
-
-               return 0;
-       }
-
-       return -ENODATA;
-}
-
-void proc_swap_free(struct proc_swaps *swap)
-{
-       if (!swap)
-               return;
-
-       free(swap->filename);
-       free(swap->type);
-       free(swap);
-}
-
-void proc_swaps_free(struct proc_swaps **swaps)
-{
-       int i;
-
-       if (!swaps)
-               return;
-
-       for (i = 0; swaps[i]; i++)
-               proc_swap_free(swaps[i]);
-
-       free(swaps);
-}
-
-int proc_get_swaps(struct proc_swaps ***swaps)
-{
-       _cleanup_proc_swaps_free_ struct proc_swaps **ss = NULL;
-       _cleanup_fclose_ FILE *f = NULL;
-       char buf[LINE_MAX];
-       size_t cnt = 0;
-
-       assert(swaps);
-       assert(!*swaps);
-
-       f = fopen("/proc/swaps", "re");
-       if (!f)
-               return -errno;
-
-       for (;;) {
-               _cleanup_proc_swap_free_ struct proc_swaps *swap = NULL;
-
-               if (!fgets(buf, sizeof(buf), f)) {
-                       if (ferror(f))
-                               return -errno;
-
-                       break;
-               }
-
-               swap = calloc(sizeof(struct proc_swaps), 1);
-               if (!swap)
-                       return -ENOMEM;
-
-               if (sscanf(buf, "%ms %ms %u %u %d",
-                          &swap->filename,
-                          &swap->type,
-                          &swap->size,
-                          &swap->used,
-                          &swap->priority) != 5)
-                       continue;
-
-               ss = (struct proc_swaps **)realloc(ss, sizeof(struct proc_swaps *) * (cnt + 2));
-               if (!ss)
-                       return -ENOMEM;
-
-               ss[cnt++] = swap;
-               ss[cnt] = NULL;
-               swap = NULL;
-       }
-
-       *swaps = ss;
-       ss = NULL;
-
-       return cnt;
-}
diff --git a/src/common/procfs.h b/src/common/procfs.h
deleted file mode 100644 (file)
index c2c0f52..0000000
+++ /dev/null
@@ -1,485 +0,0 @@
-/*
- * resourced
- *
- * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#ifndef __PROCFS_H__
-#define __PROCFS_H__
-
-#include <resourced.h>
-#include <sys/types.h>
-#include <ctype.h>
-#include <regex.h>
-#include <stdio.h>
-#include <assert.h>
-#include <string.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-#include "proc-common.h"
-
-#define OOMADJ_SU                      (0)
-#define OOMADJ_INIT                    (100)
-#define OOMADJ_FOREGRD_LOCKED          (150)
-#define OOMADJ_FOREGRD_UNLOCKED                (200)
-#define OOMADJ_BACKGRD_PERCEPTIBLE     (230)
-#define OOMADJ_BACKGRD_LOCKED          (250)
-#define OOMADJ_FAVORITE                        (270)
-#define OOMADJ_BACKGRD_UNLOCKED                (300)
-#define OOMADJ_RECENTLY_USED            (430)
-#define OOMADJ_BACKGRD_OLD              (450)
-#define OOMADJ_APP_MAX                 (990)
-#define OOMADJ_APP_INCREASE            (30)
-
-#define OOMADJ_FAVORITE_APP_MAX (OOMADJ_PREVIOUS_BACKGRD - OOMADJ_FAVORITE_APP_INCREASE)
-#define OOMADJ_FAVORITE_APP_INCREASE (1)
-
-/* OOMADJ_SERVICE_DEFAULT is default value for processes PROC_TYPE_SERVICE */
-#define OOMADJ_SERVICE_GAP             (10)
-#define OOMADJ_SERVICE_DEFAULT         (OOMADJ_BACKGRD_LOCKED - OOMADJ_SERVICE_GAP)
-
-/*
- * OOMADJ_PREVIOUS_DEFAULT is default value for processes that are
- * moved out from foreground cgroup ( >= OOMADJ_BACKGRD_PERCEPTIBLE)
- * but being in a state before background cgroup ( >= OOMADJ_BACKGRD_UNLOCKED).
- * In the middle it is possible to have process in favorite cgroup (== OOMADJ_FAVORITE).
- */
-#define OOMADJ_PREVIOUS_GAP            (10)
-#define OOMADJ_PREVIOUS_DEFAULT                (OOMADJ_BACKGRD_LOCKED - OOMADJ_PREVIOUS_GAP)
-#define OOMADJ_PREVIOUS_BACKGRD        (OOMADJ_BACKGRD_UNLOCKED - OOMADJ_PREVIOUS_GAP)
-
-
-#define PROC_OOM_SCORE_ADJ_PATH "/proc/%d/oom_score_adj"
-#define PROC_STAT_PATH "/proc/%d/stat"
-#define PROC_ZONEINFO_PATH     "/proc/zoneinfo"
-#define PROC_PAGETYPEINFO_PATH  "/proc/pagetypeinfo"
-#define PROC_BUDDYINFO_PATH    "/proc/buddyinfo"
-
-enum meminfo_id {
-       MEMINFO_ID_INVALID = -1,
-       MEMINFO_ID_MEM_TOTAL = 0,
-       MEMINFO_ID_MEM_FREE,
-       MEMINFO_ID_MEM_AVAILABLE,
-       MEMINFO_ID_BUFFERS,
-       MEMINFO_ID_CACHED,
-       MEMINFO_ID_SWAP_CACHED,
-       MEMINFO_ID_ACTIVE,
-       MEMINFO_ID_INACTIVE,
-       MEMINFO_ID_ACTIVE_ANON,
-       MEMINFO_ID_INACTIVE_ANON,
-       MEMINFO_ID_ACTIVE_FILE,
-       MEMINFO_ID_INACTIVE_FILE,
-       MEMINFO_ID_UNEVICTABLE,
-       MEMINFO_ID_MLOCKED,
-       MEMINFO_ID_HIGH_TOTAL,
-       MEMINFO_ID_HIGH_FREE,
-       MEMINFO_ID_LOW_TOTAL,
-       MEMINFO_ID_LOW_FREE,
-       MEMINFO_ID_SWAP_TOTAL,
-       MEMINFO_ID_SWAP_FREE,
-       MEMINFO_ID_DIRTY,
-       MEMINFO_ID_WRITEBACK,
-       MEMINFO_ID_ANON_PAGES,
-       MEMINFO_ID_MAPPED,
-       MEMINFO_ID_SHMEM,
-       MEMINFO_ID_SLAB,
-       MEMINFO_ID_SRECLAIMABLE,
-       MEMINFO_ID_SUNRECLAIM,
-       MEMINFO_ID_KERNEL_STACK,
-       MEMINFO_ID_PAGE_TABLES,
-       MEMINFO_ID_NFS_UNSTABLE,
-       MEMINFO_ID_BOUNCE,
-       MEMINFO_ID_WRITEBACK_TMP,
-       MEMINFO_ID_COMMIT_LIMIT,
-       MEMINFO_ID_COMMITTED_AS,
-       MEMINFO_ID_VMALLOC_TOTAL,
-       MEMINFO_ID_VMALLOC_USED,
-       MEMINFO_ID_VMALLOC_CHUNK,
-       MEMINFO_ID_MAX,
-};
-
-#define MEMINFO_MASK_MEM_TOTAL     (1ULL << MEMINFO_ID_MEM_TOTAL)
-#define MEMINFO_MASK_MEM_FREE      (1ULL << MEMINFO_ID_MEM_FREE)
-#define MEMINFO_MASK_MEM_AVAILABLE (1ULL << MEMINFO_ID_MEM_AVAILABLE)
-#define MEMINFO_MASK_BUFFERS       (1ULL << MEMINFO_ID_BUFFERS)
-#define MEMINFO_MASK_CACHED        (1ULL << MEMINFO_ID_CACHED)
-#define MEMINFO_MASK_SWAP_CACHED   (1ULL << MEMINFO_ID_SWAP_CACHED)
-#define MEMINFO_MASK_ACTIVE        (1ULL << MEMINFO_ID_ACTIVE)
-#define MEMINFO_MASK_INACTIVE      (1ULL << MEMINFO_ID_INACTIVE)
-#define MEMINFO_MASK_ACTIVE_ANON   (1ULL << MEMINFO_ID_ACTIVE_ANON)
-#define MEMINFO_MASK_INACTIVE_ANON (1ULL << MEMINFO_ID_INACTIVE_ANON)
-#define MEMINFO_MASK_ACTIVE_FILE   (1ULL << MEMINFO_ID_ACTIVE_FILE)
-#define MEMINFO_MASK_INACTIVE_FILE (1ULL << MEMINFO_ID_INACTIVE_FILE)
-#define MEMINFO_MASK_UNEVICTABLE   (1ULL << MEMINFO_ID_UNEVICTABLE)
-#define MEMINFO_MASK_MLOCKED       (1ULL << MEMINFO_ID_MLOCKED)
-#define MEMINFO_MASK_HIGH_TOTAL    (1ULL << MEMINFO_ID_HIGH_TOTAL)
-#define MEMINFO_MASK_HIGH_FREE     (1ULL << MEMINFO_ID_HIGH_FREE)
-#define MEMINFO_MASK_LOW_TOTAL     (1ULL << MEMINFO_ID_LOW_TOTAL)
-#define MEMINFO_MASK_LOW_FREE      (1ULL << MEMINFO_ID_LOW_FREE)
-#define MEMINFO_MASK_SWAP_TOTAL    (1ULL << MEMINFO_ID_SWAP_TOTAL)
-#define MEMINFO_MASK_SWAP_FREE     (1ULL << MEMINFO_ID_SWAP_FREE)
-#define MEMINFO_MASK_DIRTY         (1ULL << MEMINFO_ID_DIRTY)
-#define MEMINFO_MASK_WRITEBACK     (1ULL << MEMINFO_ID_WRITEBACK)
-#define MEMINFO_MASK_ANON_PAGES    (1ULL << MEMINFO_ID_ANON_PAGES)
-#define MEMINFO_MASK_MAPPED        (1ULL << MEMINFO_ID_MAPPED)
-#define MEMINFO_MASK_SHMEM         (1ULL << MEMINFO_ID_SHMEM)
-#define MEMINFO_MASK_SLAB          (1ULL << MEMINFO_ID_SLAB)
-#define MEMINFO_MASK_SRECLAIMABLE  (1ULL << MEMINFO_ID_SRECLAIMABLE)
-#define MEMINFO_MASK_SUNRECLAIM    (1ULL << MEMINFO_ID_SUNRECLAIM)
-#define MEMINFO_MASK_KERNEL_STACK  (1ULL << MEMINFO_ID_KERNEL_STACK)
-#define MEMINFO_MASK_PAGE_TABLES   (1ULL << MEMINFO_ID_PAGE_TABLES)
-#define MEMINFO_MASK_NFS_UNSTABLE  (1ULL << MEMINFO_ID_NFS_UNSTABLE)
-#define MEMINFO_MASK_BOUNCE        (1ULL << MEMINFO_ID_BOUNCE)
-#define MEMINFO_MASK_WRITEBACK_TMP (1ULL << MEMINFO_ID_WRITEBACK_TMP)
-#define MEMINFO_MASK_COMMIT_LIMIT  (1ULL << MEMINFO_ID_COMMIT_LIMIT)
-#define MEMINFO_MASK_COMMITTED_AS  (1ULL << MEMINFO_ID_COMMITTED_AS)
-#define MEMINFO_MASK_VMALLOC_TOTAL (1ULL << MEMINFO_ID_VMALLOC_TOTAL)
-#define MEMINFO_MASK_VMALLOC_USED  (1ULL << MEMINFO_ID_VMALLOC_USED)
-#define MEMINFO_MASK_VMALLOC_CHUNK (1ULL << MEMINFO_ID_VMALLOC_CHUNK)
-#define MEMINFO_MASK_ALL           ((1ULL << MEMINFO_ID_MAX) - 1)
-
-struct meminfo_mapping {
-       const char *name;
-       enum meminfo_id id;
-};
-typedef struct meminfo_mapping meminfo_mapping;
-
-const meminfo_mapping *meminfo_mapping_lookup(const char *str, unsigned int len);
-
-static inline enum meminfo_id meminfo_string_to_id(const char *str)
-{
-       const struct meminfo_mapping *i;
-
-       assert(str);
-       i = meminfo_mapping_lookup(str, strlen(str));
-       return i ? i->id : MEMINFO_ID_INVALID;
-}
-
-const char *meminfo_id_to_string(enum meminfo_id);
-
-struct meminfo {
-       unsigned int value[MEMINFO_ID_MAX];
-};
-
-/**
- * @desc get info corresponding size(kB) from /proc/meminfo
- * @note given meminfo struct is set all zero before filled
- * @return 0 on success, return negative error code on fail.
- */
-int proc_get_meminfo(struct meminfo *mi, unsigned long long mask);
-
-/*
- * This interface is required by proc_sys_node_trigger(...)
- */
-enum sys_node_id {
-       SYS_VM_SHRINK_MEMORY,
-       SYS_VM_COMPACT_MEMORY,
-};
-
-/*
- * Here,
- * @path is /proc/sys/vm/{shrink,compact}_memory
- * @value is always 1
- * @valid - indicates whether the node is present in kernel or not
- */
-struct sys_node_table {
-       enum sys_node_id sys_node_id;
-       const char *path;
-       int value;
-       int valid;
-};
-
-/**
- * @brief procfs entry parser arguments
- * @re_exp regular expression to look for
- * @callback callback function to be called once the arg match is identified
- * @tag unique identifier of the argument
- */
-struct parse_arg {
-       const char *re_exp;
-       int (*callback)(const char*, regmatch_t *, unsigned int, void *);
-       unsigned int tag;
-};
-
-#define PARSE_TAG(exp, fn, id) \
-{ \
-       .re_exp  = exp, \
-       .callback = fn, \
-       .tag = PARSE_TAG_##id, \
-}
-
-#define PARSE_TAG_EMPTY()  {0,}
-
-enum {
-       PARSE_TAG_ZONE = 1,
-       PARSE_TAG_PAGE_COUNT,
-       PARSE_TAG_WM_MIN,
-       PARSE_TAG_WM_LOW,
-       PARSE_TAG_WM_HIGH,
-       PARSE_TAG_MANAGED,
-       PARSE_TAG_SPANNED,
-       PARSE_TAG_MAX,
-};
-
-
-/**
- * @desc get command line from /proc/{pid}/cmdline if pid is greater than 0
- * it get /proc/cmdline if pid is 0
- * @return negative value if error
- */
-int proc_get_cmdline(pid_t pid, char *cmdline, size_t maxcmdline);
-
-/**
- * @desc find pid with /proc/{pid}/cmdline
- * it returns first entry when many pids have same cmdline
- * @return negative value if error
- */
-pid_t find_pid_from_cmdline(char *cmdline);
-
-/**
- * @desc get oom score adj value from /proc/{pid}/oom_score_adj
- * @return negative value if error or pid doesn't exist
- */
-int proc_get_oom_score_adj(int pid, int *oom_score_adj);
-
-/**
- * @desc set oom score adj value to /proc/{pid}/oom_score_adj
- * @return negative value if error or pid doesn't exist
- */
-int proc_set_oom_score_adj(int pid, int oom_score_adj, struct proc_app_info *pai);
-
-/**
- * @desc get smack subject label from /proc/{pid}/attr/current
- * this label can indicate package name about child processes
- * @return negative value if error or pid doesn't exist
- */
-int proc_get_label(pid_t pid, char *label);
-
-/**
- * @desc get USS memory usage from /proc/{pid}/smaps file.
- * @return negative value if error or pid doesn't exist
- */
-int proc_get_uss(pid_t pid, unsigned int *uss);
-
-/**
- * @desc get VmRSS and VmSwap from /proc/{pid}/status file.
- * @return negative value if error or pid doesn't exist
- */
-int proc_get_mem_status(pid_t pid, unsigned int *swap, unsigned int *rss);
-
-/**
- * @desc get aproximated usage of Zram for pid
- * @return negative value if error or pid doesn't exist
- */
-int proc_get_zram_usage(pid_t pid, unsigned int *usage);
-
-/**
- * @desc get approximate memory usage from status and statm
- * @return negative value if error or pid doesn't exist
- */
-int proc_get_approx_mem_usage(pid_t pid, unsigned int *usage);
-
-/**
- * @desc get total memory usage from VmSwap and VmRSS.
- * @return negative value if error or pid doesn't exist
- */
-int proc_get_mem_usage(pid_t pid, unsigned int *usage);
-
-/**
- * @desc get how much ram is used in each application
- * @return negative value if error or pid doesn't exist
- */
-int proc_get_ram_usage(pid_t pid, unsigned int *usage);
-
-/**
- * @desc get MemAvaliable from /proc/meminfo or calcuate it by MemFree+Cached
- * @return 0 if the values can't be read or the avaliable memory value
- */
-unsigned int proc_get_mem_available(void);
-
-/**
- * @desc get SwapFree from /proc/meminfo
- * @return 0 if the values can't be read or the free swap memory
- */
-unsigned int proc_get_swap_free(void);
-
-/**
- * @desc get SwapTotal from /proc/meminfo
- * @return 0 if the values can't be read or the total swap size
- */
-unsigned int proc_get_swap_total(void);
-
-/**
- * @desc get number of CPUs from /proc/cpuinfo
- * @return 0 if the number can't be found or number of CPUs
- */
-unsigned int proc_get_cpu_number(void);
-
-/**
- * @desc get utime and stime from /proc/{pid}/stat file.
- * @return negative value if error or pid doesn't exist
- */
-int proc_get_cpu_time(pid_t pid, unsigned long *utime, unsigned long *stime,
-                                       unsigned long *starttime);
-
-/**
- * @desc get command line from /proc/{pid}/cmdline without any truncation
- * @return negative value if error
- */
-int proc_get_raw_cmdline(pid_t pid, char *buf, int len);
-
-/**
- * @desc get symblolic link about /proc/{pid}/exe
- * @return negative value if error
- */
-int proc_get_exepath(pid_t pid, char *buf, int len);
-
-/**
- * @desc get stat from /proc/{pid}/stat
- * @return negative value if error
- */
-int proc_get_stat(pid_t pid, char *buf, int len);
-
-/**
- * @desc get status from /proc/{pid}/status
- * @return negative value if error
- */
-int proc_get_status(pid_t pid, char *buf, int len);
-
-/**
- * @desc invoke shrink_memory or compact_memory vm parameter.
- * @return none
- */
-int proc_sys_node_trigger(enum sys_node_id sys_node_id);
-
-/**
- * @desc get uptime from system time of /proc/uptime
- * @return negative value if error
- */
-int proc_get_uptime(unsigned long *uptime);
-
-/**
- * @desc get total ram size including reserved memory
- * @param[out] total Ram size in kilobytes
- * @return negative value if error
- */
-int proc_get_ram_total(unsigned int *total);
-
-/**
- * @brief print uss and memtotal for showing brief memory information
- */
-void proc_print_meninfo(FILE *fp);
-
-enum {
-       PAGE_4K = 0,
-       PAGE_8K,
-       PAGE_16K,
-       PAGE_32K,
-       PAGE_64K,
-       PAGE_128K,
-       PAGE_256K,
-       PAGE_512K,
-       PAGE_1M,
-       PAGE_2M,
-       PAGE_4M,
-       PAGE_MAX,
-};
-
-struct buddyinfo {
-       int node;
-       int page[PAGE_MAX];
-};
-
-/**
- * @desc get buddyinfo of specific zone from /proc/buddyinfo
- * @return negative value if error
- */
-int proc_get_buddyinfo(const char *zone, struct buddyinfo *bi);
-
-/**
- * @brief Generic, simplified procfs parser
- *
- * @path       path to the procfs entry
- * @parse_args set of arguments specifying regular expressions
- *              to be searched for within the procfs entry
- * @data       custom data supplied to each parse callback function
- *          specified within the parse arguments
- */
-int proc_parse_entry(const char *path, const struct parse_arg *parse_args,
-                       void *data);
-
-/**
- * @bried /proc/zoneinfo parser
- */
-static inline int proc_parse_zoneinfo(const struct parse_arg *parse_args,
-                                       void *data)
-{
-       return proc_parse_entry(PROC_ZONEINFO_PATH, parse_args, data);
-}
-/**
- * @brief /proc/pagetypeinfo parser
- */
-static inline int proc_parse_pagetypeinfo(const struct parse_arg *parse_args,
-                                               void *data)
-{
-       return proc_parse_entry(PROC_PAGETYPEINFO_PATH, parse_args, data);
-}
-
-static inline int proc_parse_buddyinfo(const struct parse_arg *parse_args,
-                                        void *data)
-{
-       return proc_parse_entry(PROC_BUDDYINFO_PATH, parse_args, data);
-}
-
-struct proc_swaps {
-       char *filename;
-       char *type;
-       unsigned int size;
-       unsigned int used;
-       int priority;
-};
-
-void proc_swap_free(struct proc_swaps *swap);
-void proc_swaps_free(struct proc_swaps **swaps);
-
-static inline void __cleanup_proc_swap_free_func(struct proc_swaps **swap)
-{
-       proc_swap_free(*swap);
-}
-
-#define _cleanup_proc_swap_free_ _cleanup_(__cleanup_proc_swap_free_func)
-
-static inline void __cleanup_proc_swaps_free_func(struct proc_swaps ***swaps)
-{
-       proc_swaps_free(*swaps);
-}
-
-#define _cleanup_proc_swaps_free_ _cleanup_(__cleanup_proc_swaps_free_func)
-
-/**
- * @desc get swap info from /proc/swaps
- * @return negative value if errors, positive value means total enties of swap devices
- */
-int proc_get_swaps(struct proc_swaps ***swaps);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /*__PROCFS_H__*/
diff --git a/src/common/procfs/meminfo-lookup.c b/src/common/procfs/meminfo-lookup.c
new file mode 100644 (file)
index 0000000..99a4f07
--- /dev/null
@@ -0,0 +1,182 @@
+/* NOTE: this file was dynamically generated by gperf but is included verbatim
+ * (instead of being regenerated) due to various build environment issues */
+
+/* ANSI-C code produced by gperf version 3.0.4 */
+/* Command-line: gperf /home/abuild/rpmbuild/BUILD/resourced-6.0.2/src/common/meminfo-lookup.gperf  */
+/* Computed positions: -k'1-2,10' */
+
+#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
+      && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
+      && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
+      && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
+      && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
+      && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
+      && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
+      && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
+      && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
+      && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
+      && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
+      && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
+      && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
+      && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
+      && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
+      && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
+      && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
+      && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
+      && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
+      && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
+      && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
+      && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
+      && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
+/* The character set is not based on ISO-646.  */
+#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
+#endif
+
+#include "procfs.h"
+#include <string.h>
+
+#define TOTAL_KEYWORDS 38
+#define MIN_WORD_LENGTH 4
+#define MAX_WORD_LENGTH 14
+#define MIN_HASH_VALUE 4
+#define MAX_HASH_VALUE 67
+/* maximum key range = 64, duplicates = 0 */
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static unsigned int
+meminfo_mapping_hash (register const char *str, register unsigned int len)
+{
+  static const unsigned char asso_values[] =
+    {
+      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+      68, 68, 68, 68, 68,  5, 25, 10, 20, 68,
+      15, 68, 25, 10, 68, 25, 15,  0, 10, 68,
+       5, 68, 20,  0, 35, 10, 15,  5, 68, 68,
+      68, 68, 68, 68, 68, 25, 68,  0, 30,  0,
+       0,  5,  5, 68,  0,  0, 68, 68,  0,  0,
+       0,  5, 68, 68,  5,  0, 15,  5, 68,  0,
+      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+      68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+      68, 68, 68, 68, 68, 68
+    };
+  register int hval = len;
+
+  switch (hval)
+    {
+      default:
+        hval += asso_values[(unsigned char)str[9]];
+      /*FALLTHROUGH*/
+      case 9:
+      case 8:
+      case 7:
+      case 6:
+      case 5:
+      case 4:
+      case 3:
+      case 2:
+        hval += asso_values[(unsigned char)str[1]];
+      /*FALLTHROUGH*/
+      case 1:
+        hval += asso_values[(unsigned char)str[0]];
+        break;
+    }
+  return hval;
+}
+
+#ifdef __GNUC__
+__inline
+#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
+__attribute__ ((__gnu_inline__))
+#endif
+#endif
+const meminfo_mapping *
+meminfo_mapping_lookup (register const char *str, register unsigned int len)
+{
+  static const meminfo_mapping wordlist[] =
+    {
+      {""}, {""}, {""}, {""},
+      {"Slab",           MEMINFO_ID_SLAB},
+      {"Shmem",          MEMINFO_ID_SHMEM},
+      {"Mapped",         MEMINFO_ID_MAPPED},
+      {"Mlocked",        MEMINFO_ID_MLOCKED},
+      {"SwapFree",       MEMINFO_ID_SWAP_FREE},
+      {"SwapTotal",      MEMINFO_ID_SWAP_TOTAL},
+      {"SwapCached",     MEMINFO_ID_SWAP_CACHED},
+      {"Active",         MEMINFO_ID_ACTIVE},
+      {"MemFree",        MEMINFO_ID_MEM_FREE},
+      {"MemTotal",       MEMINFO_ID_MEM_TOTAL},
+      {"AnonPages",      MEMINFO_ID_ANON_PAGES},
+      {"PageTables",     MEMINFO_ID_PAGE_TABLES},
+      {"Cached",         MEMINFO_ID_CACHED},
+      {"Active(file)",   MEMINFO_ID_ACTIVE_FILE},
+      {"Inactive",       MEMINFO_ID_INACTIVE},
+      {"Writeback",      MEMINFO_ID_WRITEBACK},
+      {"SUnreclaim",     MEMINFO_ID_SUNRECLAIM},
+      {"Unevictable",    MEMINFO_ID_UNEVICTABLE},
+      {"Active(anon)",   MEMINFO_ID_ACTIVE_ANON},
+      {""},
+      {"Inactive(anon)", MEMINFO_ID_INACTIVE_ANON},
+      {"Dirty",          MEMINFO_ID_DIRTY},
+      {"CommitLimit",    MEMINFO_ID_COMMIT_LIMIT},
+      {"LowFree",        MEMINFO_ID_LOW_FREE},
+      {"LowTotal",       MEMINFO_ID_LOW_TOTAL},
+      {"Inactive(file)", MEMINFO_ID_INACTIVE_FILE},
+      {""},
+      {"VmallocUsed",    MEMINFO_ID_VMALLOC_USED},
+      {"VmallocChunk",   MEMINFO_ID_VMALLOC_CHUNK},
+      {"HighFree",       MEMINFO_ID_HIGH_FREE},
+      {"HighTotal",      MEMINFO_ID_HIGH_TOTAL},
+      {""},
+      {"Bounce",         MEMINFO_ID_BOUNCE},
+      {"Buffers",        MEMINFO_ID_BUFFERS},
+      {""}, {""}, {""},
+      {"KernelStack",    MEMINFO_ID_KERNEL_STACK},
+      {"VmallocTotal",   MEMINFO_ID_VMALLOC_TOTAL},
+      {""}, {""}, {""}, {""},
+      {"MemAvailable",   MEMINFO_ID_MEM_AVAILABLE},
+      {""}, {""}, {""}, {""},
+      {"Committed_AS",   MEMINFO_ID_COMMITTED_AS},
+      {""}, {""}, {""}, {""},
+      {"WritebackTmp",   MEMINFO_ID_WRITEBACK_TMP},
+      {""}, {""}, {""}, {""},
+      {"SReclaimable",   MEMINFO_ID_SRECLAIMABLE},
+      {""}, {""}, {""}, {""},
+      {"NFS_Unstable",   MEMINFO_ID_NFS_UNSTABLE}
+    };
+
+  if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
+    {
+      register int key = meminfo_mapping_hash (str, len);
+
+      if (key <= MAX_HASH_VALUE && key >= 0)
+        {
+          register const char *s = wordlist[key].name;
+
+          if (*str == *s && !strcmp (str + 1, s + 1))
+            return &wordlist[key];
+        }
+    }
+  return 0;
+}
diff --git a/src/common/procfs/meminfo-lookup.gperf b/src/common/procfs/meminfo-lookup.gperf
new file mode 100644 (file)
index 0000000..749f259
--- /dev/null
@@ -0,0 +1,51 @@
+%{
+#include "procfs.h"
+%}
+meminfo_mapping;
+%language=ANSI-C
+%define slot-name name
+%define hash-function-name meminfo_mapping_hash
+%define lookup-function-name meminfo_mapping_lookup
+%readonly-tables
+%omit-struct-type
+%struct-type
+%includes
+%%
+MemTotal,       MEMINFO_ID_MEM_TOTAL
+MemFree,        MEMINFO_ID_MEM_FREE
+MemAvailable,   MEMINFO_ID_MEM_AVAILABLE
+Buffers,        MEMINFO_ID_BUFFERS
+Cached,         MEMINFO_ID_CACHED
+SwapCached,     MEMINFO_ID_SWAP_CACHED
+Active,         MEMINFO_ID_ACTIVE
+Inactive,       MEMINFO_ID_INACTIVE
+Active(anon),   MEMINFO_ID_ACTIVE_ANON
+Inactive(anon), MEMINFO_ID_INACTIVE_ANON
+Active(file),   MEMINFO_ID_ACTIVE_FILE
+Inactive(file), MEMINFO_ID_INACTIVE_FILE
+Unevictable,    MEMINFO_ID_UNEVICTABLE
+Mlocked,        MEMINFO_ID_MLOCKED
+HighTotal,      MEMINFO_ID_HIGH_TOTAL
+HighFree,       MEMINFO_ID_HIGH_FREE
+LowTotal,       MEMINFO_ID_LOW_TOTAL
+LowFree,        MEMINFO_ID_LOW_FREE
+SwapTotal,      MEMINFO_ID_SWAP_TOTAL
+SwapFree,       MEMINFO_ID_SWAP_FREE
+Dirty,          MEMINFO_ID_DIRTY
+Writeback,      MEMINFO_ID_WRITEBACK
+AnonPages,      MEMINFO_ID_ANON_PAGES
+Mapped,         MEMINFO_ID_MAPPED
+Shmem,          MEMINFO_ID_SHMEM
+Slab,           MEMINFO_ID_SLAB
+SReclaimable,   MEMINFO_ID_SRECLAIMABLE
+SUnreclaim,     MEMINFO_ID_SUNRECLAIM
+KernelStack,    MEMINFO_ID_KERNEL_STACK
+PageTables,     MEMINFO_ID_PAGE_TABLES
+NFS_Unstable,   MEMINFO_ID_NFS_UNSTABLE
+Bounce,         MEMINFO_ID_BOUNCE
+WritebackTmp,   MEMINFO_ID_WRITEBACK_TMP
+CommitLimit,    MEMINFO_ID_COMMIT_LIMIT
+Committed_AS,   MEMINFO_ID_COMMITTED_AS
+VmallocTotal,   MEMINFO_ID_VMALLOC_TOTAL
+VmallocUsed,    MEMINFO_ID_VMALLOC_USED
+VmallocChunk,   MEMINFO_ID_VMALLOC_CHUNK
diff --git a/src/common/procfs/procfs.c b/src/common/procfs/procfs.c
new file mode 100644 (file)
index 0000000..4caead1
--- /dev/null
@@ -0,0 +1,1102 @@
+/*
+ * resourced
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * @file procfs.c
+ *
+ * @desc communicate with procfs in resourced
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "resourced.h"
+#include "trace.h"
+#include "macro.h"
+#include "util.h"
+#include "procfs.h"
+#include "proc-common.h"
+#include "memory-cgroup.h"
+#include "module.h"
+#include "file-helper.h"
+#include "swap-common.h"
+#include "smaps.h"
+#include "notifier.h"
+#include "lowmem-handler.h"
+
+#define MEM_SWAP_RATIO                 0.5
+
+static struct sys_node_table sys_node_tables[] = {
+       { SYS_VM_SHRINK_MEMORY, "/proc/sys/vm/shrink_memory", 1, 1 },
+       { SYS_VM_COMPACT_MEMORY, "/proc/sys/vm/compact_memory", 1, 1 },
+       { },
+};
+
+int proc_get_cmdline(pid_t pid, char *cmdline, size_t maxcmdline)
+{
+       assert(cmdline);
+       assert(maxcmdline > 0);
+
+       char buf[PROC_BUF_MAX];
+       char cmdline_buf[PROC_NAME_MAX];
+       char *filename;
+       FILE *fp;
+
+       if (pid == 0)
+               snprintf(buf, sizeof(buf), "/proc/cmdline");
+       else
+               snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid);
+
+       fp = fopen(buf, "r");
+       if (fp == NULL)
+               return RESOURCED_ERROR_FAIL;
+
+       if (fgets(cmdline_buf, sizeof cmdline_buf, fp) == NULL) {
+               fclose(fp);
+               return RESOURCED_ERROR_FAIL;
+       }
+       fclose(fp);
+
+       filename = strrchr(cmdline_buf, '/');
+       if (filename == NULL)
+               filename = cmdline_buf;
+       else
+               filename = filename + 1;
+
+       strncpy(cmdline, filename, maxcmdline - 1);
+       cmdline[maxcmdline - 1] = '\0';
+
+       return RESOURCED_ERROR_NONE;
+}
+
+pid_t find_pid_from_cmdline(char *cmdline)
+{
+       pid_t pid = -1, foundpid = -1;
+       int ret = 0;
+       DIR *dp;
+       struct dirent *dentry;
+       char appname[PROC_NAME_MAX];
+
+       dp = opendir("/proc");
+       if (!dp) {
+               _E("BACKGRD MANAGE : fail to open /proc");
+               return RESOURCED_ERROR_FAIL;
+       }
+       while ((dentry = readdir(dp))) {
+               if (!isdigit(dentry->d_name[0]))
+                       continue;
+
+               pid = atoi(dentry->d_name);
+               if (!pid)
+                       continue;
+               ret = proc_get_cmdline(pid, appname, sizeof appname);
+               if (ret == RESOURCED_ERROR_NONE) {
+                       if (!strncmp(cmdline, appname, strlen(appname)+1)) {
+                               foundpid = pid;
+                               break;
+                       }
+               }
+       }
+       closedir(dp);
+       return foundpid;
+}
+
+int proc_get_oom_score_adj(int pid, int *oom_score_adj)
+{
+       char buf[sizeof(PROC_OOM_SCORE_ADJ_PATH) + MAX_DEC_SIZE(int)] = {0};
+       FILE *fp = NULL;
+
+       if (pid <= 0)
+               return RESOURCED_ERROR_FAIL;
+
+       snprintf(buf, sizeof(buf), PROC_OOM_SCORE_ADJ_PATH, pid);
+       fp = fopen(buf, "r");
+
+       if (fp == NULL) {
+               _E("fopen %s failed", buf);
+               return RESOURCED_ERROR_FAIL;
+       }
+       if (fgets(buf, sizeof(buf), fp) == NULL) {
+               fclose(fp);
+               return RESOURCED_ERROR_FAIL;
+       }
+       (*oom_score_adj) = atoi(buf);
+       fclose(fp);
+       return RESOURCED_ERROR_NONE;
+}
+
+int proc_set_oom_score_adj(int pid, int oom_score_adj, struct proc_app_info *pai)
+{
+       FILE *fp;
+       struct lowmem_control_data lowmem_data;
+       char buf[sizeof(PROC_OOM_SCORE_ADJ_PATH) + MAX_DEC_SIZE(int)] = {0};
+
+       snprintf(buf, sizeof(buf), PROC_OOM_SCORE_ADJ_PATH, pid);
+       fp = fopen(buf, "r+");
+       if (fp == NULL)
+               return RESOURCED_ERROR_FAIL;
+       if (fgets(buf, sizeof(buf), fp) == NULL) {
+               fclose(fp);
+               return RESOURCED_ERROR_FAIL;
+       }
+       fprintf(fp, "%d", oom_score_adj);
+       fclose(fp);
+
+       if (oom_score_adj >= OOMADJ_SU) {
+               lowmem_data.control_type = LOWMEM_MOVE_CGROUP;
+               lowmem_data.pid = pid;
+               lowmem_data.oom_score_adj = oom_score_adj;
+               lowmem_data.pai = pai;
+               resourced_notify(RESOURCED_NOTIFIER_MEM_CONTROL, &lowmem_data);
+       }
+
+       return RESOURCED_ERROR_NONE;
+}
+
+int proc_get_label(pid_t pid, char *label)
+{
+       char buf[PROC_BUF_MAX];
+       FILE *fp;
+
+       snprintf(buf, sizeof(buf), "/proc/%d/attr/current", pid);
+       fp = fopen(buf, "r");
+       if (fp == NULL)
+               return RESOURCED_ERROR_FAIL;
+
+       if (fgets(label, PROC_NAME_MAX-1, fp) == NULL) {
+               fclose(fp);
+               return RESOURCED_ERROR_FAIL;
+       }
+       fclose(fp);
+       return RESOURCED_ERROR_NONE;
+}
+
+int proc_get_mem_status(pid_t pid, unsigned int *vmswap_kb, unsigned int *vmrss_kb)
+{
+       char filename[PROC_BUF_MAX];
+       _cleanup_fclose_ FILE *fp = NULL;
+       unsigned int swap_kb = 0, rss_kb = 0;
+
+       snprintf(filename, PROC_BUF_MAX, "/proc/%d/status", pid);
+       fp = fopen(filename, "r");
+       if (!fp)
+               return RESOURCED_ERROR_FAIL;
+
+       if (vmrss_kb != NULL) {
+               while (fgets(filename, sizeof(filename), fp)) {
+                       /* Skip the lines, until first match */
+                       if (!strstart_with(filename, "VmRSS:"))
+                               continue;
+
+                       /* Read RSS value and end this loop. */
+                       if (sscanf(filename, "VmRSS: %u kB", &rss_kb) == 1)
+                               break;
+
+                       return RESOURCED_ERROR_NO_DATA;
+               }
+               *vmrss_kb = rss_kb;
+       }
+
+       if (vmswap_kb != NULL) {
+               /* Interate over rest of Vm* values */
+               while (fgets(filename, sizeof(filename), fp)) {
+                       /* Read VmSwap and return with positive result */
+                       if (sscanf(filename, "VmSwap: %d kB", &swap_kb) == 1)
+                               break;
+
+                       /* End of file before VmSwap read, return with error */
+                       if (feof(fp))
+                               return RESOURCED_ERROR_NO_DATA;
+               }
+               *vmswap_kb = swap_kb;
+       }
+
+       return RESOURCED_ERROR_NONE;
+}
+
+int proc_get_uss(pid_t pid, unsigned int *uss)
+{
+       _cleanup_smaps_free_ struct smaps *smaps = NULL;
+       int ret;
+
+       *uss = 0;
+
+       /*
+        * USS memory usage is number of KB accounted to a process
+        * where only private (non-shared) data are accounted.
+        *
+        * USS provides the value how much memory will be freed after
+        * termination of process.
+        */
+       ret = smaps_get(pid, &smaps,
+                       (SMAPS_MASK_PRIVATE_CLEAN | SMAPS_MASK_PRIVATE_DIRTY));
+
+       if (ret < 0) {
+               _E("Error while reading smaps or totmaps for pid %d", pid);
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       *uss += smaps->sum[SMAPS_ID_PRIVATE_CLEAN];
+       *uss += smaps->sum[SMAPS_ID_PRIVATE_DIRTY];
+
+       return RESOURCED_ERROR_NONE;
+}
+
+int proc_get_zram_usage(pid_t pid, unsigned int *usage_kb)
+{
+       int ret;
+       struct meminfo mi;
+       static unsigned int swap_total_kb = 0;
+       unsigned int proc_swap_usage_kb;
+       unsigned long long zram_usage_bytes;
+
+       /* Read total swap size just once and cache it */
+       if (!swap_total_kb) {
+               ret = proc_get_meminfo(&mi, MEMINFO_MASK_SWAP_TOTAL);
+               if (ret < 0) {
+                       _E("Failed to get %s: %m",
+                          meminfo_id_to_string(MEMINFO_ID_SWAP_TOTAL));
+                       return RESOURCED_ERROR_FAIL;
+               }
+               swap_total_kb = mi.value[MEMINFO_ID_SWAP_TOTAL];
+       }
+
+       /* Read usage of Swap (VmSwap) of interested process */
+       ret = proc_get_mem_status(pid, &proc_swap_usage_kb, NULL);
+       if (ret != RESOURCED_ERROR_NONE)
+               return ret;
+
+       /* Read current total memory usage of zram device */
+       ret = fread_nth_ulonglong(SWAP_ZRAM_SYSFILE"mm_stat", 2, &zram_usage_bytes);
+       if (ret == -ENOENT) {
+               ret = fread_ulonglong(SWAP_ZRAM_SYSFILE"mem_used_total", &zram_usage_bytes);
+       }
+
+       if (ret < 0)
+               return RESOURCED_ERROR_FAIL;
+
+       /*
+        * Calculate aproximated value of zram usage for selected process
+        * by formula: proc_zram_usage = ( VmSwap x ZramMemoryUsage )/SwapTotal
+        */
+       *usage_kb = (int)((float)proc_swap_usage_kb * BYTE_TO_KBYTE(zram_usage_bytes) / swap_total_kb);
+
+       return RESOURCED_ERROR_NONE;
+}
+
+int proc_get_approx_mem_usage(pid_t pid, unsigned int *usage_kb)
+{
+       int ret;
+       unsigned long resident_pages = 0, shared_pages = 0;
+       char filename[PROC_BUF_MAX];
+       _cleanup_fclose_ FILE *fp = NULL;
+
+       snprintf(filename, PROC_BUF_MAX, "/proc/%d/statm", pid);
+       fp = fopen(filename, "r");
+       if (!fp)
+               return RESOURCED_ERROR_FAIL;
+
+       /*
+        * For quick read, open code by putting numbers directly
+        * expected format is
+        * seq_printf(m, "%lu %lu %lu %lu 0 %lu 0\n",
+        *               size, resident, shared, text, data);
+        */
+       ret = fscanf(fp, "%*s %lu %lu %*s %*s %*s %*s\n", &resident_pages, &shared_pages);
+       if (ret < 0)
+               return RESOURCED_ERROR_FAIL;
+
+       if (resident_pages < shared_pages) {
+               _E("# resident page should be larger than or equal to # shared page");
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       /*
+        * The value resident - shared is mostly similar to Uss.
+        */
+       *usage_kb = BYTE_TO_KBYTE((unsigned long long)(resident_pages - shared_pages) << PAGE_SHIFT);
+       return RESOURCED_ERROR_NONE;
+}
+
+/**
+ * @desc get total memory usage from VmSwap and VmRSS.
+ * @return negative value if error or pid doesn't exist
+ */
+int proc_get_mem_usage(pid_t pid, unsigned int *usage)
+{
+       int ret;
+       unsigned int vmswap = 0, total = 0;
+
+       ret = proc_get_approx_mem_usage(pid, &total);
+       if (ret < 0) {
+               _E("Failed to get usage : %d", pid);
+               return ret;
+       }
+
+       if (swap_get_state() == SWAP_ON) {
+               ret = proc_get_mem_status(pid, &vmswap, NULL);
+               if (ret != RESOURCED_ERROR_NONE)
+                       goto out;
+
+               total += vmswap;
+       }
+out:
+       *usage = total;
+       return RESOURCED_ERROR_NONE;
+}
+
+/**
+ * @desc get how much ram is used in each application
+ * @return negative value if error or pid doesn't exist
+ */
+int proc_get_ram_usage(pid_t pid, unsigned int *usage_kb)
+{
+       int ret;
+       unsigned int vmswap_kb = 0, total_kb = 0;
+
+       ret = proc_get_approx_mem_usage(pid, &total_kb);
+       if (ret < 0) {
+               _E("Failed to get usage : %d", pid);
+               return ret;
+       }
+
+       if (swap_get_state() == SWAP_ON) {
+               ret = proc_get_mem_status(pid, &vmswap_kb, NULL);
+               if (ret != RESOURCED_ERROR_NONE)
+                       goto out;
+
+               /*
+                * If it is necessary to know real ram size about each application,
+                * it should consider compression ratio.
+                */
+               vmswap_kb *= MEM_SWAP_RATIO;
+               total_kb += vmswap_kb;
+       }
+out:
+       *usage_kb = total_kb;
+       return RESOURCED_ERROR_NONE;
+}
+
+unsigned int proc_get_mem_available(void)
+{
+       struct meminfo mi;
+       int ret;
+
+       ret = proc_get_meminfo(&mi, MEMINFO_MASK_MEM_AVAILABLE);
+       if (ret < 0) {
+               _E("Failed to get %s: %m",
+                               meminfo_id_to_string(MEMINFO_ID_MEM_AVAILABLE));
+               return 0;
+       }
+
+       return KBYTE_TO_MBYTE(mi.value[MEMINFO_ID_MEM_AVAILABLE]);
+}
+
+unsigned int proc_get_swap_free(void)
+{
+       struct meminfo mi;
+       int ret;
+
+       ret = proc_get_meminfo(&mi, MEMINFO_MASK_SWAP_FREE);
+       if (ret < 0) {
+               _E("Failed to get %s: %m",
+                  meminfo_id_to_string(MEMINFO_ID_SWAP_FREE));
+               return 0;
+       }
+
+       return mi.value[MEMINFO_ID_SWAP_FREE];
+}
+
+unsigned int proc_get_swap_total(void)
+{
+       struct meminfo mi;
+       int ret;
+
+       ret = proc_get_meminfo(&mi, MEMINFO_MASK_SWAP_TOTAL);
+       if (ret < 0) {
+               _E("Failed to get %s: %m",
+                  meminfo_id_to_string(MEMINFO_ID_SWAP_TOTAL));
+               return 0;
+       }
+
+       return mi.value[MEMINFO_ID_SWAP_TOTAL];
+}
+
+int proc_get_cpu_time(pid_t pid, unsigned long *utime,
+               unsigned long *stime, unsigned long *starttime)
+{
+       char proc_path[sizeof(PROC_STAT_PATH) + MAX_DEC_SIZE(int)];
+       _cleanup_fclose_ FILE *fp = NULL;
+
+       assert(utime != NULL);
+       assert(stime != NULL);
+
+       snprintf(proc_path, sizeof(proc_path), PROC_STAT_PATH, pid);
+       fp = fopen(proc_path, "r");
+       if (fp == NULL)
+               return RESOURCED_ERROR_FAIL;
+
+       if (fscanf(fp, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s") < 0)
+               return RESOURCED_ERROR_FAIL;
+
+       if (fscanf(fp, "%lu %lu", utime, stime) < 1)
+               return RESOURCED_ERROR_FAIL;
+
+       if (fscanf(fp, "%*s %*s %*s %*s %*s %*s") < 0)
+               return RESOURCED_ERROR_FAIL;
+
+       if (fscanf(fp, "%lu", starttime) < 1)
+               return RESOURCED_ERROR_FAIL;
+
+       return RESOURCED_ERROR_NONE;
+}
+
+unsigned int proc_get_cpu_number(void)
+{
+       char buf[PATH_MAX];
+       FILE *fp;
+       int cpu = 0;
+
+       fp = fopen("/proc/cpuinfo", "r");
+
+       if (!fp) {
+               _E("/proc/cpuinfo open failed");
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       while (fgets(buf, PATH_MAX, fp) != NULL) {
+               if (!strncmp(buf, "processor", 9))
+                       cpu++;
+       }
+
+       fclose(fp);
+       return cpu;
+}
+
+int proc_get_exepath(pid_t pid, char *buf, int len)
+{
+       char path[PROC_BUF_MAX];
+       int ret = 0;
+
+       snprintf(path, sizeof(path), "/proc/%d/exe", pid);
+       ret = readlink(path, buf, len-1);
+       if (ret > 0)
+               buf[ret] = '\0';
+       else
+               buf[0] = '\0';
+       return RESOURCED_ERROR_NONE;
+}
+
+static int proc_get_data(char *path, char *buf, int len)
+{
+       _cleanup_close_ int fd = -1;
+       int ret;
+
+       fd = open(path, O_RDONLY);
+       if (fd < 0)
+               return RESOURCED_ERROR_FAIL;
+
+       ret = read(fd, buf, len-1);
+       if (ret < 0) {
+               buf[0] = '\0';
+               return RESOURCED_ERROR_FAIL;
+       }
+       buf[ret] = '\0';
+       return RESOURCED_ERROR_NONE;
+}
+
+int proc_get_raw_cmdline(pid_t pid, char *buf, int len)
+{
+       char path[PROC_BUF_MAX];
+       snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
+       return proc_get_data(path, buf, len);
+}
+
+int proc_get_stat(pid_t pid, char *buf, int len)
+{
+       char path[PROC_BUF_MAX];
+       snprintf(path, sizeof(path), "/proc/%d/stat", pid);
+       return proc_get_data(path, buf, len);
+}
+
+int proc_get_status(pid_t pid, char *buf, int len)
+{
+       char path[PROC_BUF_MAX];
+       snprintf(path, sizeof(path), "/proc/%d/status", pid);
+       return proc_get_data(path, buf, len);
+}
+
+int proc_sys_node_trigger(enum sys_node_id sys_node_id)
+{
+       FILE *fp = NULL;
+
+       if (sys_node_id >= ARRAY_SIZE(sys_node_tables)) {
+               _E("sys_node_id[%d] is out of range.\n", sys_node_id);
+               return RESOURCED_ERROR_FAIL;
+       }
+       if (!sys_node_tables[sys_node_id].valid) {
+               _E("sys_node_id[%d] is not valid.\n", sys_node_id);
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       /* open and check if the path exists, else return fail */
+       fp = fopen(sys_node_tables[sys_node_id].path, "w");
+       if (fp == NULL) {
+               _E("Failed to open %s: %m\n",
+                       sys_node_tables[sys_node_id].path);
+               sys_node_tables[sys_node_id].valid = 0;
+               return RESOURCED_ERROR_FAIL;
+       }
+       fputc(sys_node_tables[sys_node_id].value, fp);
+       fclose(fp);
+       return RESOURCED_ERROR_NONE;
+}
+
+static const char* const meminfo_string_lookup[MEMINFO_ID_MAX] = {
+       [MEMINFO_ID_MEM_TOTAL]     = "MemTotal",
+       [MEMINFO_ID_MEM_FREE]      = "MemFree",
+       [MEMINFO_ID_MEM_AVAILABLE] = "MemAvailable",
+       [MEMINFO_ID_BUFFERS]       = "Buffers",
+       [MEMINFO_ID_CACHED]        = "Cached",
+       [MEMINFO_ID_SWAP_CACHED]   = "SwapCached",
+       [MEMINFO_ID_ACTIVE]        = "Active",
+       [MEMINFO_ID_INACTIVE]      = "Inactive",
+       [MEMINFO_ID_ACTIVE_ANON]   = "Active(anon)",
+       [MEMINFO_ID_INACTIVE_ANON] = "Inactive(anon)",
+       [MEMINFO_ID_ACTIVE_FILE]   = "Active(file)",
+       [MEMINFO_ID_INACTIVE_FILE] = "Inactive(file)",
+       [MEMINFO_ID_UNEVICTABLE]   = "Unevictable",
+       [MEMINFO_ID_MLOCKED]       = "Mlocked",
+       [MEMINFO_ID_HIGH_TOTAL]    = "HighTotal",
+       [MEMINFO_ID_HIGH_FREE]     = "HighFree",
+       [MEMINFO_ID_LOW_TOTAL]     = "LowTotal",
+       [MEMINFO_ID_LOW_FREE]      = "LowFree",
+       [MEMINFO_ID_SWAP_TOTAL]    = "SwapTotal",
+       [MEMINFO_ID_SWAP_FREE]     = "SwapFree",
+       [MEMINFO_ID_DIRTY]         = "Dirty",
+       [MEMINFO_ID_WRITEBACK]     = "Writeback",
+       [MEMINFO_ID_ANON_PAGES]    = "AnonPages",
+       [MEMINFO_ID_MAPPED]        = "Mapped",
+       [MEMINFO_ID_SHMEM]         = "Shmem",
+       [MEMINFO_ID_SLAB]          = "Slab",
+       [MEMINFO_ID_SRECLAIMABLE]  = "SReclaimable",
+       [MEMINFO_ID_SUNRECLAIM]    = "SUnreclaim",
+       [MEMINFO_ID_KERNEL_STACK]  = "KernelStack",
+       [MEMINFO_ID_PAGE_TABLES]   = "PageTables",
+       [MEMINFO_ID_NFS_UNSTABLE]  = "NFS_Unstable",
+       [MEMINFO_ID_BOUNCE]        = "Bounce",
+       [MEMINFO_ID_WRITEBACK_TMP] = "WritebackTmp",
+       [MEMINFO_ID_COMMIT_LIMIT]  = "CommitLimit",
+       [MEMINFO_ID_COMMITTED_AS]  = "Committed_AS",
+       [MEMINFO_ID_VMALLOC_TOTAL] = "VmallocTotal",
+       [MEMINFO_ID_VMALLOC_USED]  = "VmallocUsed",
+       [MEMINFO_ID_VMALLOC_CHUNK] = "VmallocChunk",
+};
+
+const char *meminfo_id_to_string(enum meminfo_id id)
+{
+       assert(id >= 0 && id < MEMINFO_ID_MAX);
+
+       return meminfo_string_lookup[id];
+}
+
+int proc_get_meminfo(struct meminfo *mi, unsigned long long mask)
+{
+       _cleanup_fclose_ FILE *f = NULL;
+       unsigned long long remain_mask = mask;
+       char buf[LINE_MAX];
+
+       assert(mi);
+
+       memset(mi, 0x0, sizeof(struct meminfo));
+
+       f = fopen("/proc/meminfo", "r");
+       if (!f) {
+               _E("Failed to read /proc/meminfo");
+               return -errno;
+       }
+
+       if (remain_mask & MEMINFO_MASK_MEM_AVAILABLE)
+               remain_mask |= (MEMINFO_MASK_MEM_FREE |
+                               MEMINFO_MASK_CACHED);
+
+       while (remain_mask) {
+               _cleanup_free_ char *k = NULL;
+               unsigned int v = 0;
+               enum meminfo_id id;
+               size_t l;
+
+               if (!fgets(buf, sizeof(buf), f)) {
+                       if (ferror(f))
+                               return -errno;
+                       break;
+               }
+
+               l = strcspn(buf, ":");
+               if (!l)
+                       break;
+
+               k = strndup(buf, l);
+               if (!k)
+                       return -errno;
+
+               id = meminfo_string_to_id(k);
+               if (id < 0 || id >= MEMINFO_ID_MAX)
+                       continue;
+
+               if (!(remain_mask & (1ULL << id)))
+                       continue;
+
+               remain_mask &= ~((1ULL << id));
+
+               if (sscanf(buf + l + 1, "%d", &v) != 1)
+                       break;
+
+               mi->value[id] = v;
+       }
+
+       if (remain_mask & MEMINFO_MASK_MEM_AVAILABLE) {
+               mi->value[MEMINFO_ID_MEM_AVAILABLE] =
+                       mi->value[MEMINFO_ID_MEM_FREE]
+                       + mi->value[MEMINFO_ID_CACHED];
+
+               remain_mask &= ~MEMINFO_MASK_MEM_AVAILABLE;
+       }
+
+       if (remain_mask) {
+               enum meminfo_id i;
+
+               for (i = 0; i < MEMINFO_ID_MAX; i++)
+                       if (remain_mask & (1ULL << i))
+                               _E("Failed to get meminfo: '%s'",
+                                  meminfo_id_to_string(i));
+       }
+
+       return RESOURCED_ERROR_NONE;
+}
+
+static int parse_spanned_pages(const char *s, regmatch_t *match,
+                               unsigned int parse_tag, void *data)
+{
+       char *e;
+       unsigned long v;
+       unsigned long *parse_v = (unsigned long *)data;
+
+       v = strtoul(s + match[1].rm_so, &e, 0);
+       *parse_v += v;
+
+       return 0;
+}
+
+int proc_get_ram_total(unsigned int *total_kb)
+{
+       unsigned long total_spanned = 0;
+       static unsigned int total_ram_kb = 0;
+       int ret;
+       const struct parse_arg args[] = {
+               PARSE_TAG("spanned[[:blank:]]+([0-9]+)\n",
+                         parse_spanned_pages, SPANNED),
+               PARSE_TAG_EMPTY(),
+       };
+
+       if (total_ram_kb > 0) {
+               *total_kb = total_ram_kb;
+               return RESOURCED_ERROR_NONE;
+       }
+
+       ret = proc_parse_zoneinfo(args, &total_spanned);
+       if (ret != RESOURCED_ERROR_NONE)
+               return RESOURCED_ERROR_NO_DATA;
+
+       total_ram_kb = (unsigned int)BYTE_TO_KBYTE((unsigned long long)total_spanned << PAGE_SHIFT);
+       *total_kb = total_ram_kb;
+
+       return RESOURCED_ERROR_NONE;
+}
+
+static inline char *proc_skip_blanks(const char *s)
+{
+       while (s && (isblank(*s) || !isalnum(*s)))
+               ++s;
+       return (char*)s;
+}
+
+#define PROC_MAX_REG_MATCH     6
+
+static int proc_find_match(char *s, const struct parse_arg *parse,
+                               void *data, size_t *parsed)
+{
+       regex_t regex;
+       regmatch_t match[PROC_MAX_REG_MATCH];
+       int result;
+
+       if (!s || !(*s != '\0'))
+               return -EINVAL;
+
+       if (!parse->callback)
+               return 0;
+
+       *parsed = 0;
+
+       result = regcomp(&regex, parse->re_exp, REG_EXTENDED);
+       if (!result) {
+               result = regexec(&regex, s, ARRAY_SIZE(match), match, 0);
+               if (!result) {
+                       regmatch_t *m = match;
+
+                       result =  parse->callback(s, match, parse->tag, data);
+                       if (result)
+                               goto leave;
+                       while ((m - match) < PROC_MAX_REG_MATCH &&
+                           m->rm_so >= 0 && m->rm_eo > 0)
+                               ++m;
+
+                       *parsed = m > match ? (--m)->rm_eo + 1 : 0;
+               }
+leave:
+               regfree(&regex);
+       }
+       return result;
+}
+
+/**
+ * @brief  Rather basic parser that relies on provided arguments,
+ *         specifying the actual expression to look for.
+ *         Note that it does not make any assumptions as to how
+ *         the input to be parsed is actual formated and  what is the
+ *         layout of the information held within it.
+ *         - mind it as badly specified arguments might result in a failure
+ *         to identify potential match or finding a match but not one that
+ *         has been expected. It is up to the caller to perform
+ *         the actual formatting of data.
+ *         Parsing is done per line with possible multiple regexes.
+ * @return Returns number of found matches against supplied parse arguments
+ */
+static int proc_parse_single(const char *buffer,
+                            const struct parse_arg *parse_args,
+                            void *data)
+{
+       char *s = (char*)buffer;
+       size_t size;
+       unsigned int match = 0;
+
+       while (s && *s != '\n' && *s != '\0') {
+               const struct parse_arg *p = parse_args;
+
+               size = 0;
+               s = proc_skip_blanks(s);
+
+               while (proc_find_match(s, p, data, &size))
+                       ++p;
+
+               if (!size)
+                       break;
+               s += size;
+               ++match;
+       }
+       return match;
+}
+
+/**
+ * @brief Simplified procfs parser
+ *
+ *  Reads the procfs entry line by line triggering regex match
+ *  function for each supplied argument.
+ *  Note: The set of arguments should end with an empty one.
+ *
+ * @return returns 0 upon successfully calling the actual parsing
+ *        procedure at least once, error code otherwise.
+ *        Note: it is up to the caller to properly handle
+ *        callbacks triggered upon each match found and to determine
+ *        if parsing itself actually succeeded.
+ */
+int proc_parse_entry(const char *path, const struct parse_arg *parse_args,
+                       void *data)
+{
+       char buf[LINE_MAX];
+       _cleanup_fclose_ FILE *f = NULL;
+
+       f = fopen(path, "r");
+       if (!f)
+               return -errno;
+
+       while (fgets(buf, sizeof(buf), f))
+               proc_parse_single(buf, parse_args, data);
+       return ferror(f) ? -errno : 0;
+}
+
+int proc_get_uptime(unsigned long *uptime)
+{
+       _cleanup_fclose_ FILE *fp = NULL;
+       double stime;
+
+       fp = fopen("/proc/uptime", "r");
+       if (fp == NULL)
+               return RESOURCED_ERROR_FAIL;
+
+       if (fscanf(fp, "%lf %*s", &stime) < 0)
+               return RESOURCED_ERROR_FAIL;
+
+       *uptime = (unsigned long)stime;
+       return RESOURCED_ERROR_NONE;
+}
+
+/**
+ * @brief print simple memory info with rss and memtotal
+ *
+ *  Reads the procfs about all process id and print RSS usage.
+ *  Note: If fp is valid, the result is written by desired file.
+ *            Otherwise, it printed message through dlog.
+ */
+void proc_print_meninfo(FILE *fp)
+{
+       _cleanup_closedir_ DIR *dir = NULL;
+       struct dirent *de;
+       pid_t pid, caller;
+       char cmdline[PATH_MAX];
+       _cleanup_fclose_ FILE *output_file = NULL;
+       int oom_score_adj, ret;
+       unsigned int rss, swap;
+       struct meminfo mi;
+       unsigned int free_kb = 0;
+       unsigned int total_mem_kb = 0, available_kb = 0, used_kb;
+       unsigned int swap_total_kb = 0, swap_free_kb = 0, swap_used_kb;
+       unsigned long long zram_used_bytes;
+
+       dir = opendir("/proc");
+       if (dir == NULL) {
+               _E("cannot read directory /proc.");
+               return;
+       }
+
+       LOG_DUMP(fp, "     PID    RSS    SWAP    OOM_SCORE    COMMAND\n");
+
+       caller = getpid();
+       while ((de = readdir(dir)) != NULL) {
+               pid = atoi(de->d_name);
+
+               /* exclude negative value which means string value and kernel thread */
+               if (pid < 1 || pid == caller)
+                       continue;
+
+               ret = proc_get_cmdline(pid, cmdline, sizeof cmdline);
+               if (ret)
+                       continue;
+
+               ret = proc_get_mem_status(pid, &swap, &rss);
+               if (ret)
+                       continue;
+
+               ret = proc_get_oom_score_adj(pid, &oom_score_adj);
+               if (ret)
+                       continue;
+
+               LOG_DUMP(fp, "%8d %8u  %8u %8d          %s\n",
+                               pid,
+                               rss,
+                               swap,
+                               oom_score_adj,
+                               cmdline);
+
+       } /* end of while */
+
+       ret = proc_get_meminfo(&mi,
+                       (MEMINFO_MASK_MEM_TOTAL |
+                        MEMINFO_MASK_MEM_FREE |
+                        MEMINFO_MASK_MEM_AVAILABLE |
+                        MEMINFO_MASK_CACHED |
+                        MEMINFO_MASK_SWAP_TOTAL |
+                        MEMINFO_MASK_SWAP_FREE));
+       if (ret < 0) {
+               _E("Failed to get meminfo");
+               return;
+       }
+
+       total_mem_kb = mi.value[MEMINFO_ID_MEM_TOTAL];
+       free_kb = mi.value[MEMINFO_ID_MEM_FREE];
+       available_kb = mi.value[MEMINFO_ID_MEM_AVAILABLE];
+       swap_total_kb = mi.value[MEMINFO_ID_SWAP_TOTAL];
+       swap_free_kb = mi.value[MEMINFO_ID_SWAP_FREE];
+
+       used_kb = total_mem_kb - available_kb;
+       swap_used_kb = swap_total_kb - swap_free_kb;
+
+       ret = fread_nth_ulonglong(SWAP_ZRAM_SYSFILE"mm_stat", 2, &zram_used_bytes);
+       if (ret == -ENOENT) {
+               ret = fread_ulonglong(SWAP_ZRAM_SYSFILE"mem_used_total", &zram_used_bytes);
+       }
+
+       if (ret != RESOURCED_ERROR_NONE)
+               zram_used_bytes = 0;
+
+       LOG_DUMP(fp, "====================================================================\n");
+       LOG_DUMP(fp, "Total RAM size: \t%15d MB( %6d kB)\n",
+                       KBYTE_TO_MBYTE(total_mem_kb), total_mem_kb);
+       LOG_DUMP(fp, "Used (Mem+Reclaimable): %15d MB( %6d kB)\n",
+                       KBYTE_TO_MBYTE(total_mem_kb - free_kb), total_mem_kb - free_kb);
+       LOG_DUMP(fp, "Used (Mem+Swap): \t%15d MB( %6d kB)\n",
+                       KBYTE_TO_MBYTE(used_kb), used_kb);
+       LOG_DUMP(fp, "Used (Mem):  \t\t%15d MB( %6d kB)\n",
+                       KBYTE_TO_MBYTE(used_kb), used_kb);
+       LOG_DUMP(fp, "Used (Swap): \t\t%15d MB( %6d kB)\n",
+                       KBYTE_TO_MBYTE(swap_used_kb), swap_used_kb);
+       LOG_DUMP(fp, "Used (Zram block device): %13d MB( %6d kB)\n",
+                       (int)BYTE_TO_MBYTE(zram_used_bytes), (int)BYTE_TO_KBYTE(zram_used_bytes));
+       LOG_DUMP(fp, "Mem Free:\t\t%15d MB( %6d kB)\n",
+                       KBYTE_TO_MBYTE(free_kb), free_kb);
+       LOG_DUMP(fp,  "Available (Free+Reclaimable):%10d MB( %6d kB)\n",
+                       KBYTE_TO_MBYTE(available_kb), available_kb);
+       return;
+}
+
+int proc_get_buddyinfo(const char *zone, struct buddyinfo *bi)
+{
+       _cleanup_fclose_ FILE *f = NULL;
+       char buf[LINE_MAX];
+
+       g_assert(zone);
+       g_assert(bi);
+
+       f = fopen("/proc/buddyinfo", "re");
+       if (!f)
+               return -errno;
+
+       for (;;) {
+               int n;
+               char zonename[32] = { 0, };
+
+               if (!fgets(buf, sizeof(buf), f)) {
+                       if (ferror(f))
+                               return -errno;
+
+                       break;
+               }
+
+               n = sscanf(buf, "Node %d, zone %31s %d %d %d %d %d %d %d %d %d %d %d",
+                          &bi->node,
+                          zonename,
+                          &bi->page[PAGE_4K],
+                          &bi->page[PAGE_8K],
+                          &bi->page[PAGE_16K],
+                          &bi->page[PAGE_32K],
+                          &bi->page[PAGE_64K],
+                          &bi->page[PAGE_128K],
+                          &bi->page[PAGE_256K],
+                          &bi->page[PAGE_512K],
+                          &bi->page[PAGE_1M],
+                          &bi->page[PAGE_2M],
+                          &bi->page[PAGE_4M]);
+               if (n != 13)
+                       break;
+
+               if (!streq(zone, zonename))
+                       continue;
+
+               return 0;
+       }
+
+       return -ENODATA;
+}
+
+void proc_swap_free(struct proc_swaps *swap)
+{
+       if (!swap)
+               return;
+
+       free(swap->filename);
+       free(swap->type);
+       free(swap);
+}
+
+void proc_swaps_free(struct proc_swaps **swaps)
+{
+       int i;
+
+       if (!swaps)
+               return;
+
+       for (i = 0; swaps[i]; i++)
+               proc_swap_free(swaps[i]);
+
+       free(swaps);
+}
+
+int proc_get_swaps(struct proc_swaps ***swaps)
+{
+       _cleanup_proc_swaps_free_ struct proc_swaps **ss = NULL;
+       _cleanup_fclose_ FILE *f = NULL;
+       char buf[LINE_MAX];
+       size_t cnt = 0;
+
+       assert(swaps);
+       assert(!*swaps);
+
+       f = fopen("/proc/swaps", "re");
+       if (!f)
+               return -errno;
+
+       for (;;) {
+               _cleanup_proc_swap_free_ struct proc_swaps *swap = NULL;
+
+               if (!fgets(buf, sizeof(buf), f)) {
+                       if (ferror(f))
+                               return -errno;
+
+                       break;
+               }
+
+               swap = calloc(sizeof(struct proc_swaps), 1);
+               if (!swap)
+                       return -ENOMEM;
+
+               if (sscanf(buf, "%ms %ms %u %u %d",
+                          &swap->filename,
+                          &swap->type,
+                          &swap->size,
+                          &swap->used,
+                          &swap->priority) != 5)
+                       continue;
+
+               ss = (struct proc_swaps **)realloc(ss, sizeof(struct proc_swaps *) * (cnt + 2));
+               if (!ss)
+                       return -ENOMEM;
+
+               ss[cnt++] = swap;
+               ss[cnt] = NULL;
+               swap = NULL;
+       }
+
+       *swaps = ss;
+       ss = NULL;
+
+       return cnt;
+}
diff --git a/src/common/procfs/procfs.h b/src/common/procfs/procfs.h
new file mode 100644 (file)
index 0000000..c2c0f52
--- /dev/null
@@ -0,0 +1,485 @@
+/*
+ * resourced
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __PROCFS_H__
+#define __PROCFS_H__
+
+#include <resourced.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include <regex.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "proc-common.h"
+
+#define OOMADJ_SU                      (0)
+#define OOMADJ_INIT                    (100)
+#define OOMADJ_FOREGRD_LOCKED          (150)
+#define OOMADJ_FOREGRD_UNLOCKED                (200)
+#define OOMADJ_BACKGRD_PERCEPTIBLE     (230)
+#define OOMADJ_BACKGRD_LOCKED          (250)
+#define OOMADJ_FAVORITE                        (270)
+#define OOMADJ_BACKGRD_UNLOCKED                (300)
+#define OOMADJ_RECENTLY_USED            (430)
+#define OOMADJ_BACKGRD_OLD              (450)
+#define OOMADJ_APP_MAX                 (990)
+#define OOMADJ_APP_INCREASE            (30)
+
+#define OOMADJ_FAVORITE_APP_MAX (OOMADJ_PREVIOUS_BACKGRD - OOMADJ_FAVORITE_APP_INCREASE)
+#define OOMADJ_FAVORITE_APP_INCREASE (1)
+
+/* OOMADJ_SERVICE_DEFAULT is default value for processes PROC_TYPE_SERVICE */
+#define OOMADJ_SERVICE_GAP             (10)
+#define OOMADJ_SERVICE_DEFAULT         (OOMADJ_BACKGRD_LOCKED - OOMADJ_SERVICE_GAP)
+
+/*
+ * OOMADJ_PREVIOUS_DEFAULT is default value for processes that are
+ * moved out from foreground cgroup ( >= OOMADJ_BACKGRD_PERCEPTIBLE)
+ * but being in a state before background cgroup ( >= OOMADJ_BACKGRD_UNLOCKED).
+ * In the middle it is possible to have process in favorite cgroup (== OOMADJ_FAVORITE).
+ */
+#define OOMADJ_PREVIOUS_GAP            (10)
+#define OOMADJ_PREVIOUS_DEFAULT                (OOMADJ_BACKGRD_LOCKED - OOMADJ_PREVIOUS_GAP)
+#define OOMADJ_PREVIOUS_BACKGRD        (OOMADJ_BACKGRD_UNLOCKED - OOMADJ_PREVIOUS_GAP)
+
+
+#define PROC_OOM_SCORE_ADJ_PATH "/proc/%d/oom_score_adj"
+#define PROC_STAT_PATH "/proc/%d/stat"
+#define PROC_ZONEINFO_PATH     "/proc/zoneinfo"
+#define PROC_PAGETYPEINFO_PATH  "/proc/pagetypeinfo"
+#define PROC_BUDDYINFO_PATH    "/proc/buddyinfo"
+
+enum meminfo_id {
+       MEMINFO_ID_INVALID = -1,
+       MEMINFO_ID_MEM_TOTAL = 0,
+       MEMINFO_ID_MEM_FREE,
+       MEMINFO_ID_MEM_AVAILABLE,
+       MEMINFO_ID_BUFFERS,
+       MEMINFO_ID_CACHED,
+       MEMINFO_ID_SWAP_CACHED,
+       MEMINFO_ID_ACTIVE,
+       MEMINFO_ID_INACTIVE,
+       MEMINFO_ID_ACTIVE_ANON,
+       MEMINFO_ID_INACTIVE_ANON,
+       MEMINFO_ID_ACTIVE_FILE,
+       MEMINFO_ID_INACTIVE_FILE,
+       MEMINFO_ID_UNEVICTABLE,
+       MEMINFO_ID_MLOCKED,
+       MEMINFO_ID_HIGH_TOTAL,
+       MEMINFO_ID_HIGH_FREE,
+       MEMINFO_ID_LOW_TOTAL,
+       MEMINFO_ID_LOW_FREE,
+       MEMINFO_ID_SWAP_TOTAL,
+       MEMINFO_ID_SWAP_FREE,
+       MEMINFO_ID_DIRTY,
+       MEMINFO_ID_WRITEBACK,
+       MEMINFO_ID_ANON_PAGES,
+       MEMINFO_ID_MAPPED,
+       MEMINFO_ID_SHMEM,
+       MEMINFO_ID_SLAB,
+       MEMINFO_ID_SRECLAIMABLE,
+       MEMINFO_ID_SUNRECLAIM,
+       MEMINFO_ID_KERNEL_STACK,
+       MEMINFO_ID_PAGE_TABLES,
+       MEMINFO_ID_NFS_UNSTABLE,
+       MEMINFO_ID_BOUNCE,
+       MEMINFO_ID_WRITEBACK_TMP,
+       MEMINFO_ID_COMMIT_LIMIT,
+       MEMINFO_ID_COMMITTED_AS,
+       MEMINFO_ID_VMALLOC_TOTAL,
+       MEMINFO_ID_VMALLOC_USED,
+       MEMINFO_ID_VMALLOC_CHUNK,
+       MEMINFO_ID_MAX,
+};
+
+#define MEMINFO_MASK_MEM_TOTAL     (1ULL << MEMINFO_ID_MEM_TOTAL)
+#define MEMINFO_MASK_MEM_FREE      (1ULL << MEMINFO_ID_MEM_FREE)
+#define MEMINFO_MASK_MEM_AVAILABLE (1ULL << MEMINFO_ID_MEM_AVAILABLE)
+#define MEMINFO_MASK_BUFFERS       (1ULL << MEMINFO_ID_BUFFERS)
+#define MEMINFO_MASK_CACHED        (1ULL << MEMINFO_ID_CACHED)
+#define MEMINFO_MASK_SWAP_CACHED   (1ULL << MEMINFO_ID_SWAP_CACHED)
+#define MEMINFO_MASK_ACTIVE        (1ULL << MEMINFO_ID_ACTIVE)
+#define MEMINFO_MASK_INACTIVE      (1ULL << MEMINFO_ID_INACTIVE)
+#define MEMINFO_MASK_ACTIVE_ANON   (1ULL << MEMINFO_ID_ACTIVE_ANON)
+#define MEMINFO_MASK_INACTIVE_ANON (1ULL << MEMINFO_ID_INACTIVE_ANON)
+#define MEMINFO_MASK_ACTIVE_FILE   (1ULL << MEMINFO_ID_ACTIVE_FILE)
+#define MEMINFO_MASK_INACTIVE_FILE (1ULL << MEMINFO_ID_INACTIVE_FILE)
+#define MEMINFO_MASK_UNEVICTABLE   (1ULL << MEMINFO_ID_UNEVICTABLE)
+#define MEMINFO_MASK_MLOCKED       (1ULL << MEMINFO_ID_MLOCKED)
+#define MEMINFO_MASK_HIGH_TOTAL    (1ULL << MEMINFO_ID_HIGH_TOTAL)
+#define MEMINFO_MASK_HIGH_FREE     (1ULL << MEMINFO_ID_HIGH_FREE)
+#define MEMINFO_MASK_LOW_TOTAL     (1ULL << MEMINFO_ID_LOW_TOTAL)
+#define MEMINFO_MASK_LOW_FREE      (1ULL << MEMINFO_ID_LOW_FREE)
+#define MEMINFO_MASK_SWAP_TOTAL    (1ULL << MEMINFO_ID_SWAP_TOTAL)
+#define MEMINFO_MASK_SWAP_FREE     (1ULL << MEMINFO_ID_SWAP_FREE)
+#define MEMINFO_MASK_DIRTY         (1ULL << MEMINFO_ID_DIRTY)
+#define MEMINFO_MASK_WRITEBACK     (1ULL << MEMINFO_ID_WRITEBACK)
+#define MEMINFO_MASK_ANON_PAGES    (1ULL << MEMINFO_ID_ANON_PAGES)
+#define MEMINFO_MASK_MAPPED        (1ULL << MEMINFO_ID_MAPPED)
+#define MEMINFO_MASK_SHMEM         (1ULL << MEMINFO_ID_SHMEM)
+#define MEMINFO_MASK_SLAB          (1ULL << MEMINFO_ID_SLAB)
+#define MEMINFO_MASK_SRECLAIMABLE  (1ULL << MEMINFO_ID_SRECLAIMABLE)
+#define MEMINFO_MASK_SUNRECLAIM    (1ULL << MEMINFO_ID_SUNRECLAIM)
+#define MEMINFO_MASK_KERNEL_STACK  (1ULL << MEMINFO_ID_KERNEL_STACK)
+#define MEMINFO_MASK_PAGE_TABLES   (1ULL << MEMINFO_ID_PAGE_TABLES)
+#define MEMINFO_MASK_NFS_UNSTABLE  (1ULL << MEMINFO_ID_NFS_UNSTABLE)
+#define MEMINFO_MASK_BOUNCE        (1ULL << MEMINFO_ID_BOUNCE)
+#define MEMINFO_MASK_WRITEBACK_TMP (1ULL << MEMINFO_ID_WRITEBACK_TMP)
+#define MEMINFO_MASK_COMMIT_LIMIT  (1ULL << MEMINFO_ID_COMMIT_LIMIT)
+#define MEMINFO_MASK_COMMITTED_AS  (1ULL << MEMINFO_ID_COMMITTED_AS)
+#define MEMINFO_MASK_VMALLOC_TOTAL (1ULL << MEMINFO_ID_VMALLOC_TOTAL)
+#define MEMINFO_MASK_VMALLOC_USED  (1ULL << MEMINFO_ID_VMALLOC_USED)
+#define MEMINFO_MASK_VMALLOC_CHUNK (1ULL << MEMINFO_ID_VMALLOC_CHUNK)
+#define MEMINFO_MASK_ALL           ((1ULL << MEMINFO_ID_MAX) - 1)
+
+struct meminfo_mapping {
+       const char *name;
+       enum meminfo_id id;
+};
+typedef struct meminfo_mapping meminfo_mapping;
+
+const meminfo_mapping *meminfo_mapping_lookup(const char *str, unsigned int len);
+
+static inline enum meminfo_id meminfo_string_to_id(const char *str)
+{
+       const struct meminfo_mapping *i;
+
+       assert(str);
+       i = meminfo_mapping_lookup(str, strlen(str));
+       return i ? i->id : MEMINFO_ID_INVALID;
+}
+
+const char *meminfo_id_to_string(enum meminfo_id);
+
+struct meminfo {
+       unsigned int value[MEMINFO_ID_MAX];
+};
+
+/**
+ * @desc get info corresponding size(kB) from /proc/meminfo
+ * @note given meminfo struct is set all zero before filled
+ * @return 0 on success, return negative error code on fail.
+ */
+int proc_get_meminfo(struct meminfo *mi, unsigned long long mask);
+
+/*
+ * This interface is required by proc_sys_node_trigger(...)
+ */
+enum sys_node_id {
+       SYS_VM_SHRINK_MEMORY,
+       SYS_VM_COMPACT_MEMORY,
+};
+
+/*
+ * Here,
+ * @path is /proc/sys/vm/{shrink,compact}_memory
+ * @value is always 1
+ * @valid - indicates whether the node is present in kernel or not
+ */
+struct sys_node_table {
+       enum sys_node_id sys_node_id;
+       const char *path;
+       int value;
+       int valid;
+};
+
+/**
+ * @brief procfs entry parser arguments
+ * @re_exp regular expression to look for
+ * @callback callback function to be called once the arg match is identified
+ * @tag unique identifier of the argument
+ */
+struct parse_arg {
+       const char *re_exp;
+       int (*callback)(const char*, regmatch_t *, unsigned int, void *);
+       unsigned int tag;
+};
+
+#define PARSE_TAG(exp, fn, id) \
+{ \
+       .re_exp  = exp, \
+       .callback = fn, \
+       .tag = PARSE_TAG_##id, \
+}
+
+#define PARSE_TAG_EMPTY()  {0,}
+
+enum {
+       PARSE_TAG_ZONE = 1,
+       PARSE_TAG_PAGE_COUNT,
+       PARSE_TAG_WM_MIN,
+       PARSE_TAG_WM_LOW,
+       PARSE_TAG_WM_HIGH,
+       PARSE_TAG_MANAGED,
+       PARSE_TAG_SPANNED,
+       PARSE_TAG_MAX,
+};
+
+
+/**
+ * @desc get command line from /proc/{pid}/cmdline if pid is greater than 0
+ * it get /proc/cmdline if pid is 0
+ * @return negative value if error
+ */
+int proc_get_cmdline(pid_t pid, char *cmdline, size_t maxcmdline);
+
+/**
+ * @desc find pid with /proc/{pid}/cmdline
+ * it returns first entry when many pids have same cmdline
+ * @return negative value if error
+ */
+pid_t find_pid_from_cmdline(char *cmdline);
+
+/**
+ * @desc get oom score adj value from /proc/{pid}/oom_score_adj
+ * @return negative value if error or pid doesn't exist
+ */
+int proc_get_oom_score_adj(int pid, int *oom_score_adj);
+
+/**
+ * @desc set oom score adj value to /proc/{pid}/oom_score_adj
+ * @return negative value if error or pid doesn't exist
+ */
+int proc_set_oom_score_adj(int pid, int oom_score_adj, struct proc_app_info *pai);
+
+/**
+ * @desc get smack subject label from /proc/{pid}/attr/current
+ * this label can indicate package name about child processes
+ * @return negative value if error or pid doesn't exist
+ */
+int proc_get_label(pid_t pid, char *label);
+
+/**
+ * @desc get USS memory usage from /proc/{pid}/smaps file.
+ * @return negative value if error or pid doesn't exist
+ */
+int proc_get_uss(pid_t pid, unsigned int *uss);
+
+/**
+ * @desc get VmRSS and VmSwap from /proc/{pid}/status file.
+ * @return negative value if error or pid doesn't exist
+ */
+int proc_get_mem_status(pid_t pid, unsigned int *swap, unsigned int *rss);
+
+/**
+ * @desc get aproximated usage of Zram for pid
+ * @return negative value if error or pid doesn't exist
+ */
+int proc_get_zram_usage(pid_t pid, unsigned int *usage);
+
+/**
+ * @desc get approximate memory usage from status and statm
+ * @return negative value if error or pid doesn't exist
+ */
+int proc_get_approx_mem_usage(pid_t pid, unsigned int *usage);
+
+/**
+ * @desc get total memory usage from VmSwap and VmRSS.
+ * @return negative value if error or pid doesn't exist
+ */
+int proc_get_mem_usage(pid_t pid, unsigned int *usage);
+
+/**
+ * @desc get how much ram is used in each application
+ * @return negative value if error or pid doesn't exist
+ */
+int proc_get_ram_usage(pid_t pid, unsigned int *usage);
+
+/**
+ * @desc get MemAvaliable from /proc/meminfo or calcuate it by MemFree+Cached
+ * @return 0 if the values can't be read or the avaliable memory value
+ */
+unsigned int proc_get_mem_available(void);
+
+/**
+ * @desc get SwapFree from /proc/meminfo
+ * @return 0 if the values can't be read or the free swap memory
+ */
+unsigned int proc_get_swap_free(void);
+
+/**
+ * @desc get SwapTotal from /proc/meminfo
+ * @return 0 if the values can't be read or the total swap size
+ */
+unsigned int proc_get_swap_total(void);
+
+/**
+ * @desc get number of CPUs from /proc/cpuinfo
+ * @return 0 if the number can't be found or number of CPUs
+ */
+unsigned int proc_get_cpu_number(void);
+
+/**
+ * @desc get utime and stime from /proc/{pid}/stat file.
+ * @return negative value if error or pid doesn't exist
+ */
+int proc_get_cpu_time(pid_t pid, unsigned long *utime, unsigned long *stime,
+                                       unsigned long *starttime);
+
+/**
+ * @desc get command line from /proc/{pid}/cmdline without any truncation
+ * @return negative value if error
+ */
+int proc_get_raw_cmdline(pid_t pid, char *buf, int len);
+
+/**
+ * @desc get symblolic link about /proc/{pid}/exe
+ * @return negative value if error
+ */
+int proc_get_exepath(pid_t pid, char *buf, int len);
+
+/**
+ * @desc get stat from /proc/{pid}/stat
+ * @return negative value if error
+ */
+int proc_get_stat(pid_t pid, char *buf, int len);
+
+/**
+ * @desc get status from /proc/{pid}/status
+ * @return negative value if error
+ */
+int proc_get_status(pid_t pid, char *buf, int len);
+
+/**
+ * @desc invoke shrink_memory or compact_memory vm parameter.
+ * @return none
+ */
+int proc_sys_node_trigger(enum sys_node_id sys_node_id);
+
+/**
+ * @desc get uptime from system time of /proc/uptime
+ * @return negative value if error
+ */
+int proc_get_uptime(unsigned long *uptime);
+
+/**
+ * @desc get total ram size including reserved memory
+ * @param[out] total Ram size in kilobytes
+ * @return negative value if error
+ */
+int proc_get_ram_total(unsigned int *total);
+
+/**
+ * @brief print uss and memtotal for showing brief memory information
+ */
+void proc_print_meninfo(FILE *fp);
+
+enum {
+       PAGE_4K = 0,
+       PAGE_8K,
+       PAGE_16K,
+       PAGE_32K,
+       PAGE_64K,
+       PAGE_128K,
+       PAGE_256K,
+       PAGE_512K,
+       PAGE_1M,
+       PAGE_2M,
+       PAGE_4M,
+       PAGE_MAX,
+};
+
+struct buddyinfo {
+       int node;
+       int page[PAGE_MAX];
+};
+
+/**
+ * @desc get buddyinfo of specific zone from /proc/buddyinfo
+ * @return negative value if error
+ */
+int proc_get_buddyinfo(const char *zone, struct buddyinfo *bi);
+
+/**
+ * @brief Generic, simplified procfs parser
+ *
+ * @path       path to the procfs entry
+ * @parse_args set of arguments specifying regular expressions
+ *              to be searched for within the procfs entry
+ * @data       custom data supplied to each parse callback function
+ *          specified within the parse arguments
+ */
+int proc_parse_entry(const char *path, const struct parse_arg *parse_args,
+                       void *data);
+
+/**
+ * @bried /proc/zoneinfo parser
+ */
+static inline int proc_parse_zoneinfo(const struct parse_arg *parse_args,
+                                       void *data)
+{
+       return proc_parse_entry(PROC_ZONEINFO_PATH, parse_args, data);
+}
+/**
+ * @brief /proc/pagetypeinfo parser
+ */
+static inline int proc_parse_pagetypeinfo(const struct parse_arg *parse_args,
+                                               void *data)
+{
+       return proc_parse_entry(PROC_PAGETYPEINFO_PATH, parse_args, data);
+}
+
+static inline int proc_parse_buddyinfo(const struct parse_arg *parse_args,
+                                        void *data)
+{
+       return proc_parse_entry(PROC_BUDDYINFO_PATH, parse_args, data);
+}
+
+struct proc_swaps {
+       char *filename;
+       char *type;
+       unsigned int size;
+       unsigned int used;
+       int priority;
+};
+
+void proc_swap_free(struct proc_swaps *swap);
+void proc_swaps_free(struct proc_swaps **swaps);
+
+static inline void __cleanup_proc_swap_free_func(struct proc_swaps **swap)
+{
+       proc_swap_free(*swap);
+}
+
+#define _cleanup_proc_swap_free_ _cleanup_(__cleanup_proc_swap_free_func)
+
+static inline void __cleanup_proc_swaps_free_func(struct proc_swaps ***swaps)
+{
+       proc_swaps_free(*swaps);
+}
+
+#define _cleanup_proc_swaps_free_ _cleanup_(__cleanup_proc_swaps_free_func)
+
+/**
+ * @desc get swap info from /proc/swaps
+ * @return negative value if errors, positive value means total enties of swap devices
+ */
+int proc_get_swaps(struct proc_swaps ***swaps);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /*__PROCFS_H__*/
diff --git a/src/common/procfs/smaps-lookup.c b/src/common/procfs/smaps-lookup.c
new file mode 100644 (file)
index 0000000..9a2b3f7
--- /dev/null
@@ -0,0 +1,133 @@
+/* NOTE: this file was dynamically generated by gperf but is included verbatim (instead of
+ * being regenerated) due to various build environment issues */
+
+/* ANSI-C code produced by gperf version 3.0.4 */
+/* Command-line: gperf /home/abuild/rpmbuild/BUILD/resourced-6.0.2/src/common/smaps-lookup.gperf  */
+/* Computed positions: -k'1,$' */
+
+#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
+      && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
+      && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
+      && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
+      && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
+      && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
+      && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
+      && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
+      && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
+      && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
+      && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
+      && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
+      && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
+      && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
+      && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
+      && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
+      && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
+      && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
+      && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
+      && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
+      && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
+      && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
+      && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
+/* The character set is not based on ISO-646.  */
+#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
+#endif
+
+#include "smaps.h"
+#include <string.h>
+
+#define TOTAL_KEYWORDS 15
+#define MIN_WORD_LENGTH 3
+#define MAX_WORD_LENGTH 14
+#define MIN_HASH_VALUE 3
+#define MAX_HASH_VALUE 24
+/* maximum key range = 22, duplicates = 0 */
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static unsigned int
+smap_mapping_hash (register const char *str, register unsigned int len)
+{
+  static const unsigned char asso_values[] =
+    {
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 10, 25, 25, 25, 25,
+      25, 25, 25, 25, 25,  5,  0,  0, 25, 25,
+       0, 25,  5,  0, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+       0,  5, 25, 25, 25, 25, 25, 25, 25, 25,
+       5, 25,  0, 25, 25,  0, 25, 25, 25, 25,
+      25,  0, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25
+    };
+  return len + asso_values[(unsigned char)str[len - 1]] + asso_values[(unsigned char)str[0]];
+}
+
+#ifdef __GNUC__
+__inline
+#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
+__attribute__ ((__gnu_inline__))
+#endif
+#endif
+const smap_mapping *
+smap_mapping_lookup (register const char *str, register unsigned int len)
+{
+  static const smap_mapping wordlist[] =
+    {
+      {""}, {""}, {""},
+      {"Pss",            SMAPS_ID_PSS},
+      {"Swap",           SMAPS_ID_SWAP},
+      {"PSwap",          SMAPS_ID_PSWAP},
+      {"Locked",         SMAPS_ID_LOCKED},
+      {""},
+      {"Rss",            SMAPS_ID_RSS},
+      {"Size",           SMAPS_ID_SIZE},
+      {""}, {""},
+      {"Shared_Dirty",   SMAPS_ID_SHARED_DIRTY},
+      {"Private_Dirty",  SMAPS_ID_PRIVATE_DIRTY}, // patrollin' tryna catch me private dirty
+      {""},
+      {"Referenced",     SMAPS_ID_REFERENCED},
+      {"MMUPageSize",    SMAPS_ID_MMU_PAGE_SIZE},
+      {"Shared_Clean",   SMAPS_ID_SHARED_CLEAN},
+      {"Private_Clean",  SMAPS_ID_PRIVATE_CLEAN},
+      {"Anonymous",      SMAPS_ID_ANONYMOUS},
+      {""}, {""}, {""},
+      {"AnonHugePages",  SMAPS_ID_ANON_HUGE_PAGES},
+      {"KernelPageSize", SMAPS_ID_KERNEL_PAGE_SIZE}
+    };
+
+  if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
+    {
+      register int key = smap_mapping_hash (str, len);
+
+      if (key <= MAX_HASH_VALUE && key >= 0)
+        {
+          register const char *s = wordlist[key].name;
+
+          if (*str == *s && !strcmp (str + 1, s + 1))
+            return &wordlist[key];
+        }
+    }
+  return 0;
+}
diff --git a/src/common/procfs/smaps-lookup.gperf b/src/common/procfs/smaps-lookup.gperf
new file mode 100644 (file)
index 0000000..27112cb
--- /dev/null
@@ -0,0 +1,28 @@
+%{
+#include "smaps.h"
+%}
+smap_mapping;
+%language=ANSI-C
+%define slot-name name
+%define hash-function-name smap_mapping_hash
+%define lookup-function-name smap_mapping_lookup
+%readonly-tables
+%omit-struct-type
+%struct-type
+%includes
+%%
+AnonHugePages,  SMAPS_ID_ANON_HUGE_PAGES
+Anonymous,      SMAPS_ID_ANONYMOUS
+KernelPageSize, SMAPS_ID_KERNEL_PAGE_SIZE
+Locked,         SMAPS_ID_LOCKED
+MMUPageSize,    SMAPS_ID_MMU_PAGE_SIZE
+PSwap,          SMAPS_ID_PSWAP
+Private_Clean,  SMAPS_ID_PRIVATE_CLEAN
+Private_Dirty,  SMAPS_ID_PRIVATE_DIRTY
+Pss,            SMAPS_ID_PSS
+Referenced,     SMAPS_ID_REFERENCED
+Rss,            SMAPS_ID_RSS
+Shared_Clean,   SMAPS_ID_SHARED_CLEAN
+Shared_Dirty,   SMAPS_ID_SHARED_DIRTY
+Size,           SMAPS_ID_SIZE
+Swap,           SMAPS_ID_SWAP
diff --git a/src/common/procfs/smaps.c b/src/common/procfs/smaps.c
new file mode 100644 (file)
index 0000000..6d940cf
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * resourced
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * @file smaps.c
+ * @desc get smaps info of process
+ */
+
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+
+#include "util.h"
+#include "smaps.h"
+#include "trace.h"
+
+static int have_totmaps = 0;
+
+static bool totmaps_available(void)
+{
+       if (have_totmaps == 2)
+               have_totmaps = (access("/proc/1/totmaps", R_OK) == 0);
+
+       return have_totmaps;
+}
+
+static void smap_free(struct smap *map)
+{
+       if (!map)
+               return;
+
+       if (map->mode)
+               free(map->mode);
+
+       if (map->name)
+               free(map->name);
+
+       free(map);
+}
+
+void smaps_free(struct smaps *maps)
+{
+       int i;
+
+       if (!maps)
+               return;
+
+       for (i = 0; i < maps->n_map; i++)
+               smap_free(maps->maps[i]);
+
+       free(maps->maps);
+       free(maps);
+}
+
+static int add_smap_to_smaps(struct smaps *maps, struct smap *map)
+{
+       int i;
+
+       assert(maps);
+       assert(map);
+
+       maps->n_map++;
+
+       maps->maps = (struct smap **)realloc(
+               maps->maps,
+               sizeof(struct smap *) * maps->n_map);
+       if (!maps->maps)
+               return -ENOMEM;
+
+       maps->maps[maps->n_map - 1] = map;
+
+       for (i = 0; i < SMAPS_ID_MAX; i++)
+               maps->sum[i] += map->value[i];
+
+       return 0;
+}
+
+int smaps_get(pid_t pid, struct smaps **maps, enum smap_mask mask)
+{
+       _cleanup_free_ char *path = NULL;
+       _cleanup_fclose_ FILE *f = NULL;
+       struct smaps *m = NULL;
+       char buf[LINE_MAX];
+       bool get_line = true, totmaps;
+       int r;
+       struct smap *map;
+
+       assert(maps);
+
+       totmaps = totmaps_available();
+       if (totmaps && (mask & ~SMAPS_MASK_TOTMAPS) == 0) {
+               r = asprintf(&path, "/proc/%d/totmaps", pid);
+       } else {
+               totmaps = false;
+               r = asprintf(&path, "/proc/%d/smaps", pid);
+       }
+
+       if (r < 0)
+               return -ENOMEM;
+
+       f = fopen(path, "re");
+       if (!f)
+               return -errno;
+
+       m = new0(struct smaps, 1);
+       if (!m)
+               return -ENOMEM;
+
+       for (;;) {
+               map = NULL;
+               int n;
+               size_t l;
+               enum smap_id id;
+
+               if (get_line && !fgets(buf, sizeof(buf), f)) {
+                       if (ferror(f)) {
+                               r = -errno;
+                               goto on_error;
+                       }
+                       break;
+               }
+               get_line = true;
+
+               /*
+                * If totmaps are available and the caller doesn't
+                * need fields exclusive to smaps, we use them here.
+                * Reading totmaps is on average 20 times faster than
+                * reading smaps.
+                */
+               if (totmaps) {
+                       unsigned int v = 0;
+
+                       l = strcspn(buf, ":");
+                       if (l >= sizeof(buf) - 2 || !buf[l])
+                               goto totmaps_error;
+                       buf[l] = 0;
+
+                       id = smap_string_to_id(buf);
+                       if (id < 0 || id >= SMAPS_ID_MAX)
+                               continue;
+
+                       if (sscanf(buf + l + 1, "%d kB", &v) != 1)
+                               goto totmaps_error;
+
+                       m->sum[id] = v;
+                       continue;
+
+totmaps_error:
+                       _E("Unknown totmaps format, expected: '%%s : %%d kB'");
+                       r = -EIO;
+                       have_totmaps = 0; // don't ever read totmaps again
+                       goto on_error;
+               }
+
+               map = new0(struct smap, 1);
+               if (!map) {
+                       r = -errno;
+                       goto on_error;
+               }
+
+               n = sscanf(buf, "%x-%x %ms %*s %*s %*s %ms",
+                          &map->start, &map->end, &map->mode, &map->name);
+
+               if (n == 3 && !map->name)
+                       map->name = strndup("[anon]", strlen("[anon]"));
+               else if (n != 4) {
+                       r = -EINVAL;
+                       goto on_error;
+               }
+
+               for (;;) {
+                       _cleanup_free_ char *k = NULL;
+                       unsigned int v = 0;
+
+                       if (!fgets(buf, sizeof(buf), f)) {
+                               if (ferror(f)) {
+                                       r = -errno;
+                                       goto on_error;
+                               }
+                               break;
+                       }
+
+                       if ((*buf >= '0' && *buf <= '9') ||
+                           (*buf >= 'a' && *buf <= 'f')) {
+                               get_line = false;
+                               break;
+                       }
+
+                       l = strcspn(buf, ":");
+                       if (l >= sizeof(buf) - 2 || !buf[l])
+                               goto on_error;
+
+                       if (!l)
+                               break;
+
+                       k = strndup(buf, l);
+                       if (!k) {
+                               r = -ENOMEM;
+                               goto on_error;
+                       }
+
+                       id = smap_string_to_id(k);
+                       if (id < 0 || id >= SMAPS_ID_MAX)
+                               continue;
+
+                       if (!(mask & (1 << id)))
+                               continue;
+
+                       if (sscanf(buf + l + 1, "%d kB", &v) != 1)
+                               break;
+
+                       map->value[id] = v;
+               }
+
+               r = add_smap_to_smaps(m, map);
+               if (r < 0)
+                       goto on_error;
+       }
+
+       *maps = m;
+
+       return 0;
+
+on_error:
+       smap_free(map);
+       smaps_free(m);
+       return r;
+}
diff --git a/src/common/procfs/smaps.h b/src/common/procfs/smaps.h
new file mode 100644 (file)
index 0000000..5962c81
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * resourced
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+/*
+ * @file smaps.h
+ * @desc /proc/{PID}/smaps info loopup util
+ */
+
+#ifndef _RESOURCED_SMAPS_H_
+#define _RESOURCED_SMAPS_H_
+
+#include <assert.h>
+#include <string.h>
+
+#include "util.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+enum smap_id {
+       SMAPS_ID_INVALID = -1,
+       SMAPS_ID_ANON_HUGE_PAGES = 0,
+       SMAPS_ID_ANONYMOUS,
+       SMAPS_ID_KERNEL_PAGE_SIZE,
+       SMAPS_ID_LOCKED,
+       SMAPS_ID_MMU_PAGE_SIZE,
+       SMAPS_ID_PSWAP,
+       SMAPS_ID_PRIVATE_CLEAN,
+       SMAPS_ID_PRIVATE_DIRTY,
+       SMAPS_ID_PSS,
+       SMAPS_ID_REFERENCED,
+       SMAPS_ID_RSS,
+       SMAPS_ID_SHARED_CLEAN,
+       SMAPS_ID_SHARED_DIRTY,
+       SMAPS_ID_SIZE,
+       SMAPS_ID_SWAP,
+       SMAPS_ID_MAX,
+};
+
+enum smap_mask {
+       SMAPS_MASK_ANON_HUGE_PAGES      = 1 << SMAPS_ID_ANON_HUGE_PAGES,
+       SMAPS_MASK_ANONYMOUS            = 1 << SMAPS_ID_ANONYMOUS,
+       SMAPS_MASK_KERNEL_PAGE_SIZE     = 1 << SMAPS_ID_KERNEL_PAGE_SIZE,
+       SMAPS_MASK_LOCKED               = 1 << SMAPS_ID_LOCKED,
+       SMAPS_MASK_MMU_PAGE_SIZE        = 1 << SMAPS_ID_MMU_PAGE_SIZE,
+       SMAPS_MASK_PSWAP                = 1 << SMAPS_ID_PSWAP,
+       SMAPS_MASK_PRIVATE_CLEAN        = 1 << SMAPS_ID_PRIVATE_CLEAN,
+       SMAPS_MASK_PRIVATE_DIRTY        = 1 << SMAPS_ID_PRIVATE_DIRTY,
+       SMAPS_MASK_PSS                  = 1 << SMAPS_ID_PSS,
+       SMAPS_MASK_REFERENCED           = 1 << SMAPS_ID_REFERENCED,
+       SMAPS_MASK_RSS                  = 1 << SMAPS_ID_RSS,
+       SMAPS_MASK_SHARED_CLEAN         = 1 << SMAPS_ID_SHARED_CLEAN,
+       SMAPS_MASK_SHARED_DIRTY         = 1 << SMAPS_ID_SHARED_DIRTY,
+       SMAPS_MASK_SIZE                 = 1 << SMAPS_ID_SIZE,
+       SMAPS_MASK_SWAP                 = 1 << SMAPS_ID_SWAP,
+       SMAPS_MASK_ALL                  = (1 << SMAPS_ID_MAX) - 1,
+       SMAPS_MASK_TOTMAPS = SMAPS_MASK_RSS | SMAPS_MASK_PSS
+                                               | SMAPS_MASK_SHARED_CLEAN | SMAPS_MASK_SHARED_DIRTY
+                                               | SMAPS_MASK_PRIVATE_CLEAN | SMAPS_MASK_PRIVATE_DIRTY
+                                               | SMAPS_MASK_REFERENCED | SMAPS_MASK_ANONYMOUS
+                                               | SMAPS_MASK_ANON_HUGE_PAGES | SMAPS_MASK_SWAP
+};
+
+struct smap_mapping {
+       const char* name;
+       enum smap_id id;
+};
+typedef struct smap_mapping smap_mapping;
+
+const smap_mapping *smap_mapping_lookup(const char *str, unsigned int len);
+
+static inline enum smap_id smap_string_to_id(const char *str)
+{
+       const struct smap_mapping *m;
+
+       assert(str);
+       m = smap_mapping_lookup(str,
+                               strlen(str));
+       return m ? m->id : SMAPS_ID_INVALID;
+}
+
+struct smap {
+       unsigned int start;
+       unsigned int end;
+       char *mode;
+       char *name;
+       unsigned int value[SMAPS_ID_MAX];
+};
+
+struct smaps {
+       unsigned int sum[SMAPS_ID_MAX];
+       int n_map;
+       struct smap **maps;
+};
+
+void smaps_free(struct smaps *maps);
+int smaps_get(pid_t pid, struct smaps **maps, enum smap_mask mask);
+
+static inline void smaps_freep(struct smaps **maps)
+{
+       if (*maps)
+               smaps_free(*maps);
+}
+
+#define _cleanup_smaps_free_ _cleanup_(smaps_freep)
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif  /* _RESOURCED_SMAPS_H_ */
diff --git a/src/common/safe-kill.c b/src/common/safe-kill.c
deleted file mode 100644 (file)
index 7b95e1e..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * resourced
- *
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-/**
- * @file safe-kill.c
- *
- * @desc check if process is dumping core before sending a signal
- *
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
- *
- */
-
-#include "safe-kill.h"
-#include "trace.h"
-#include "util.h"
-#include "macro.h"
-#include <signal.h>
-#include <stdio.h>
-#include <limits.h>
-#include <stdbool.h>
-
-EXPORT_TEST bool is_process_coredumping(pid_t pid)
-{
-       char buf[LINE_MAX];
-       _cleanup_fclose_ FILE *fp = NULL;
-       int val = 0;
-
-       snprintf(buf, sizeof buf, "/proc/%d/status", pid);
-       fp = fopen(buf, "r");
-       if (!fp)
-               return false;
-
-       while (fgets(buf, sizeof(buf), fp)) {
-               /* Skip the lines, until first match */
-               if (!strstart_with(buf, "CoreDumping:"))
-                       continue;
-
-               if (sscanf(buf, "CoreDumping: %d", &val) == 1)
-                       break;
-
-               return false;
-       }
-
-       return (val == 1);
-}
-
-int safe_kill(pid_t pid, int sig)
-{
-       /* Pass signals other than SIGKILL, as other signals are not delivered to
-        * a process that's dumping a core anyway, and SIGKILL is the only one that
-        * can potentially break that process.
-        * Alternatively, with SIGKILL check if process is coredumping.
-        */
-       if (sig != SIGKILL || !is_process_coredumping(pid)) {
-               _D("safe-kill: delivering signal %d to process %d immediately", sig, pid);
-               return kill(pid, sig);
-       }
-
-       _I("safe-kill: process %d is coredumping - signal SIGKILL not sent", pid);
-       return 0;
-}
diff --git a/src/common/safe-kill.h b/src/common/safe-kill.h
deleted file mode 100644 (file)
index 7f0de4b..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * resourced
- *
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#ifndef SAFE_KILL_H
-#define SAFE_KILL_H
-
-#include <sys/types.h>
-#include <stdbool.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-int safe_kill(pid_t pid, int sig);
-
-#ifdef _UNIT_TEST
-bool is_process_coredumping(pid_t pid);
-#endif
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* SAFE_KILL_H */
diff --git a/src/common/smaps-lookup.c b/src/common/smaps-lookup.c
deleted file mode 100644 (file)
index 9a2b3f7..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/* NOTE: this file was dynamically generated by gperf but is included verbatim (instead of
- * being regenerated) due to various build environment issues */
-
-/* ANSI-C code produced by gperf version 3.0.4 */
-/* Command-line: gperf /home/abuild/rpmbuild/BUILD/resourced-6.0.2/src/common/smaps-lookup.gperf  */
-/* Computed positions: -k'1,$' */
-
-#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
-      && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
-      && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
-      && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
-      && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
-      && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
-      && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
-      && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
-      && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
-      && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
-      && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
-      && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
-      && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
-      && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
-      && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
-      && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
-      && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
-      && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
-      && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
-      && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
-      && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
-      && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
-      && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
-/* The character set is not based on ISO-646.  */
-#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
-#endif
-
-#include "smaps.h"
-#include <string.h>
-
-#define TOTAL_KEYWORDS 15
-#define MIN_WORD_LENGTH 3
-#define MAX_WORD_LENGTH 14
-#define MIN_HASH_VALUE 3
-#define MAX_HASH_VALUE 24
-/* maximum key range = 22, duplicates = 0 */
-
-#ifdef __GNUC__
-__inline
-#else
-#ifdef __cplusplus
-inline
-#endif
-#endif
-static unsigned int
-smap_mapping_hash (register const char *str, register unsigned int len)
-{
-  static const unsigned char asso_values[] =
-    {
-      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-      25, 25, 25, 25, 25, 10, 25, 25, 25, 25,
-      25, 25, 25, 25, 25,  5,  0,  0, 25, 25,
-       0, 25,  5,  0, 25, 25, 25, 25, 25, 25,
-      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-       0,  5, 25, 25, 25, 25, 25, 25, 25, 25,
-       5, 25,  0, 25, 25,  0, 25, 25, 25, 25,
-      25,  0, 25, 25, 25, 25, 25, 25, 25, 25,
-      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-      25, 25, 25, 25, 25, 25
-    };
-  return len + asso_values[(unsigned char)str[len - 1]] + asso_values[(unsigned char)str[0]];
-}
-
-#ifdef __GNUC__
-__inline
-#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
-__attribute__ ((__gnu_inline__))
-#endif
-#endif
-const smap_mapping *
-smap_mapping_lookup (register const char *str, register unsigned int len)
-{
-  static const smap_mapping wordlist[] =
-    {
-      {""}, {""}, {""},
-      {"Pss",            SMAPS_ID_PSS},
-      {"Swap",           SMAPS_ID_SWAP},
-      {"PSwap",          SMAPS_ID_PSWAP},
-      {"Locked",         SMAPS_ID_LOCKED},
-      {""},
-      {"Rss",            SMAPS_ID_RSS},
-      {"Size",           SMAPS_ID_SIZE},
-      {""}, {""},
-      {"Shared_Dirty",   SMAPS_ID_SHARED_DIRTY},
-      {"Private_Dirty",  SMAPS_ID_PRIVATE_DIRTY}, // patrollin' tryna catch me private dirty
-      {""},
-      {"Referenced",     SMAPS_ID_REFERENCED},
-      {"MMUPageSize",    SMAPS_ID_MMU_PAGE_SIZE},
-      {"Shared_Clean",   SMAPS_ID_SHARED_CLEAN},
-      {"Private_Clean",  SMAPS_ID_PRIVATE_CLEAN},
-      {"Anonymous",      SMAPS_ID_ANONYMOUS},
-      {""}, {""}, {""},
-      {"AnonHugePages",  SMAPS_ID_ANON_HUGE_PAGES},
-      {"KernelPageSize", SMAPS_ID_KERNEL_PAGE_SIZE}
-    };
-
-  if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
-    {
-      register int key = smap_mapping_hash (str, len);
-
-      if (key <= MAX_HASH_VALUE && key >= 0)
-        {
-          register const char *s = wordlist[key].name;
-
-          if (*str == *s && !strcmp (str + 1, s + 1))
-            return &wordlist[key];
-        }
-    }
-  return 0;
-}
diff --git a/src/common/smaps-lookup.gperf b/src/common/smaps-lookup.gperf
deleted file mode 100644 (file)
index 27112cb..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-%{
-#include "smaps.h"
-%}
-smap_mapping;
-%language=ANSI-C
-%define slot-name name
-%define hash-function-name smap_mapping_hash
-%define lookup-function-name smap_mapping_lookup
-%readonly-tables
-%omit-struct-type
-%struct-type
-%includes
-%%
-AnonHugePages,  SMAPS_ID_ANON_HUGE_PAGES
-Anonymous,      SMAPS_ID_ANONYMOUS
-KernelPageSize, SMAPS_ID_KERNEL_PAGE_SIZE
-Locked,         SMAPS_ID_LOCKED
-MMUPageSize,    SMAPS_ID_MMU_PAGE_SIZE
-PSwap,          SMAPS_ID_PSWAP
-Private_Clean,  SMAPS_ID_PRIVATE_CLEAN
-Private_Dirty,  SMAPS_ID_PRIVATE_DIRTY
-Pss,            SMAPS_ID_PSS
-Referenced,     SMAPS_ID_REFERENCED
-Rss,            SMAPS_ID_RSS
-Shared_Clean,   SMAPS_ID_SHARED_CLEAN
-Shared_Dirty,   SMAPS_ID_SHARED_DIRTY
-Size,           SMAPS_ID_SIZE
-Swap,           SMAPS_ID_SWAP
diff --git a/src/common/smaps.c b/src/common/smaps.c
deleted file mode 100644 (file)
index 6d940cf..0000000
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * resourced
- *
- * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-/*
- * @file smaps.c
- * @desc get smaps info of process
- */
-
-#include <stdlib.h>
-#include <assert.h>
-#include <errno.h>
-#include <limits.h>
-
-#include "util.h"
-#include "smaps.h"
-#include "trace.h"
-
-static int have_totmaps = 0;
-
-static bool totmaps_available(void)
-{
-       if (have_totmaps == 2)
-               have_totmaps = (access("/proc/1/totmaps", R_OK) == 0);
-
-       return have_totmaps;
-}
-
-static void smap_free(struct smap *map)
-{
-       if (!map)
-               return;
-
-       if (map->mode)
-               free(map->mode);
-
-       if (map->name)
-               free(map->name);
-
-       free(map);
-}
-
-void smaps_free(struct smaps *maps)
-{
-       int i;
-
-       if (!maps)
-               return;
-
-       for (i = 0; i < maps->n_map; i++)
-               smap_free(maps->maps[i]);
-
-       free(maps->maps);
-       free(maps);
-}
-
-static int add_smap_to_smaps(struct smaps *maps, struct smap *map)
-{
-       int i;
-
-       assert(maps);
-       assert(map);
-
-       maps->n_map++;
-
-       maps->maps = (struct smap **)realloc(
-               maps->maps,
-               sizeof(struct smap *) * maps->n_map);
-       if (!maps->maps)
-               return -ENOMEM;
-
-       maps->maps[maps->n_map - 1] = map;
-
-       for (i = 0; i < SMAPS_ID_MAX; i++)
-               maps->sum[i] += map->value[i];
-
-       return 0;
-}
-
-int smaps_get(pid_t pid, struct smaps **maps, enum smap_mask mask)
-{
-       _cleanup_free_ char *path = NULL;
-       _cleanup_fclose_ FILE *f = NULL;
-       struct smaps *m = NULL;
-       char buf[LINE_MAX];
-       bool get_line = true, totmaps;
-       int r;
-       struct smap *map;
-
-       assert(maps);
-
-       totmaps = totmaps_available();
-       if (totmaps && (mask & ~SMAPS_MASK_TOTMAPS) == 0) {
-               r = asprintf(&path, "/proc/%d/totmaps", pid);
-       } else {
-               totmaps = false;
-               r = asprintf(&path, "/proc/%d/smaps", pid);
-       }
-
-       if (r < 0)
-               return -ENOMEM;
-
-       f = fopen(path, "re");
-       if (!f)
-               return -errno;
-
-       m = new0(struct smaps, 1);
-       if (!m)
-               return -ENOMEM;
-
-       for (;;) {
-               map = NULL;
-               int n;
-               size_t l;
-               enum smap_id id;
-
-               if (get_line && !fgets(buf, sizeof(buf), f)) {
-                       if (ferror(f)) {
-                               r = -errno;
-                               goto on_error;
-                       }
-                       break;
-               }
-               get_line = true;
-
-               /*
-                * If totmaps are available and the caller doesn't
-                * need fields exclusive to smaps, we use them here.
-                * Reading totmaps is on average 20 times faster than
-                * reading smaps.
-                */
-               if (totmaps) {
-                       unsigned int v = 0;
-
-                       l = strcspn(buf, ":");
-                       if (l >= sizeof(buf) - 2 || !buf[l])
-                               goto totmaps_error;
-                       buf[l] = 0;
-
-                       id = smap_string_to_id(buf);
-                       if (id < 0 || id >= SMAPS_ID_MAX)
-                               continue;
-
-                       if (sscanf(buf + l + 1, "%d kB", &v) != 1)
-                               goto totmaps_error;
-
-                       m->sum[id] = v;
-                       continue;
-
-totmaps_error:
-                       _E("Unknown totmaps format, expected: '%%s : %%d kB'");
-                       r = -EIO;
-                       have_totmaps = 0; // don't ever read totmaps again
-                       goto on_error;
-               }
-
-               map = new0(struct smap, 1);
-               if (!map) {
-                       r = -errno;
-                       goto on_error;
-               }
-
-               n = sscanf(buf, "%x-%x %ms %*s %*s %*s %ms",
-                          &map->start, &map->end, &map->mode, &map->name);
-
-               if (n == 3 && !map->name)
-                       map->name = strndup("[anon]", strlen("[anon]"));
-               else if (n != 4) {
-                       r = -EINVAL;
-                       goto on_error;
-               }
-
-               for (;;) {
-                       _cleanup_free_ char *k = NULL;
-                       unsigned int v = 0;
-
-                       if (!fgets(buf, sizeof(buf), f)) {
-                               if (ferror(f)) {
-                                       r = -errno;
-                                       goto on_error;
-                               }
-                               break;
-                       }
-
-                       if ((*buf >= '0' && *buf <= '9') ||
-                           (*buf >= 'a' && *buf <= 'f')) {
-                               get_line = false;
-                               break;
-                       }
-
-                       l = strcspn(buf, ":");
-                       if (l >= sizeof(buf) - 2 || !buf[l])
-                               goto on_error;
-
-                       if (!l)
-                               break;
-
-                       k = strndup(buf, l);
-                       if (!k) {
-                               r = -ENOMEM;
-                               goto on_error;
-                       }
-
-                       id = smap_string_to_id(k);
-                       if (id < 0 || id >= SMAPS_ID_MAX)
-                               continue;
-
-                       if (!(mask & (1 << id)))
-                               continue;
-
-                       if (sscanf(buf + l + 1, "%d kB", &v) != 1)
-                               break;
-
-                       map->value[id] = v;
-               }
-
-               r = add_smap_to_smaps(m, map);
-               if (r < 0)
-                       goto on_error;
-       }
-
-       *maps = m;
-
-       return 0;
-
-on_error:
-       smap_free(map);
-       smaps_free(m);
-       return r;
-}
diff --git a/src/common/smaps.h b/src/common/smaps.h
deleted file mode 100644 (file)
index 5962c81..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * resourced
- *
- * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
-*/
-
-/*
- * @file smaps.h
- * @desc /proc/{PID}/smaps info loopup util
- */
-
-#ifndef _RESOURCED_SMAPS_H_
-#define _RESOURCED_SMAPS_H_
-
-#include <assert.h>
-#include <string.h>
-
-#include "util.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-enum smap_id {
-       SMAPS_ID_INVALID = -1,
-       SMAPS_ID_ANON_HUGE_PAGES = 0,
-       SMAPS_ID_ANONYMOUS,
-       SMAPS_ID_KERNEL_PAGE_SIZE,
-       SMAPS_ID_LOCKED,
-       SMAPS_ID_MMU_PAGE_SIZE,
-       SMAPS_ID_PSWAP,
-       SMAPS_ID_PRIVATE_CLEAN,
-       SMAPS_ID_PRIVATE_DIRTY,
-       SMAPS_ID_PSS,
-       SMAPS_ID_REFERENCED,
-       SMAPS_ID_RSS,
-       SMAPS_ID_SHARED_CLEAN,
-       SMAPS_ID_SHARED_DIRTY,
-       SMAPS_ID_SIZE,
-       SMAPS_ID_SWAP,
-       SMAPS_ID_MAX,
-};
-
-enum smap_mask {
-       SMAPS_MASK_ANON_HUGE_PAGES      = 1 << SMAPS_ID_ANON_HUGE_PAGES,
-       SMAPS_MASK_ANONYMOUS            = 1 << SMAPS_ID_ANONYMOUS,
-       SMAPS_MASK_KERNEL_PAGE_SIZE     = 1 << SMAPS_ID_KERNEL_PAGE_SIZE,
-       SMAPS_MASK_LOCKED               = 1 << SMAPS_ID_LOCKED,
-       SMAPS_MASK_MMU_PAGE_SIZE        = 1 << SMAPS_ID_MMU_PAGE_SIZE,
-       SMAPS_MASK_PSWAP                = 1 << SMAPS_ID_PSWAP,
-       SMAPS_MASK_PRIVATE_CLEAN        = 1 << SMAPS_ID_PRIVATE_CLEAN,
-       SMAPS_MASK_PRIVATE_DIRTY        = 1 << SMAPS_ID_PRIVATE_DIRTY,
-       SMAPS_MASK_PSS                  = 1 << SMAPS_ID_PSS,
-       SMAPS_MASK_REFERENCED           = 1 << SMAPS_ID_REFERENCED,
-       SMAPS_MASK_RSS                  = 1 << SMAPS_ID_RSS,
-       SMAPS_MASK_SHARED_CLEAN         = 1 << SMAPS_ID_SHARED_CLEAN,
-       SMAPS_MASK_SHARED_DIRTY         = 1 << SMAPS_ID_SHARED_DIRTY,
-       SMAPS_MASK_SIZE                 = 1 << SMAPS_ID_SIZE,
-       SMAPS_MASK_SWAP                 = 1 << SMAPS_ID_SWAP,
-       SMAPS_MASK_ALL                  = (1 << SMAPS_ID_MAX) - 1,
-       SMAPS_MASK_TOTMAPS = SMAPS_MASK_RSS | SMAPS_MASK_PSS
-                                               | SMAPS_MASK_SHARED_CLEAN | SMAPS_MASK_SHARED_DIRTY
-                                               | SMAPS_MASK_PRIVATE_CLEAN | SMAPS_MASK_PRIVATE_DIRTY
-                                               | SMAPS_MASK_REFERENCED | SMAPS_MASK_ANONYMOUS
-                                               | SMAPS_MASK_ANON_HUGE_PAGES | SMAPS_MASK_SWAP
-};
-
-struct smap_mapping {
-       const char* name;
-       enum smap_id id;
-};
-typedef struct smap_mapping smap_mapping;
-
-const smap_mapping *smap_mapping_lookup(const char *str, unsigned int len);
-
-static inline enum smap_id smap_string_to_id(const char *str)
-{
-       const struct smap_mapping *m;
-
-       assert(str);
-       m = smap_mapping_lookup(str,
-                               strlen(str));
-       return m ? m->id : SMAPS_ID_INVALID;
-}
-
-struct smap {
-       unsigned int start;
-       unsigned int end;
-       char *mode;
-       char *name;
-       unsigned int value[SMAPS_ID_MAX];
-};
-
-struct smaps {
-       unsigned int sum[SMAPS_ID_MAX];
-       int n_map;
-       struct smap **maps;
-};
-
-void smaps_free(struct smaps *maps);
-int smaps_get(pid_t pid, struct smaps **maps, enum smap_mask mask);
-
-static inline void smaps_freep(struct smaps **maps)
-{
-       if (*maps)
-               smaps_free(*maps);
-}
-
-#define _cleanup_smaps_free_ _cleanup_(smaps_freep)
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif  /* _RESOURCED_SMAPS_H_ */
diff --git a/src/common/swap-common.c b/src/common/swap-common.c
deleted file mode 100644 (file)
index 709e8e3..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * resourced
- *
- * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "macro.h"
-#include "swap-common.h"
-#include "trace.h"
-
-static struct swap_conf *swap_conf = NULL;
-
-static enum swap_state swap_state = SWAP_OFF;
-
-struct swap_conf *get_swap_conf(void)
-{
-       if (!swap_conf) {
-               swap_conf = (struct swap_conf *)calloc(1, sizeof (struct swap_conf));
-               if (!swap_conf) {
-                       _E("Failed to alloc memory for cpu configuration");
-                       return NULL;
-               }
-               else {
-                       swap_conf->enable = false;
-                       swap_conf->boot_reclaim_enable = false;
-                       swap_conf->swap_type = SWAP_TYPE_NONE;
-                       swap_conf->swappiness[MEMCG_THROTTLING] = MEMORY_INIT_SWAPPINESS;
-               }
-       }
-
-       return swap_conf;
-}
-
-
-void free_swap_conf(void)
-{
-       if (swap_conf)
-               free(swap_conf);
-}
-
-enum swap_state swap_get_state(void)
-{
-       return swap_state;
-}
-
-/* Following function is supposed to be used by swap module only.
- *
- * Implemented in common part for the purpose of integration with
- * dynamically loaded "swap" plugin.
- *
- * From available options it seems cleaner to export getter/setter
- * like the one below (with a bit of swap-internal logic).
- * Other option would be keeping set function in swap module, but
- * that would require us to reference and alter then-global swap_state
- * variable (in common part) from swap shared object.
- */
-void swap_set_state(enum swap_state state)
-{
-       if ((state != SWAP_ON) && (state != SWAP_OFF))
-               return;
-
-       swap_state = state;
-}
diff --git a/src/common/swap-common.h b/src/common/swap-common.h
deleted file mode 100644 (file)
index 17116ed..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * resourced
- *
- * Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-/**
- * @file swap-common.h
- * @desc swap common process
- **/
-
-#ifndef __SWAP_COMMON_H__
-#define __SWAP_COMMON_H__
-
-#include <stdio.h>
-#include "resourced.h"
-#include "memory-cgroup.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-#define SWAP_ZRAM_SYSFILE      "/sys/block/zram0/"
-#define SWAP_FILE_NAME         "/opt/usr/.swapfile"
-#define SWAP_CONF_FILE         RD_CONFIG_FILE(optimizer)
-
-#define MEMORY_INIT_SWAPPINESS   200
-
-enum swap_state {
-       SWAP_ARG_START = -1,
-       SWAP_OFF,
-       SWAP_ON,
-       SWAP_ARG_END,
-};
-
-enum swap_type {
-       SWAP_TYPE_NONE = 0x0,
-       SWAP_TYPE_ZRAM = 0x1,
-       SWAP_TYPE_FILE = 0x2,
-       SWAP_TYPE_ZSWAP = 0x4,
-       SWAP_TYPE_MAX,
-};
-
-struct swap_status_msg {
-       char path[MAX_PATH_LENGTH];
-};
-
-enum swap_compact_reason {
-       SWAP_COMPACT_MEM_LEVEL_CRITICAL,
-       SWAP_COMPACT_MEM_LEVEL_OOM,
-       SWAP_COMPACT_SWAP_FULL,
-       SWAP_COMPACT_RESASON_MAX,
-};
-
-/*
- * Each swap modoule can have priority.
- * The swap list of kernel has low-to-high order
- * while swap ordering is high-to-low.
- * So, if a swap module has lower priority, it should be intialized eariler.
- * On the top of that, SWAP_PRI_DISABLE will be used
- * not to support multiple swap devices.
- */
-enum swap_priority {
-       SWAP_PRI_DISABLE = -255,
-       SWAP_PRI_LOW = -1,
-       SWAP_PRI_DEFAULT = 0,
-       SWAP_PRI_HIGH = 1,
-};
-
-struct swap_module_ops {
-       char *name;
-       enum swap_type type;
-       char *path;
-       int priority;
-       unsigned int k_size;
-       int (*init)(void *data);
-       int (*exit) (void *data);
-       int (*activate)(void *data);
-       int (*reclaim)(void *data);
-       int (*conf)(void *data);
-};
-
-struct zram_conf {
-       char algorithm[MAX_TYPE_LENGTH - 1];
-       float ratio;
-};
-
-struct zswap_conf {
-       float pool_ratio;
-       char pool_type[MAX_TYPE_LENGTH -1];
-};
-
-struct swap_conf {
-       bool enable;
-       bool boot_reclaim_enable;
-       enum swap_type swap_type;
-       int swappiness[MEMCG_END];
-       struct zram_conf zram;
-       struct zswap_conf zswap;
-};
-
-struct swap_conf *get_swap_conf(void);
-void free_swap_conf(void);
-
-enum swap_state swap_get_state(void);
-void swap_set_state(enum swap_state state);
-
-int swap_set_file(char *file, struct swap_module_ops *swap, char *crypt_type);
-int do_mkswap(const char *device);
-int do_dd(char *input, char *output, unsigned int size, unsigned int count);
-
-bool swap_is_on(const char *name);
-
-void swap_add(const struct swap_module_ops *swap);
-void swap_remove(const struct swap_module_ops *swap);
-
-#define SWAP_MODULE_REGISTER(swap)                                     \
-static void __attribute__ ((constructor)) swap_module_register(void)           \
-{                                                      \
-       swap_add(swap);                                 \
-}                                                      \
-static void __attribute__ ((destructor)) swap_module_unregister(void)  \
-{                                                      \
-       swap_remove(swap);                              \
-}
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __SWAP_COMMON_H__ */
diff --git a/src/process/priority/proc-priority.c b/src/process/priority/proc-priority.c
deleted file mode 100644 (file)
index ea62ad0..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * resourced
- *
- * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
-*/
-
-/*
- * @file proc-priority.c
- * @desc set specific priority to predefined application
-*/
-
-#include <glib.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "lowmem-handler.h"
-#include "cpu-cgroup.h"
-#include "config-parser.h"
-#include "const.h"
-#include "module.h"
-#include "notifier.h"
-#include "proc-common.h"
-#include "proc-main.h"
-#include "procfs.h"
-#include "resourced.h"
-#include "trace.h"
-#include "cpu-common.h"
-
-static GHashTable *fixed_app_list;
-static GHashTable *fixed_service_list;
-static GHashTable *fixed_process_list;
-
-void fixed_app_and_service_list_init(void)
-{
-       fixed_app_list = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, free);
-       fixed_service_list = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, free);
-       fixed_process_list = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, free);
-       g_assert(fixed_app_list && fixed_service_list && fixed_process_list);
-}
-
-void fixed_app_and_service_list_exit(void)
-{
-       if (fixed_app_list)
-               g_hash_table_destroy(fixed_app_list);
-       if (fixed_service_list)
-               g_hash_table_destroy(fixed_service_list);
-       if (fixed_process_list)
-               g_hash_table_destroy(fixed_process_list);
-}
-
-void fixed_app_list_insert(struct proc_conf_info *pci)
-{
-       g_hash_table_insert(fixed_app_list, (gpointer)pci->name, (gpointer)pci);
-}
-
-void fixed_service_list_insert(struct proc_conf_info *pci)
-{
-       g_hash_table_insert(fixed_service_list, (gpointer)pci->name, (gpointer)pci);
-}
-
-void fixed_process_list_insert(struct proc_conf_info *pci)
-{
-       g_hash_table_insert(fixed_process_list, (gpointer)pci->name, (gpointer)pci);
-}
-
-GHashTable* fixed_app_list_get(void)
-{
-       return fixed_app_list;
-}
-
-GHashTable* fixed_service_list_get(void)
-{
-       return fixed_service_list;
-}
-
-GHashTable* fixed_process_list_get(void)
-{
-       return fixed_process_list;
-}
-
-struct proc_conf_info* fixed_app_and_service_exist_check(const char *name, enum proc_type proc_type)
-{
-       if (proc_type != APP_TYPE && proc_type != SERVICE_TYPE && proc_type != PROCESS_TYPE) {
-               _E("Unknown type (we support only app, service, and process types)");
-               return NULL;
-       }
-
-       if (proc_type == APP_TYPE) {
-               if (g_hash_table_size(fixed_app_list) == 0)
-                       return NULL;
-
-               return (struct proc_conf_info *)g_hash_table_lookup(fixed_app_list, name);
-       }
-       else if (proc_type == SERVICE_TYPE) {
-               if (g_hash_table_size(fixed_service_list) == 0)
-                       return NULL;
-
-               return (struct proc_conf_info *)g_hash_table_lookup(fixed_service_list, name);
-       }
-       else {
-               if (g_hash_table_size(fixed_process_list) == 0)
-                       return NULL;
-
-               return (struct proc_conf_info *)g_hash_table_lookup(fixed_process_list, name);
-       }
-}
-
-enum proc_action fixed_app_and_service_watchdog_action(const char *name, enum proc_type proc_type)
-{
-       struct proc_conf_info *pci;
-
-       pci = fixed_app_and_service_exist_check(name, proc_type);
-       if (pci) {
-               return pci->watchdog_action;
-       }
-       else {
-               return PROC_ACTION_KILL;
-       }
-}
diff --git a/src/process/proc-priority.c b/src/process/proc-priority.c
new file mode 100644 (file)
index 0000000..ea62ad0
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * resourced
+ *
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+/*
+ * @file proc-priority.c
+ * @desc set specific priority to predefined application
+*/
+
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "lowmem-handler.h"
+#include "cpu-cgroup.h"
+#include "config-parser.h"
+#include "const.h"
+#include "module.h"
+#include "notifier.h"
+#include "proc-common.h"
+#include "proc-main.h"
+#include "procfs.h"
+#include "resourced.h"
+#include "trace.h"
+#include "cpu-common.h"
+
+static GHashTable *fixed_app_list;
+static GHashTable *fixed_service_list;
+static GHashTable *fixed_process_list;
+
+void fixed_app_and_service_list_init(void)
+{
+       fixed_app_list = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, free);
+       fixed_service_list = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, free);
+       fixed_process_list = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, free);
+       g_assert(fixed_app_list && fixed_service_list && fixed_process_list);
+}
+
+void fixed_app_and_service_list_exit(void)
+{
+       if (fixed_app_list)
+               g_hash_table_destroy(fixed_app_list);
+       if (fixed_service_list)
+               g_hash_table_destroy(fixed_service_list);
+       if (fixed_process_list)
+               g_hash_table_destroy(fixed_process_list);
+}
+
+void fixed_app_list_insert(struct proc_conf_info *pci)
+{
+       g_hash_table_insert(fixed_app_list, (gpointer)pci->name, (gpointer)pci);
+}
+
+void fixed_service_list_insert(struct proc_conf_info *pci)
+{
+       g_hash_table_insert(fixed_service_list, (gpointer)pci->name, (gpointer)pci);
+}
+
+void fixed_process_list_insert(struct proc_conf_info *pci)
+{
+       g_hash_table_insert(fixed_process_list, (gpointer)pci->name, (gpointer)pci);
+}
+
+GHashTable* fixed_app_list_get(void)
+{
+       return fixed_app_list;
+}
+
+GHashTable* fixed_service_list_get(void)
+{
+       return fixed_service_list;
+}
+
+GHashTable* fixed_process_list_get(void)
+{
+       return fixed_process_list;
+}
+
+struct proc_conf_info* fixed_app_and_service_exist_check(const char *name, enum proc_type proc_type)
+{
+       if (proc_type != APP_TYPE && proc_type != SERVICE_TYPE && proc_type != PROCESS_TYPE) {
+               _E("Unknown type (we support only app, service, and process types)");
+               return NULL;
+       }
+
+       if (proc_type == APP_TYPE) {
+               if (g_hash_table_size(fixed_app_list) == 0)
+                       return NULL;
+
+               return (struct proc_conf_info *)g_hash_table_lookup(fixed_app_list, name);
+       }
+       else if (proc_type == SERVICE_TYPE) {
+               if (g_hash_table_size(fixed_service_list) == 0)
+                       return NULL;
+
+               return (struct proc_conf_info *)g_hash_table_lookup(fixed_service_list, name);
+       }
+       else {
+               if (g_hash_table_size(fixed_process_list) == 0)
+                       return NULL;
+
+               return (struct proc_conf_info *)g_hash_table_lookup(fixed_process_list, name);
+       }
+}
+
+enum proc_action fixed_app_and_service_watchdog_action(const char *name, enum proc_type proc_type)
+{
+       struct proc_conf_info *pci;
+
+       pci = fixed_app_and_service_exist_check(name, proc_type);
+       if (pci) {
+               return pci->watchdog_action;
+       }
+       else {
+               return PROC_ACTION_KILL;
+       }
+}
diff --git a/src/resource-limiter/cpu-throttling.c b/src/resource-limiter/cpu-throttling.c
new file mode 100644 (file)
index 0000000..623713b
--- /dev/null
@@ -0,0 +1,295 @@
+/*
+ * resourced
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file cpu.c
+ *
+ * @desc cpu module
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ */
+#include <dirent.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/syscall.h>
+#include "notifier.h"
+#include "procfs.h"
+#include "proc-common.h"
+#include "macro.h"
+#include "module.h"
+#include "module-data.h"
+#include "resourced.h"
+#include "trace.h"
+#include "vconf.h"
+#include "util.h"
+#include "cgroup.h"
+#include "config-parser.h"
+#include "const.h"
+#include "file-helper.h"
+#include "cpu-cgroup.h"
+
+#define CPU_CONF_FILE       RD_CONFIG_FILE(limiter)
+#define CPU_CONF_SECTION    "CPU"
+#define CPU_CONF_PREDEFINE  "PREDEFINE"
+#define CPU_CONF_BOOTING    "BOOTING_PREDEFINE"
+#define CPU_CONF_WRT        "WRT_PREDEFINE"
+#define CPU_CONF_LAZY       "LAZY_PREDEFINE"
+#define MAX_PREDEFINED_TASKS  10
+#define CPU_TIMER_INTERVAL       30
+#define CPU_BACKGROUND_PRI    1
+#define CPU_CONTROL_PRI       10
+
+bool throttling_success = false;
+bool skip_bandwidth = false;
+bool skip_share = false;
+struct sched_attr throttling_attr;
+struct sched_attr normal_attr;
+
+static int move_process_to_throttling_group(pid_t pid, struct proc_app_info *pai)
+{
+       GSList *iter = NULL;
+       pid_t child_pid;
+
+       if (!throttling_success)
+               return RESOURCED_ERROR_NONE;
+
+       if (pai) {
+               if (pai->app_cpu_nice_update_exclude)
+                       goto cpu_cgroup_move;
+
+               sched_setattr_of_all_tasks(pai->main_pid, &throttling_attr, 0);
+               if (pai->childs) {
+                       gslist_for_each_item(iter, pai->childs) {
+                               child_pid = GPOINTER_TO_PID(iter->data);
+                               sched_setattr_of_all_tasks(child_pid, &throttling_attr, 0);
+                       }
+               }
+       }
+       else {
+               sched_setattr_of_all_tasks(pid, &throttling_attr, 0);
+       }
+
+cpu_cgroup_move:
+       if (!skip_share || !skip_bandwidth)
+               return cpu_move_cgroup_foreach(pid, pai, CPUCG_THROTTLING_PATH);
+       else
+               return RESOURCED_ERROR_NONE;
+}
+
+static int move_out_process_from_throttling_group(pid_t pid, struct proc_app_info *pai)
+{
+       GSList *iter = NULL;
+       pid_t child_pid;
+
+       if (!throttling_success)
+               return RESOURCED_ERROR_NONE;
+
+       if (pai) {
+               if (pai->app_cpu_nice_update_exclude)
+                       goto cpu_cgroup_move;
+
+               sched_setattr_of_all_tasks(pai->main_pid, &normal_attr, 0);
+               if (pai->childs) {
+                       gslist_for_each_item(iter, pai->childs) {
+                               child_pid = GPOINTER_TO_PID(iter->data);
+                               sched_setattr_of_all_tasks(child_pid, &normal_attr, 0);
+                       }
+               }
+       }
+       else {
+               sched_setattr_of_all_tasks(pid, &normal_attr, 0);
+       }
+
+cpu_cgroup_move:
+       if (!skip_share || !skip_bandwidth)
+               return cpu_move_cgroup_foreach(pid, pai, CPUCG_PATH);
+       else
+               return RESOURCED_ERROR_NONE;
+}
+
+static int cpu_foreground_state(void *data)
+{
+       int ret;
+       struct proc_status *ps = (struct proc_status *)data;
+
+       assert(ps);
+       _D("app foreground: pid = %d", ps->pid);
+       ret = move_out_process_from_throttling_group(ps->pid, ps->pai);
+       if (ret < 0)
+               _E("Failed to throttle cpu resource of %s%s process (%d)",
+               ps->pai ? "App " : "System service",
+               ps->pai ? ps->pai->appid : "", ps->pid);
+       return RESOURCED_ERROR_NONE;
+}
+
+static int cpu_background_state(void *data)
+{
+       int ret;
+       struct proc_status *ps = (struct proc_status *)data;
+       assert(ps);
+
+       _D("app background: pid = %d", ps->pid);
+       ret = move_process_to_throttling_group(ps->pid, ps->pai);
+       if (ret < 0)
+               _E("Failed to throttle cpu resource of %s%s process (%d)",
+               ps->pai ? "App " : "System service",
+               ps->pai ? ps->pai->appid : "", ps->pid);
+       return RESOURCED_ERROR_NONE;
+}
+
+static void load_cpu_throttling_config(void)
+{
+       int ret;
+       int cpu_nice;
+       long long cpu_runtime_us;
+       unsigned long long cpu_period_us;
+       unsigned long long cpu_share;
+       enum cpu_sched_type cpu_sched_type;
+
+       struct cpu_throttling_conf *cpu_throttling_conf = get_cpu_throttling_conf();
+       if (cpu_throttling_conf == NULL) {
+               _E("[CPU-THROTTLING] cpu sched configuration structure should not be NULL");
+               return;
+       }
+
+       if (!cpu_throttling_conf->enable) {
+               _I("[CPU-THROTTLING] cpu throttling is disabled");
+               goto free_cpu_throttling_conf;
+       }
+
+       cpu_nice = cpu_throttling_conf->cpu_sched_info.cpu_nice;
+       cpu_sched_type = cpu_throttling_conf->cpu_sched_info.cpu_sched_type;
+       cpu_share = cpu_throttling_conf->cpu_cgroup_info.cpu_share;
+       cpu_period_us = cpu_throttling_conf->cpu_cgroup_info.cfs_period_us;
+       cpu_runtime_us = cpu_throttling_conf->cpu_cgroup_info.cfs_runtime_us;
+
+       if (cpu_share == 0) {
+               _E("[CPU-THROTTLING] cpu share cannot be 0");
+               cpu_share = CPU_THROTTLING_SHARE;
+               skip_share = true;
+       }
+
+       if (cpu_period_us == 0 || cpu_runtime_us == 0 ||
+                       cpu_period_us < cpu_runtime_us) {
+               _E("[CPU-THROTTLING] cpu period (%llu) and runtime (%lld) is out of scope",
+                               cpu_period_us, cpu_runtime_us);
+               skip_bandwidth = true;
+       }
+
+       if (cpu_sched_type < CPU_SCHED_IDLE || cpu_sched_type > CPU_SCHED_OTHER) {
+               _E("[CPU-THROTTLING] cpu scheduler type is unknown or realtime");
+               cpu_sched_type = CPU_SCHED_IDLE;
+       }
+
+       if (cpu_sched_type != CPU_SCHED_IDLE &&
+                       (cpu_nice < CPU_MIN_NICE || cpu_nice > CPU_MAX_NICE)) {
+               _W("[CPU-THROTTLING] cpu nice is out of scope");
+               cpu_nice = CPU_MAX_NICE;        /* the worst nice value */
+       }
+
+       /* Make a cpu throttling directory at the cpu cgroup */
+       if (!skip_share || !skip_bandwidth) {
+               ret = cpucg_make_full_subdir(CPUCG_PATH);
+               if (ret < 0) {
+                       _E("Failed to initialize cpu cgroup for throttling\n");
+                       goto free_cpu_throttling_conf;
+               }
+
+               /* Initialize cpu throttling cgroup */
+               cgroup_write_node_ulonglong(CPUCG_THROTTLING_PATH, CPUCG_SHARE, cpu_share);
+               cgroup_write_node_longlong(CPUCG_THROTTLING_PATH, CPUCG_CONTROL_BANDWIDTH,
+                               cpu_runtime_us);
+               cgroup_write_node_ulonglong(CPUCG_THROTTLING_PATH, CPUCG_CONTROL_FULL_BANDWIDTH,
+                               cpu_period_us);
+       }
+
+       /* Initialize type and nice of cpu throttling scheduler */
+       memset(&normal_attr, 0, sizeof(struct sched_attr));
+       normal_attr.size = sizeof(struct sched_attr);
+       normal_attr.sched_nice = CPU_DEFAULT_NICE;
+       normal_attr.sched_policy = SCHED_OTHER;
+
+       memset(&throttling_attr, 0, sizeof(struct sched_attr));
+       throttling_attr.size = sizeof(struct sched_attr);
+       throttling_attr.sched_nice = cpu_nice;
+       switch (cpu_sched_type) {
+               case CPU_SCHED_IDLE:
+                       throttling_attr.sched_policy = SCHED_IDLE;
+                       break;
+               case CPU_SCHED_BATCH:
+                       throttling_attr.sched_policy = SCHED_BATCH;
+                       break;
+               case CPU_SCHED_OTHER:
+                       throttling_attr.sched_policy = SCHED_OTHER;
+                       break;
+               default:
+                       if (!skip_share || !skip_bandwidth)
+                               rmdir(CPUCG_THROTTLING_PATH);
+                       goto free_cpu_throttling_conf;
+       }
+
+       throttling_success = true;
+
+       _I("[CPU-THROTTLING] throttling policy = %s",
+               throttling_attr.sched_policy == SCHED_IDLE ? "SCHED_IDLE" :
+                       throttling_attr.sched_policy == SCHED_BATCH ? "SCHED_BATCH" :
+                       throttling_attr.sched_policy == SCHED_OTHER ? "SCHED_OTHER" : "wrong scheduler type");
+       _I("[CPU-THROTTLING] throttling nice = %d", throttling_attr.sched_nice);
+
+free_cpu_throttling_conf:
+       free_cpu_throttling_conf();
+}
+
+static int resourced_cpu_init(void *data)
+{
+       _D("resourced cpu init start");
+       load_cpu_throttling_config();
+
+       register_notifier(RESOURCED_NOTIFIER_APP_RESUME, cpu_foreground_state);
+       register_notifier(RESOURCED_NOTIFIER_APP_FOREGRD, cpu_foreground_state);
+       register_notifier(RESOURCED_NOTIFIER_WIDGET_FOREGRD, cpu_foreground_state);
+       register_notifier(RESOURCED_NOTIFIER_APP_BACKGRD, cpu_background_state);
+       register_notifier(RESOURCED_NOTIFIER_THROTTLING_RESOURCE, cpu_background_state);
+
+       return RESOURCED_ERROR_NONE;
+}
+
+static int resourced_cpu_finalize(void *data)
+{
+       unregister_notifier(RESOURCED_NOTIFIER_APP_RESUME, cpu_foreground_state);
+       unregister_notifier(RESOURCED_NOTIFIER_APP_FOREGRD, cpu_foreground_state);
+       unregister_notifier(RESOURCED_NOTIFIER_WIDGET_FOREGRD, cpu_foreground_state);
+       unregister_notifier(RESOURCED_NOTIFIER_APP_BACKGRD, cpu_background_state);
+       unregister_notifier(RESOURCED_NOTIFIER_THROTTLING_RESOURCE, cpu_background_state);
+
+       return RESOURCED_ERROR_NONE;
+}
+
+static struct module_ops cpu_modules_ops = {
+       .priority = MODULE_PRIORITY_NORMAL,
+       .name = "cpu-throttling",
+       .init = resourced_cpu_init,
+       .exit = resourced_cpu_finalize,
+};
+
+MODULE_REGISTER(&cpu_modules_ops)
diff --git a/src/resource-limiter/cpu/cpu-throttling.c b/src/resource-limiter/cpu/cpu-throttling.c
deleted file mode 100644 (file)
index 623713b..0000000
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * resourced
- *
- * Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file cpu.c
- *
- * @desc cpu module
- *
- * Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved.
- *
- */
-#include <dirent.h>
-#include <errno.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/syscall.h>
-#include "notifier.h"
-#include "procfs.h"
-#include "proc-common.h"
-#include "macro.h"
-#include "module.h"
-#include "module-data.h"
-#include "resourced.h"
-#include "trace.h"
-#include "vconf.h"
-#include "util.h"
-#include "cgroup.h"
-#include "config-parser.h"
-#include "const.h"
-#include "file-helper.h"
-#include "cpu-cgroup.h"
-
-#define CPU_CONF_FILE       RD_CONFIG_FILE(limiter)
-#define CPU_CONF_SECTION    "CPU"
-#define CPU_CONF_PREDEFINE  "PREDEFINE"
-#define CPU_CONF_BOOTING    "BOOTING_PREDEFINE"
-#define CPU_CONF_WRT        "WRT_PREDEFINE"
-#define CPU_CONF_LAZY       "LAZY_PREDEFINE"
-#define MAX_PREDEFINED_TASKS  10
-#define CPU_TIMER_INTERVAL       30
-#define CPU_BACKGROUND_PRI    1
-#define CPU_CONTROL_PRI       10
-
-bool throttling_success = false;
-bool skip_bandwidth = false;
-bool skip_share = false;
-struct sched_attr throttling_attr;
-struct sched_attr normal_attr;
-
-static int move_process_to_throttling_group(pid_t pid, struct proc_app_info *pai)
-{
-       GSList *iter = NULL;
-       pid_t child_pid;
-
-       if (!throttling_success)
-               return RESOURCED_ERROR_NONE;
-
-       if (pai) {
-               if (pai->app_cpu_nice_update_exclude)
-                       goto cpu_cgroup_move;
-
-               sched_setattr_of_all_tasks(pai->main_pid, &throttling_attr, 0);
-               if (pai->childs) {
-                       gslist_for_each_item(iter, pai->childs) {
-                               child_pid = GPOINTER_TO_PID(iter->data);
-                               sched_setattr_of_all_tasks(child_pid, &throttling_attr, 0);
-                       }
-               }
-       }
-       else {
-               sched_setattr_of_all_tasks(pid, &throttling_attr, 0);
-       }
-
-cpu_cgroup_move:
-       if (!skip_share || !skip_bandwidth)
-               return cpu_move_cgroup_foreach(pid, pai, CPUCG_THROTTLING_PATH);
-       else
-               return RESOURCED_ERROR_NONE;
-}
-
-static int move_out_process_from_throttling_group(pid_t pid, struct proc_app_info *pai)
-{
-       GSList *iter = NULL;
-       pid_t child_pid;
-
-       if (!throttling_success)
-               return RESOURCED_ERROR_NONE;
-
-       if (pai) {
-               if (pai->app_cpu_nice_update_exclude)
-                       goto cpu_cgroup_move;
-
-               sched_setattr_of_all_tasks(pai->main_pid, &normal_attr, 0);
-               if (pai->childs) {
-                       gslist_for_each_item(iter, pai->childs) {
-                               child_pid = GPOINTER_TO_PID(iter->data);
-                               sched_setattr_of_all_tasks(child_pid, &normal_attr, 0);
-                       }
-               }
-       }
-       else {
-               sched_setattr_of_all_tasks(pid, &normal_attr, 0);
-       }
-
-cpu_cgroup_move:
-       if (!skip_share || !skip_bandwidth)
-               return cpu_move_cgroup_foreach(pid, pai, CPUCG_PATH);
-       else
-               return RESOURCED_ERROR_NONE;
-}
-
-static int cpu_foreground_state(void *data)
-{
-       int ret;
-       struct proc_status *ps = (struct proc_status *)data;
-
-       assert(ps);
-       _D("app foreground: pid = %d", ps->pid);
-       ret = move_out_process_from_throttling_group(ps->pid, ps->pai);
-       if (ret < 0)
-               _E("Failed to throttle cpu resource of %s%s process (%d)",
-               ps->pai ? "App " : "System service",
-               ps->pai ? ps->pai->appid : "", ps->pid);
-       return RESOURCED_ERROR_NONE;
-}
-
-static int cpu_background_state(void *data)
-{
-       int ret;
-       struct proc_status *ps = (struct proc_status *)data;
-       assert(ps);
-
-       _D("app background: pid = %d", ps->pid);
-       ret = move_process_to_throttling_group(ps->pid, ps->pai);
-       if (ret < 0)
-               _E("Failed to throttle cpu resource of %s%s process (%d)",
-               ps->pai ? "App " : "System service",
-               ps->pai ? ps->pai->appid : "", ps->pid);
-       return RESOURCED_ERROR_NONE;
-}
-
-static void load_cpu_throttling_config(void)
-{
-       int ret;
-       int cpu_nice;
-       long long cpu_runtime_us;
-       unsigned long long cpu_period_us;
-       unsigned long long cpu_share;
-       enum cpu_sched_type cpu_sched_type;
-
-       struct cpu_throttling_conf *cpu_throttling_conf = get_cpu_throttling_conf();
-       if (cpu_throttling_conf == NULL) {
-               _E("[CPU-THROTTLING] cpu sched configuration structure should not be NULL");
-               return;
-       }
-
-       if (!cpu_throttling_conf->enable) {
-               _I("[CPU-THROTTLING] cpu throttling is disabled");
-               goto free_cpu_throttling_conf;
-       }
-
-       cpu_nice = cpu_throttling_conf->cpu_sched_info.cpu_nice;
-       cpu_sched_type = cpu_throttling_conf->cpu_sched_info.cpu_sched_type;
-       cpu_share = cpu_throttling_conf->cpu_cgroup_info.cpu_share;
-       cpu_period_us = cpu_throttling_conf->cpu_cgroup_info.cfs_period_us;
-       cpu_runtime_us = cpu_throttling_conf->cpu_cgroup_info.cfs_runtime_us;
-
-       if (cpu_share == 0) {
-               _E("[CPU-THROTTLING] cpu share cannot be 0");
-               cpu_share = CPU_THROTTLING_SHARE;
-               skip_share = true;
-       }
-
-       if (cpu_period_us == 0 || cpu_runtime_us == 0 ||
-                       cpu_period_us < cpu_runtime_us) {
-               _E("[CPU-THROTTLING] cpu period (%llu) and runtime (%lld) is out of scope",
-                               cpu_period_us, cpu_runtime_us);
-               skip_bandwidth = true;
-       }
-
-       if (cpu_sched_type < CPU_SCHED_IDLE || cpu_sched_type > CPU_SCHED_OTHER) {
-               _E("[CPU-THROTTLING] cpu scheduler type is unknown or realtime");
-               cpu_sched_type = CPU_SCHED_IDLE;
-       }
-
-       if (cpu_sched_type != CPU_SCHED_IDLE &&
-                       (cpu_nice < CPU_MIN_NICE || cpu_nice > CPU_MAX_NICE)) {
-               _W("[CPU-THROTTLING] cpu nice is out of scope");
-               cpu_nice = CPU_MAX_NICE;        /* the worst nice value */
-       }
-
-       /* Make a cpu throttling directory at the cpu cgroup */
-       if (!skip_share || !skip_bandwidth) {
-               ret = cpucg_make_full_subdir(CPUCG_PATH);
-               if (ret < 0) {
-                       _E("Failed to initialize cpu cgroup for throttling\n");
-                       goto free_cpu_throttling_conf;
-               }
-
-               /* Initialize cpu throttling cgroup */
-               cgroup_write_node_ulonglong(CPUCG_THROTTLING_PATH, CPUCG_SHARE, cpu_share);
-               cgroup_write_node_longlong(CPUCG_THROTTLING_PATH, CPUCG_CONTROL_BANDWIDTH,
-                               cpu_runtime_us);
-               cgroup_write_node_ulonglong(CPUCG_THROTTLING_PATH, CPUCG_CONTROL_FULL_BANDWIDTH,
-                               cpu_period_us);
-       }
-
-       /* Initialize type and nice of cpu throttling scheduler */
-       memset(&normal_attr, 0, sizeof(struct sched_attr));
-       normal_attr.size = sizeof(struct sched_attr);
-       normal_attr.sched_nice = CPU_DEFAULT_NICE;
-       normal_attr.sched_policy = SCHED_OTHER;
-
-       memset(&throttling_attr, 0, sizeof(struct sched_attr));
-       throttling_attr.size = sizeof(struct sched_attr);
-       throttling_attr.sched_nice = cpu_nice;
-       switch (cpu_sched_type) {
-               case CPU_SCHED_IDLE:
-                       throttling_attr.sched_policy = SCHED_IDLE;
-                       break;
-               case CPU_SCHED_BATCH:
-                       throttling_attr.sched_policy = SCHED_BATCH;
-                       break;
-               case CPU_SCHED_OTHER:
-                       throttling_attr.sched_policy = SCHED_OTHER;
-                       break;
-               default:
-                       if (!skip_share || !skip_bandwidth)
-                               rmdir(CPUCG_THROTTLING_PATH);
-                       goto free_cpu_throttling_conf;
-       }
-
-       throttling_success = true;
-
-       _I("[CPU-THROTTLING] throttling policy = %s",
-               throttling_attr.sched_policy == SCHED_IDLE ? "SCHED_IDLE" :
-                       throttling_attr.sched_policy == SCHED_BATCH ? "SCHED_BATCH" :
-                       throttling_attr.sched_policy == SCHED_OTHER ? "SCHED_OTHER" : "wrong scheduler type");
-       _I("[CPU-THROTTLING] throttling nice = %d", throttling_attr.sched_nice);
-
-free_cpu_throttling_conf:
-       free_cpu_throttling_conf();
-}
-
-static int resourced_cpu_init(void *data)
-{
-       _D("resourced cpu init start");
-       load_cpu_throttling_config();
-
-       register_notifier(RESOURCED_NOTIFIER_APP_RESUME, cpu_foreground_state);
-       register_notifier(RESOURCED_NOTIFIER_APP_FOREGRD, cpu_foreground_state);
-       register_notifier(RESOURCED_NOTIFIER_WIDGET_FOREGRD, cpu_foreground_state);
-       register_notifier(RESOURCED_NOTIFIER_APP_BACKGRD, cpu_background_state);
-       register_notifier(RESOURCED_NOTIFIER_THROTTLING_RESOURCE, cpu_background_state);
-
-       return RESOURCED_ERROR_NONE;
-}
-
-static int resourced_cpu_finalize(void *data)
-{
-       unregister_notifier(RESOURCED_NOTIFIER_APP_RESUME, cpu_foreground_state);
-       unregister_notifier(RESOURCED_NOTIFIER_APP_FOREGRD, cpu_foreground_state);
-       unregister_notifier(RESOURCED_NOTIFIER_WIDGET_FOREGRD, cpu_foreground_state);
-       unregister_notifier(RESOURCED_NOTIFIER_APP_BACKGRD, cpu_background_state);
-       unregister_notifier(RESOURCED_NOTIFIER_THROTTLING_RESOURCE, cpu_background_state);
-
-       return RESOURCED_ERROR_NONE;
-}
-
-static struct module_ops cpu_modules_ops = {
-       .priority = MODULE_PRIORITY_NORMAL,
-       .name = "cpu-throttling",
-       .init = resourced_cpu_init,
-       .exit = resourced_cpu_finalize,
-};
-
-MODULE_REGISTER(&cpu_modules_ops)
diff --git a/src/resource-monitor/abnormal/heart-abnormal.c b/src/resource-monitor/abnormal/heart-abnormal.c
deleted file mode 100644 (file)
index 02554a6..0000000
+++ /dev/null
@@ -1,436 +0,0 @@
-/*
- * resourced
- *
- * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * @file heart-abnormal.c
- *
- * @desc heart abnormal module
- *
- * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <glib.h>
-#include <sys/time.h>
-
-#include "proc-common.h"
-#include "notifier.h"
-#include "resourced.h"
-#include "dbus-handler.h"
-#include "heart.h"
-#include "logging.h"
-#include "heart-common.h"
-#include "trace.h"
-#include "module.h"
-#include "macro.h"
-
-#define ABNORMAL_NAME                          "abnormal"
-#define ABNORMAL_DATA_MAX                      1024
-#define ABNORMAL_CHECK_NUM                     10
-
-#define TIMESTAMP_LEN                          16
-#define MILLISEC                               1000
-#define TIME_MAX_LEN                           64
-#define SLUG_TYPE_MALFUN                       6
-#define NOPID                                  0
-
-enum abnormal_type {
-       FC = 0,
-       ANR = 1,
-       ABNORMAL_TYPE_MAX,
-};
-
-struct heart_abnormal_table {
-       char appid[MAX_APPID_LENGTH];
-       char pkgid[MAX_PKGNAME_LENGTH];
-       time_t time;
-       int count[ABNORMAL_TYPE_MAX];
-};
-
-static GHashTable *heart_abnormal_list;
-static pthread_mutex_t heart_abnormal_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-void heart_abnormal_fill_array(struct logging_table_form *entry, void *data)
-{
-       int ret, i;
-       unsigned int type;
-       struct heart_abnormal_table *table = NULL;
-       GHashTable *list = (GHashTable *)data;
-
-       if (sscanf((char *)entry->data, "%*s %*s %u ", &type) < 0) {
-               _E("sscanf failed, %m");
-               return;
-       }
-
-       if (type >= ABNORMAL_TYPE_MAX) {
-               _E("wrong abnormal type, %u", type);
-               return;
-       }
-       ret = pthread_mutex_lock(&heart_abnormal_mutex);
-       if (ret) {
-               _E("pthread_mutex_lock() failed, %d", ret);
-               return;
-       }
-       table = g_hash_table_lookup(list, entry->appid);
-       if (!table) {
-               table = malloc(sizeof(struct heart_abnormal_table));
-               if (!table) {
-                       _E("malloc failed");
-                       goto unlock_exit;
-               }
-
-               if (snprintf(table->appid, MAX_APPID_LENGTH, "%s", entry->appid) < 0) {
-                       _E("snprintf failed");
-                       free(table);
-                       goto unlock_exit;
-               }
-
-               if (snprintf(table->pkgid, MAX_PKGNAME_LENGTH, "%s", entry->pkgid) < 0) {
-                       _E("snprintf failed");
-                       free(table);
-                       goto unlock_exit;
-               }
-               table->time = entry->time;
-
-               for (i = 0; i < ABNORMAL_TYPE_MAX; i++)
-                       table->count[i] = 0;
-
-               table->count[type] = 0;
-               g_hash_table_insert(list, (gpointer)table->appid, (gpointer)table);
-       }
-       table->count[type]++;
-
-unlock_exit:
-       ret = pthread_mutex_unlock(&heart_abnormal_mutex);
-       if (ret)
-               _E("pthread_mutex_unlock() failed, %d", ret);
-}
-
-static void heart_abnormal_launch_popup(char *appid, int count)
-{
-       _W("A malfunction popup is supposed to be created here, but system-popup "
-          "doesn't actually expose a MalfunctionNotifierLaunch DBus method and "
-          "this legacy functionality is deprecated.");
-
-#if 0
-       /* Dead code (see above); it has been disabled instead of outright removed
-        * because I've seen too many braindead repository copy-pastes annihilating
-        * git history to trust people to be able to find this code in case their
-        * legacy system suddenly stops working and I don't want to deal with the
-        * flak I could be getting for it. In a year or two (unless somebody patches
-        * system-popup to add MalfurionNotifierLaunch or some other good reason
-        * appears) it would be good to get rid of this code though. */
-
-       int ret;
-       char num[10];
-       char _appid[MAX_APPID_LENGTH];
-       GVariant *param;
-
-       /* Launch malfunction system popup */
-       snprintf(num, 10, "%d", count);
-       snprintf(_appid, MAX_APPID_LENGTH, "%s", appid);
-       _D("appid %s, count %d", appid, count);
-
-       param = g_variant_new("(ssssss)", "_SYSPOPUP_CONTENT_",
-               "malfunction_notifier",
-               "_ERRORS_",
-               num,
-               "_APPID_",
-               _appid)
-
-       ret = d_bus_call_method_async_gvariant("org.tizen.system.popup",
-                       "/Org/Tizen/System/Popup/System",
-                       "org.tizen.system.popup.System",
-                       "MalfunctionNotifierLaunch", param);
-       if (ret < 0)
-               _E("Failed to launch MalfunctionNotifier");
-       else
-               _I("MalfunctionNotifierLaunch Success");
-#endif
-}
-
-static int heart_abnormal_report_malfunction(char *name)
-{
-       int ret = -1;
-       char timestr[TIMESTAMP_LEN] = {0,};
-       int milli;
-       char msgid[TIME_MAX_LEN + sizeof '+' + MAX_DEC_SIZE(milli)] = {0,};
-       char ts[TIME_MAX_LEN] = {0,};
-       struct timeval time_of_day;
-       time_t unix_time = time(NULL);
-       struct tm loc_tm;
-
-       if (gettimeofday(&time_of_day, NULL)) {
-               _E("gettimeofday failed");
-               return ret;
-       }
-       if (!localtime_r(&time_of_day.tv_sec, &loc_tm)) {
-               _E("localtime_r failed");
-               return ret;
-       }
-
-       snprintf(timestr, sizeof(timestr), "%.10ld", unix_time);
-       milli = time_of_day.tv_usec / MILLISEC;
-       strftime(ts, TIME_MAX_LEN, "%Y.%m.%d-%H:%M:%S", &loc_tm);
-       snprintf(msgid, sizeof(msgid), "%s+%d", ts, milli);
-
-       ret = d_bus_call_method_async_gvariant("org.tizen.system.crash", "/Org/Tizen/System/Crash/Crash", "org.tizen.system.crash.Crash",
-                               "sluggish_dump",
-                               g_variant_new("(iisss)", SLUG_TYPE_MALFUN, NOPID, name, timestr, msgid));
-
-       if (ret < 0)
-               _E("Malfunction reporting to sluggish tool failed");
-       return ret;
-}
-
-static void heart_abnormal_process_crashed(GVariant *params)
-{
-       int ret, notify, count;
-       gpointer key, value;
-       time_t curtime, starttime;
-       GHashTableIter hiter;
-       char *process_name = NULL, *exepath = NULL, *appid = NULL, *pkgid = NULL;
-       char info[ABNORMAL_DATA_MAX];
-       struct heart_abnormal_table *table = NULL;
-
-       do_expr_unless_g_variant_get_typechecked(return, params, "(&s&s&s&ssiia{sv})", &process_name, &exepath, &appid, &pkgid,
-                                       NULL, NULL, NULL, NULL);
-       if (!process_name || !exepath || !appid || !pkgid) {
-               _E("Failed: dbus_message_get_args()");
-               return;
-       }
-       curtime = time(NULL);
-       starttime = curtime - 604800;
-       if (starttime < 0)
-               starttime = 0;
-
-       if (g_hash_table_size(heart_abnormal_list))
-               g_hash_table_remove_all(heart_abnormal_list);
-
-       logging_read_foreach(ABNORMAL_NAME, appid, NULL, starttime, curtime,
-                       heart_abnormal_fill_array, heart_abnormal_list);
-
-       g_hash_table_iter_init(&hiter, heart_abnormal_list);
-
-       count = 0;
-       while (g_hash_table_iter_next(&hiter, &key, &value)) {
-               table = (struct heart_abnormal_table *)value;
-               if (!table)
-                       break;
-               count += table->count[FC];
-       }
-
-       notify = 0;
-       if (count > ABNORMAL_CHECK_NUM) {
-               heart_abnormal_launch_popup(appid, count);
-               notify = 1;
-               heart_abnormal_report_malfunction(appid);
-       }
-
-       g_hash_table_remove_all(heart_abnormal_list);
-
-       snprintf(info, sizeof(info), "%s %s %d %d ", process_name, exepath, notify, FC);
-       _D("info : %s %d", info, count);
-       ret = logging_write(PID_FOR_ROOT, ABNORMAL_NAME, appid, pkgid, time(NULL), info);
-       if (ret != RESOURCED_ERROR_NONE)
-               _E("Failed to logging_write %s", info);
-}
-
-static int heart_abnormal_anr(void *data)
-{
-       int ret;
-       char info[ABNORMAL_DATA_MAX];
-       struct proc_status *ps = (struct proc_status *)data;
-       char *appid, *pkgid;
-
-       ret = proc_get_id_info(ps, &appid, &pkgid);
-       if (ret != RESOURCED_ERROR_NONE) {
-               _E("Failed to proc_get_id_info");
-               return ret;
-       }
-       snprintf(info, sizeof(info), "%d ANR %d ", ps->pid, ANR);
-       _D("info : %s", info);
-       ret = logging_write(PID_FOR_ROOT, ABNORMAL_NAME, appid, pkgid, time(NULL), info);
-       if (ret != RESOURCED_ERROR_NONE)
-               _E("Failed to logging_write %s", info);
-       return ret;
-}
-
-static void heart_abnormal_free_value(gpointer value)
-{
-       struct heart_abnormal_table *table =
-               (struct heart_abnormal_table *)value;
-
-       if (!table)
-               return;
-
-       free(table);
-}
-
-static void dbus_heart_get_abnormal_data(GDBusMethodInvocation *invocation, GVariant *params)
-{
-       int type = -1, period = -1;
-       int ret, count, i;
-       time_t starttime;
-       char *appid;
-       gpointer key, value;
-       GHashTableIter hiter;
-       struct heart_abnormal_table *table = NULL;
-       GVariantBuilder builder, *sub_builder;
-
-       do_expr_unless_g_variant_get_typechecked(goto failure, params, "(ii)", &type, &period);
-       if (type < 0 || ABNORMAL_TYPE_MAX  < type || period < 0) {
-               _E("Wrong message arguments! %d", type);
-               goto failure;
-       }
-       starttime = time(NULL);
-       switch (period) {
-       case DATA_LATEST:
-               starttime = 0;
-               break;
-       case DATA_3HOUR:
-               starttime -= 10800;
-               break;
-       case DATA_6HOUR:
-               starttime -= 21600;
-               break;
-       case DATA_12HOUR:
-               starttime -= 43200;
-               break;
-       case DATA_1DAY:
-               starttime -= 86400;
-               break;
-       case DATA_1WEEK:
-               starttime -= 604800;
-               break;
-       default:
-               _E("Wrong message arguments! %d", period);
-               goto failure;
-       }
-
-       if (starttime < 0)
-               starttime = 0;
-
-       if (g_hash_table_size(heart_abnormal_list))
-               g_hash_table_remove_all(heart_abnormal_list);
-
-       logging_read_foreach(ABNORMAL_NAME, NULL, NULL, starttime, time(NULL),
-                       heart_abnormal_fill_array, heart_abnormal_list);
-
-       ret = pthread_mutex_lock(&heart_abnormal_mutex);
-       if (ret) {
-               _E("pthread_mutex_lock() failed, %d", ret);
-               goto failure;
-       }
-
-       g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
-       sub_builder = g_variant_builder_new(G_VARIANT_TYPE("a(si)"));
-
-       g_hash_table_iter_init(&hiter, heart_abnormal_list);
-       while (g_hash_table_iter_next(&hiter, &key, &value)) {
-               table = (struct heart_abnormal_table *)value;
-               if (!table)
-                       break;
-               count = 0;
-               appid = table->appid;
-
-               if (type == ABNORMAL_TYPE_MAX) {
-                       for (i = 0; i < ABNORMAL_TYPE_MAX; i++)
-                               count += table->count[i];
-               } else
-                       count += table->count[type];
-
-               if (!count)
-                       continue;
-
-               g_variant_builder_add(sub_builder, "(si)", appid, count);
-       }
-       g_variant_builder_add_value(&builder, g_variant_new("a(si)", sub_builder));
-       g_variant_builder_unref(sub_builder);
-
-       ret = pthread_mutex_unlock(&heart_abnormal_mutex);
-       if (ret) {
-               _E("pthread_mutex_unlock() failed, %d", ret);
-               goto failure;
-       }
-       g_hash_table_remove_all(heart_abnormal_list);
-
-       g_dbus_method_invocation_return_value(invocation, g_variant_builder_end(&builder));
-       return;
-
-failure:
-       D_BUS_REPLY_ERR(invocation);
-}
-
-static const char dbus_methods_xml[] =
-"              <method name='GetAbnormalData'>"
-"                      <arg type='i' name='Type' direction='in'/>"
-"                      <arg type='i' name='Period' direction='in'/>"
-"                      <arg type='a(si)' name='CountPerApp' direction='out'/>"
-"              </method>";
-
-static struct d_bus_method dbus_methods[] = {
-       { "GetAbnormalData", dbus_heart_get_abnormal_data },
-};
-
-static int heart_abnormal_init(void *data)
-{
-       int ret;
-
-       ret = logging_module_init(ABNORMAL_NAME, ONE_WEEK, HALF_HOUR, NULL, 0, SYSTEM_DEFAULT);
-       if (ret != RESOURCED_ERROR_NONE) {
-               _E("logging module init failed");
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       heart_dbus_declare_methods(dbus_methods_xml, dbus_methods, ARRAY_SIZE(dbus_methods));
-
-       ret = d_bus_register_signal(CRASH_PATH_CRASH,
-                       CRASH_INTERFACE_CRASH, PROCESS_CRASHED,
-                       heart_abnormal_process_crashed, NULL);
-       if (ret < 0)
-               _E("Failed to add a capacity status signal handler");
-       heart_abnormal_list = g_hash_table_new_full(
-                       g_str_hash,
-                       g_str_equal,
-                       NULL,
-                       heart_abnormal_free_value);
-
-       register_notifier(RESOURCED_NOTIFIER_APP_ANR, heart_abnormal_anr);
-       _D("heart abnormal init finished");
-       return RESOURCED_ERROR_NONE;
-}
-
-static int heart_abnormal_exit(void *data)
-{
-       if (heart_abnormal_list)
-               g_hash_table_destroy(heart_abnormal_list);
-       logging_module_exit();
-       unregister_notifier(RESOURCED_NOTIFIER_APP_ANR, heart_abnormal_anr);
-       _D("heart abnormal exit");
-       return RESOURCED_ERROR_NONE;
-}
-
-static const struct heart_module_ops heart_abnormal_ops = {
-       .name           = "ABNORMAL",
-       .init           = heart_abnormal_init,
-       .exit           = heart_abnormal_exit,
-};
-HEART_MODULE_REGISTER(&heart_abnormal_ops)
diff --git a/src/resource-monitor/battery/heart-battery.c b/src/resource-monitor/battery/heart-battery.c
deleted file mode 100644 (file)
index 4c5b9b6..0000000
+++ /dev/null
@@ -1,3702 +0,0 @@
-/*
- * resourced
- *
- * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * @file heart-battery.c
- *
- * @desc heart battery module
- *
- * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
- *
- */
-
-#include <stdio.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <glib.h>
-#include <sqlite3.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <math.h>
-#include <device/display.h>
-#include <device/callback.h>
-#include <system_info.h>
-
-#include "proc-common.h"
-#include "notifier.h"
-#include "resourced.h"
-#include "dbus-handler.h"
-#include "heart.h"
-#include "logging.h"
-#include "heart-common.h"
-#include "config-parser.h"
-#include "trace.h"
-#include "vconf.h"
-#include "module.h"
-#include "macro.h"
-#include "util.h"
-#include "file-helper.h"
-
-#define TIZEN_SYSTEM_APPID                     "org.tizen.system"
-#define TIZEN_SYSTEM_BATTERY_APPID             "org.tizen.system.battery.capacity"
-#define BATTERY_NAME                           "battery"
-#define BATTERY_DATA_MAX                       1024
-#define BATTERY_CAPACITY_MAX                   512
-#define BATTERY_LINE_MAX                       128
-#define BATTERY_CLEAN_MAX                      100
-#define BATTERY_HISTORY_DAY_MAX                        7
-#define BATTERY_HISTORY_RESET_MAX              5
-#define BATTERY_HISTORY_RESET_CURRENT          (BATTERY_HISTORY_RESET_MAX - 1)
-#define BATTERY_HISTORY_COUNT_MAX              1000
-#define HEART_BATTERY_UPDATE_INTERVAL          HALF_HOUR
-#define HEART_BATTERY_SAVE_INTERVAL            HALF_HOUR
-#define HEART_BATTERY_CAPACITY_DATA_FILE       HEART_FILE_PATH"/.battery_capacity.dat"
-#define HEART_BATTERY_CONF_SECTION              "BATTERY_POWER_MODE"
-#define GET_CHARGER_STATUS                     "ChargerStatus"
-#define GET_BATTERY_CAPACITY                   "GetPercent"
-#define CALCULATE_DAY_BASE_TIME(x)             ((x / DAY_TO_SEC(1)) * (DAY_TO_SEC(1)))
-#define REMAIN_CAPACITY(x)                     (100 - x)
-#define BATTERY_PREDICTION_DATA_MIN            5
-#define BATTERY_USAGE_LEARNING                 -1
-#define CUMUL_WEIGHT                           (0.8)
-#define TREND_WEIGHT                           (1 - CUMUL_WEIGHT)
-#define DISCHARGE_BASE_RATE                    (0.2)
-
-/*
- * BATTERY_PREDICTION_LATEST_COUNT must be >= BATTERY_PREDICTION_DATA_MIN
- */
-#define BATTERY_PREDICTION_LATEST_COUNT                5
-/*
- * BATTERY_PREDICTION_PERIOD possible values:
- * DATA_LATEST, DATA_3HOUR, DATA_6HOUR, DATA_12HOUR, DATA_1DAY
- */
-#define BATTERY_PREDICTION_PERIOD              DATA_3HOUR
-
-#define BATTERY_USED_TIME                       "BATTERY_USED_TIME"
-#define BATTERY_STATUS                          "BATTERY_STATUS"
-#define BATTERY_RESET_USAGE                     "BATTERY_RESET_USAGE"
-#define BATTERY_WEEK_DAY_USAGE                  "BATTERY_WEEK_DAY_USAGE"
-#define BATTERY_LEVEL_USAGE                     "BATTERY_LEVEL_USAGE"
-#define BATTERY_PREDICTION                      "BATTERY_PREDICTION"
-
-#define INDEX_WINDOW_SIZE              10  /*data storing index*/
-#define BATTERY_LEVEL_GAP              5  /*previous 5 battery data*/
-#define LONG_TIME_WEIGHT               (0.7) /*weightage given for longer time discharge*/
-#define SHORT_TIME_WEIGHT              (1-LONG_TIME_WEIGHT) /*weightage given for short time discharge*/
-#define NEW_PIVOT_WEIGHTAGE(x)         (x * 0.10) /* x/10th part */
-#define OLD_PIVOT_WEIGHTAGE(x)         (1.0 - NEW_PIVOT_WEIGHTAGE(x))
-#define MIN_DISCHARGE_PERIOD           40
-#define LOW_CAPACITY                   2
-#define MIN_TIME_FOR_LVL_CHANGE                50
-#define BATT_CHG_FLUSH_DATA            10
-
-/*
- * Below 6 values are the co-efficient of the polynomial. These are devired from
- * OCV and  and battery percentage level based on experiment
- */
-#define OCV_SOC_POLY_COEF_1                    (3402.664)
-#define OCV_SOC_POLY_COEF_2                    (42.031)
-#define OCV_SOC_POLY_COEF_3                    (-1.76745)
-#define OCV_SOC_POLY_COEF_4                    (0.034798)
-#define OCV_SOC_POLY_COEF_5                    (-0.00030516)
-#define OCV_SOC_POLY_COEF_6                    (0.0000010116)
-#define UPS_FACTOR                             (2.88)
-#define DOUBLE_ZERO                            (0.000000)
-#define FULL_CAPACITY                  100
-/* BATTERY_C_RATE is defined as the rate of which battery capacity is changing
- * If total battery capacity is XmAh, then in one second battery capacity change
- * will be considered as 90
- */
-#define BATTERY_C_RATE                 90
-#define SEC_TO_MIN(x) ((x + 30)/60)  /* 30 secs buffer to round off */
-#define CAL_MIN(x, y) ((x < y) ? x : y)
-#define BATTERY_WINDOW_INDEX(x)                (((x) +  INDEX_WINDOW_SIZE) % INDEX_WINDOW_SIZE)
-#define HEART_BATTERY_DATA_FILE                HEART_FILE_PATH"/.battery_data.dat"
-#define HEART_BATTERY_PIVOT_INFO       HEART_FILE_PATH"/.battery_pivot_data.dat"
-#define VCONFKEY_HEART_BATTERY_DEVICE_MODE                     "db/setting/psmode"
-#define VCONFKEY_SETAPPL_MANAGE_BATTERY_TRIGGER_TIME "db/setting/manage_battery_trigger_time"
-
-/*
- * Remaining Useful Life prediction logic
- */
-#define RUL_DATA_FILE                  HEART_FILE_PATH"/.rul_data.dat"
-#define RUL_CHARGING_CYCLES_FILE                       HEART_FILE_PATH"/.charging_cycles.dat"
-#define RUL_MIN_CAPACITY_DIFF                  50
-#define RUL_DISPLAY_ON_CUTOFF_RATIO                    0.1f
-#define RUL_DATA_SIZE                  32
-
-enum {
-       TA     = 0,     /* prediction based on total data average */
-       PCB    = 1,     /* prediction with physiological behaviors */
-       WEEK   = 2,     /* prediction based on weekly data */
-       COUNT  = 3,     /* prediction based on last BATTERY_PREDICTION_COUNT number of items */
-       PERIOD = 4,     /* prediction based on data from last BATTERY_PREDICTION_PERIOD time */
-       MAX_STRATEGY = 5,
-};
-
-enum {
-       POWER_NORMAL_MODE  = 0,
-       POWER_SAVING_MODE  = 1,
-       ULTRA_SAVING_MODE  = 2,
-       POWER_MODE_MAX     = 3,
-};
-
-enum {
-       BATTERY_LEVEL_LOW = 0, /* 15 ~ 0 */
-       BATTERY_LEVEL_MID = 1, /* 49 ~ 16 */
-       BATTERY_LEVEL_HIGH = 2, /* 50 ~ 100 */
-       BATTERY_LEVEL_MAX = 3,
-};
-
-enum {
-       DEFAULT_MIN = 0,
-       DEFAULT_AVG = 1,
-       DEFAULT_MAX = 2,
-       DEFAULT_VALUE_MAX = 3,
-};
-
-/* Structure to calculate percentage time LCD on during charging */
-struct rul_lcd_data {
-       display_state_e state;
-       long on_time;
-       long on_start_time;
-       long on_stop_time;
-};
-
-/* Structure to store RUL related charging info  */
-struct rul_info {
-       long charging_start_time;
-       long charging_stop_time;
-       float raw_capacity; /* capacity (mAh) accumulation during charging */
-       int soc_start; /* SoC(%) value when charging starts */
-       int soc_stop; /* SoC(%) value when charging stops */
-       int charging_cycles; /* Number of charging cycles */
-       int curr_soc; /* Current SoC %, compare with prev_soc to determine if charging */
-       int prev_soc; /* Previous value of SoC % */
-       struct rul_lcd_data lcd_data; /* LCD related data */
-};
-
-struct battery_used {
-       time_t used_time_sec; /* seconds on battery */
-       time_t last_update_time;
-       int last_charger_status;
-};
-
-struct battery_usage {
-       time_t start_time; /* timestamp when event started */
-       long sec_per_cap[MAX_CHARGER_STATE]; /* seconds per capacity level change */
-       long cap_counter[MAX_CHARGER_STATE]; /* number of capacity level changes */
-};
-
-struct battery_prediction {
-       long sec_per_cap[MAX_STRATEGY]; /* seconds per capacity level change */
-       long cap_counter[MAX_STRATEGY]; /* number of capacity level changes */
-       long time_pred_min[MAX_STRATEGY]; /* time prediction in minutes */
-};
-
-struct battery_pivot_info {
-       long start_time_dischg; /* store the time from when discharge started */
-       int pvt_data_ind; /* index to keep track of total_dischg_time value */
-       int start_cap_dischg; /* capacity from when discharge started */
-       int total_dischg_time[INDEX_WINDOW_SIZE]; /* total discharge period */
-       time_t last_clock_tick; /* last tick stored */
-};
-
-struct battery_status {
-       /* current battery status */
-       enum charger_status_type curr_charger_status;
-       int curr_capacity;
-
-       enum discharge_rate_level_type discharge_rate_level;
-       /* current runtime statistics */
-       long curr_run_time_sec[MAX_CHARGER_STATE]; /* seconds since reset */
-       long curr_cap_counter[MAX_CHARGER_STATE]; /* capacity level changes */
-
-       long last_wall_time[INDEX_WINDOW_SIZE];  /* previous battery level discharge time */
-       /* previous battery level change time in charging mode */
-       long last_wall_time_chg;
-       /* charging data index*/
-       int index_chg;
-       /* store last 5 battery level change time diff */
-       int last_wall_time_chg_diff[BATTERY_LEVEL_GAP];
-        /* indicates whether do we have enough data to estimate the battery time */
-       int data_available;
-       int curr_index;  /* store current index value */
-       int last_capacity;  /* last battery capacity value */
-       int last_capacity_chg; /* last battery capacity value in charge mode */
-       int remaining_time; /* previous remaining time */
-       int remaining_time_chg; /* previous remaining time in charging mode */
-       int remaining_time_ups; /* previous remaining time in UPS */
-       double last_volt_intg[INDEX_WINDOW_SIZE]; /* store previous calculated voltage integral(energy) value */
-       double last_pwr_bchg;  /* store the battery power available just before charging start */
-
-       /* wall clock time stamp when last event happened in seconds */
-       time_t last_event_wall_time;
-       time_t last_clock_tick;
-
-       /*
-        * reset mark is set when battery is charged in over 90% and
-        * charger was disconnected from the device.
-        * We consider then the device as "charged"
-        *
-        * The possible values are 0 and 1 they're swapped to opposite on change.
-        */
-       int reset_mark;
-       time_t reset_mark_timestamp;
-
-       /* usage time from last reset_mark change*/
-       struct battery_usage batt_reset_usage[BATTERY_HISTORY_RESET_MAX];
-
-       /* usage time by week day */
-       struct battery_usage week_day_usage[BATTERY_HISTORY_DAY_MAX];
-
-       /* usage time by user behavior & battery level */
-       struct battery_usage batt_lvl_usage[BATTERY_LEVEL_MAX];
-
-       /* calculated battery prediction */
-       struct battery_prediction prediction[MAX_CHARGER_STATE];
-
-       /* battery pivot information */
-       struct battery_pivot_info pvt;
-};
-
-static int default_sec_per_cap[MAX_CHARGER_STATE][DEFAULT_VALUE_MAX] = {
-       { 70, 670, 3600 }, /* DISCHARGING MIN: 70s, AVG: 670s, MAX: 1 hour */
-       { 30, 80, 3600 }    /* CHARGING MIN: 30s, AVG: 80s,  MAX: 1 hour */
-};
-
-static double default_mode_spc[POWER_MODE_MAX] = {
-       670,    /* POWER_NORMAL_MODE */
-       750,    /* POWER_SAVING_MODE */
-       1947    /* ULTRA_SAVING_MODE */
-};
-
-static double default_mode_factor[POWER_MODE_MAX] = {
-       1,      /* POWER_NORMAL_MODE */
-       1.1,    /* POWER_SAVING_MODE */
-       2.88    /* ULTRA_SAVING_MODE */
-};
-
-struct heart_power_profile {
-       float wifi_on;
-       float wifi_active;
-       float wifi_scan;
-};
-
-static struct heart_power_profile power_profile;
-#ifdef NETWORK_SUPPORT
-static struct heart_calc_time calc_time;
-#endif
-static struct battery_used batt_used;
-static struct battery_status batt_stat;
-static GSList *capacity_history_list = NULL;
-static pthread_mutex_t heart_battery_mutex = PTHREAD_MUTEX_INITIALIZER;
-static time_t last_file_commit_time;
-static int battery_learning_mode;
-
-static int ocv_degree; /* Degree of the OCV and SOC polynomial */
-static double *intg;   /* Co-efficients of the OCV and SOC polynomial */
-static double pivot_nor;  /* time pivot for normal mode */
-static double pivot_ups; /* time pivot for UPS mode */
-static double volt_intg_full; /* 100% battery voltage integral(engery) value */
-static bool data_avail_chg = false; /* 5 readings in charging mode */
- /*
- * variable to hold the current device mode(NORMAL, PS & UPS)
- */
-static int device_mode = POWER_NORMAL_MODE;
-
-static int heart_battery_direct_get_capacity(void);
-
-/*
- * Given the 'SOC', remaining energy of the cell can be predicted. New battery
- * remaining time estimation logic will calculating the remaining energy as
- * 'curr_volt_intg'.
- *
- * Based on estimated average power(P), a time estimate can be calcluated.
- * Power can be estimated based on constant SOC interval Ps and constant
- * time interval Pt.
- *
- * At high usage Ps will be short term average power and Pt will be long term
- * average power.
- *
- * At low usage Ps will be long term average power and Pt will be short term
- * average power.
- *
- * The new logic will calculate the average power 'batt_pwr' from Ps and Pt.
- *
- * Under-relaxation is a popular and effective technique of stabilizing prediction.
- * The predicted time is stabilized around a pivot, which is calculated from the
- * high-usage time and low-usage time
- *
- * The new logic will calculated 'pivot_nor' and 'pivot_ups' for normal and UPS
- * mode respectively
- *
- * Finally, using current available energy(curr_volt_intg), average power(batt_pwr)
- * and pivot time (pivot_nor or pivot_ups) this new logic will estimate the Battery
- * Remaining Time for normal mode and UPS mode
- */
-/*
- * new battery remaining time estimation logic
- */
-static int logic_v2;
-/*
- * Total time taken in minutes when device is discharging at fastest rate
- */
-static int discharge_fast;
-/*
- * Total time taken in minutes when device is discharging at slowest rate
- */
-static int discharge_slow;
-/*
- * Avarage power consumed in UPS mode
- */
-static double average_pwr;
-/*
- * Total battery capacity in minutes(mAM)
- */
-static int total_battery_capacity;
-/*
- * This variable indicates first battery level update after charger insert
- */
-static bool first_level_change = FALSE;
-/*
- * This variable indicates the battery header used in heart.conf file
- */
-static char battery_header[BATTERY_LINE_MAX] = "BATTERY";
-
-/*
- * Remaining Useful Life (RUL) prediction logic
- */
-static int logic_rul;
-struct rul_info rul;
-
-static int get_battery_remaining_time(int mode, enum charger_status_type status);
-
-int heart_battery_get_capacity(void)
-{
-       return batt_stat.curr_capacity;
-}
-
-enum charger_status_type heart_battery_get_charger_status(void)
-{
-       return batt_stat.curr_charger_status;
-}
-
-static inline void heart_battery_set_usage_reset_stime(int history, time_t start_time)
-{
-       batt_stat.batt_reset_usage[history].start_time = start_time;
-}
-
-static inline void heart_battery_set_usage_reset(int history, enum charger_status_type status, long sec_per_cap, long cap_counter)
-{
-       batt_stat.batt_reset_usage[history].sec_per_cap[status] = sec_per_cap;
-       batt_stat.batt_reset_usage[history].cap_counter[status] = cap_counter;
-}
-
-static inline long heart_battery_get_usage_reset_total_time(int history, enum charger_status_type status)
-{
-       return batt_stat.batt_reset_usage[history].sec_per_cap[status] * batt_stat.batt_reset_usage[history].cap_counter[status];
-}
-
-static inline long heart_battery_get_usage_reset_count(int history, enum charger_status_type status)
-{
-       return batt_stat.batt_reset_usage[history].cap_counter[status];
-}
-
-static inline void heart_battery_set_usage_level_stime(int level, time_t start_time)
-{
-       batt_stat.batt_lvl_usage[level].start_time = start_time;
-}
-
-static inline void heart_battery_set_usage_level(int level, enum charger_status_type status, long sec_per_cap, long cap_counter)
-{
-       batt_stat.batt_lvl_usage[level].sec_per_cap[status] = sec_per_cap;
-       batt_stat.batt_lvl_usage[level].cap_counter[status] = cap_counter;
-}
-
-static inline long heart_battery_get_usage_level_total_time(int level, enum charger_status_type status)
-{
-       return batt_stat.batt_lvl_usage[level].sec_per_cap[status] * batt_stat.batt_lvl_usage[level].cap_counter[status];
-}
-
-static inline long heart_battery_get_usage_level_spc(int level, enum charger_status_type status)
-{
-       return batt_stat.batt_lvl_usage[level].sec_per_cap[status];
-}
-
-static inline long heart_battery_get_usage_level_count(int level, enum charger_status_type status)
-{
-       return batt_stat.batt_lvl_usage[level].cap_counter[status];
-}
-
-static inline long heart_battery_get_usage_week_total_time(int day, enum charger_status_type status)
-{
-       return batt_stat.week_day_usage[day].sec_per_cap[status] * batt_stat.week_day_usage[day].cap_counter[status];
-}
-
-static inline long heart_battery_get_usage_week_count(int day, enum charger_status_type status)
-{
-       return batt_stat.week_day_usage[day].cap_counter[status];
-}
-
-static inline void heart_battery_set_usage_week_stime(int day, time_t start_time)
-{
-       batt_stat.week_day_usage[day].start_time = start_time;
-}
-
-static inline time_t heart_battery_get_usage_week_stime(int day)
-{
-       return batt_stat.week_day_usage[day].start_time;
-}
-
-static inline int heart_battery_get_learning_mode(void)
-{
-       int i, count = 0;
-
-       if (logic_v2) { /* new logic */
-               /*wait till enough data gets collected to estimated battery remaining time */
-               if (batt_stat.data_available == TRUE)
-                       return 1;
-               return 0;
-       }
-        /* old logic */
-       for (i = 0; i < BATTERY_HISTORY_DAY_MAX; i++) {
-               if (heart_battery_get_usage_week_stime(i))
-                       count++;
-               if (count > 1)
-                       return 1;
-       }
-       return 0;
-}
-
-static inline void heart_battery_set_usage_week(int day, enum charger_status_type status, long sec_per_cap, long cap_counter)
-{
-       batt_stat.week_day_usage[day].sec_per_cap[status] = sec_per_cap;
-       batt_stat.week_day_usage[day].cap_counter[status] = cap_counter;
-}
-
-static inline void heart_battery_set_prediction(int strategy, enum charger_status_type status, long sec_per_cap, long cap_counter, long pred_min)
-{
-       batt_stat.prediction[status].sec_per_cap[strategy] = sec_per_cap;
-       batt_stat.prediction[status].cap_counter[strategy] = cap_counter;
-       batt_stat.prediction[status].time_pred_min[strategy] = pred_min;
-}
-
-static inline long heart_battery_get_prediction_time(int strategy, enum charger_status_type status)
-{
-       return batt_stat.prediction[status].time_pred_min[strategy];
-}
-
-static inline time_t heart_battery_get_file_commit_timestamp()
-{
-       return last_file_commit_time;
-}
-
-static inline void heart_battery_set_file_commit_timestamp(time_t timestamp)
-{
-       last_file_commit_time = timestamp;
-}
-
-static int heart_battery_calculate_discharge_rate_level(long spc)
-{
-       long gap, total_spc;
-
-       total_spc = batt_stat.prediction[DISCHARGING].sec_per_cap[TA];
-       if (!total_spc)
-               return BATTERY_DISCHARGE_NONE;
-       gap = (total_spc * DISCHARGE_BASE_RATE);
-
-       _I("total: %ld, spc: %ld, gap: %ld", total_spc, spc, gap);
-
-       if (total_spc + gap < spc)
-               return BATTERY_DISCHARGE_LOW;
-       else if (total_spc - gap > spc)
-               return BATTERY_DISCHARGE_HIGH;
-
-       return BATTERY_DISCHARGE_AVG;
-}
-
-static void heart_battery_save_used_time(char *key, struct battery_used *used)
-{
-       assert(key);
-       assert(used);
-
-       logging_leveldb_putv(key, strlen(key), "%d %d ",
-                       used->used_time_sec, used->last_update_time);
-};
-
-static void heart_battery_save_status(char *key, struct battery_status *status)
-{
-       assert(key);
-       assert(status);
-
-       logging_leveldb_putv(key, strlen(key), "%d %ld %ld %ld %ld %d %d ",
-                       status->curr_capacity,
-                       status->curr_run_time_sec[DISCHARGING],
-                       status->curr_cap_counter[DISCHARGING],
-                       status->curr_run_time_sec[CHARGING],
-                       status->curr_cap_counter[CHARGING],
-                       status->curr_charger_status,
-                       status->reset_mark);
-};
-
-static void heart_battery_save_usage(char *key, struct battery_usage *usage, int total_size)
-{
-       int i, len, num;
-       char buf[BATTERY_DATA_MAX] = {0, };
-
-       assert(key);
-       assert(usage);
-
-       len = 0;
-       num = total_size/sizeof(struct battery_usage);
-       for (i = 0; i < num; i++) {
-               len += snprintf(buf + len, BATTERY_DATA_MAX - len, "%ld %ld %ld %ld %ld ",
-                               usage[i].start_time,
-                               usage[i].sec_per_cap[DISCHARGING],
-                               usage[i].cap_counter[DISCHARGING],
-                               usage[i].sec_per_cap[CHARGING],
-                               usage[i].cap_counter[CHARGING]);
-       }
-       logging_leveldb_put(key, strlen(key), buf, len);
-};
-
-static void heart_battery_save_prediction(char *key, struct battery_prediction *prediction)
-{
-       int i, len;
-       char buf[BATTERY_DATA_MAX] = {0, };
-
-       assert(key);
-       assert(prediction);
-
-       len = 0;
-       for (i = 0; i < MAX_STRATEGY; i++) {
-               len += snprintf(buf + len, BATTERY_DATA_MAX - len, "%ld %ld %ld %ld %ld %ld ",
-                               prediction[DISCHARGING].sec_per_cap[i],
-                               prediction[DISCHARGING].cap_counter[i],
-                               prediction[DISCHARGING].time_pred_min[i],
-                               prediction[CHARGING].sec_per_cap[i],
-                               prediction[CHARGING].cap_counter[i],
-                               prediction[CHARGING].time_pred_min[i]);
-       }
-       logging_leveldb_put(key, strlen(key), buf, len);
-};
-
-
-static int heart_battery_load_used_time(char *key, struct battery_used *used)
-{
-       int ret;
-       char *token;
-       char buf[BATTERY_DATA_MAX] = {0, };
-       char *saveptr;
-
-       if (!key || !used)
-               return RESOURCED_ERROR_FAIL;
-
-       ret = logging_leveldb_read(key, strlen(key), buf, sizeof(buf));
-       if (ret != RESOURCED_ERROR_NONE) {
-               _E("Failed to read leveldb key: %s", key);
-               return RESOURCED_ERROR_FAIL;
-       }
-       token = strtok_r(buf, " ", &saveptr);
-       if (!token) {
-               _E("Failed to token value");
-               return RESOURCED_ERROR_FAIL;
-       }
-       used->used_time_sec = atoi(token);
-       token = strtok_r(NULL, " ", &saveptr);
-       if (!token) {
-               _E("Failed to token value");
-               return RESOURCED_ERROR_FAIL;
-       }
-       used->last_update_time = atoi(token);
-       return RESOURCED_ERROR_NONE;
-};
-
-static int heart_battery_load_status(char *key, struct battery_status *status)
-{
-       int ret;
-       char *token;
-       char buf[BATTERY_DATA_MAX] = {0, };
-       char *saveptr;
-
-       if (!key || !status)
-               return RESOURCED_ERROR_FAIL;
-
-       ret = logging_leveldb_read(key, strlen(key), buf, sizeof(buf));
-       if (ret != RESOURCED_ERROR_NONE) {
-               _E("Failed to read leveldb key: %s", key);
-               return RESOURCED_ERROR_FAIL;
-       }
-       token = strtok_r(buf, " ", &saveptr);
-       if (!token) {
-               _E("Failed to token value");
-               return RESOURCED_ERROR_FAIL;
-       }
-       status->curr_capacity = atoi(token);
-       token = strtok_r(NULL, " ", &saveptr);
-       if (!token) {
-               _E("Failed to token value");
-               return RESOURCED_ERROR_FAIL;
-       }
-       status->curr_run_time_sec[DISCHARGING] = atol(token);
-       token = strtok_r(NULL, " ", &saveptr);
-       if (!token) {
-               _E("Failed to token value");
-               return RESOURCED_ERROR_FAIL;
-       }
-       status->curr_cap_counter[DISCHARGING] = atol(token);
-       token = strtok_r(NULL, " ", &saveptr);
-       if (!token) {
-               _E("Failed to token value");
-               return RESOURCED_ERROR_FAIL;
-       }
-       status->curr_run_time_sec[CHARGING] = atol(token);
-       token = strtok_r(NULL, " ", &saveptr);
-       if (!token) {
-               _E("Failed to token value");
-               return RESOURCED_ERROR_FAIL;
-       }
-       status->curr_cap_counter[CHARGING] = atol(token);
-       token = strtok_r(NULL, " ", &saveptr);
-       if (!token) {
-               _E("Failed to token value");
-               return RESOURCED_ERROR_FAIL;
-       }
-       status->curr_charger_status = atoi(token);
-       token = strtok_r(NULL, " ", &saveptr);
-       if (!token) {
-               _E("Failed to token value");
-               return RESOURCED_ERROR_FAIL;
-       }
-       status->reset_mark = atoi(token);
-       return RESOURCED_ERROR_NONE;
-};
-
-static int heart_battery_load_usage(char *key, struct battery_usage *usage, int total_size)
-{
-       int i, num, ret;
-       char *token;
-       char buf[BATTERY_DATA_MAX] = {0, };
-       char *saveptr;
-
-       if (!key || !usage)
-               return RESOURCED_ERROR_FAIL;
-
-       ret = logging_leveldb_read(key, strlen(key), buf, sizeof(buf));
-       if (ret != RESOURCED_ERROR_NONE) {
-               _E("Failed to read leveldb key");
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       if (buf[0] == '\0') {
-               _D("There is no history about %s", key);
-               return RESOURCED_ERROR_NONE;
-       }
-
-       i = 0;
-       num = total_size/sizeof(struct battery_usage);
-       token = strtok_r(buf, " ", &saveptr);
-       if (!token) {
-               _E("Failed to token value");
-               return RESOURCED_ERROR_FAIL;
-       }
-       while (token && i++ < num) {
-               usage[i].start_time = atol(token);
-               token = strtok_r(NULL, " ", &saveptr);
-               if (!token) {
-                       _E("Failed to token value");
-                       return RESOURCED_ERROR_FAIL;
-               }
-               usage[i].sec_per_cap[DISCHARGING] = atol(token);
-               token = strtok_r(NULL, " ", &saveptr);
-               if (!token) {
-                       _E("Failed to token value");
-                       return RESOURCED_ERROR_FAIL;
-               }
-               usage[i].cap_counter[DISCHARGING] = atol(token);
-               token = strtok_r(NULL, " ", &saveptr);
-               if (!token) {
-                       _E("Failed to token value");
-                       return RESOURCED_ERROR_FAIL;
-               }
-               usage[i].sec_per_cap[CHARGING] = atol(token);
-               token = strtok_r(NULL, " ", &saveptr);
-               if (!token) {
-                       _E("Failed to token value");
-                       return RESOURCED_ERROR_FAIL;
-               }
-               usage[i].cap_counter[CHARGING] = atol(token);
-               token = strtok_r(NULL, " ", &saveptr);
-               _D("load [%d] stime: %ld, spc: %ld, count: %ld, spc: %ld, count: %ld",
-                               i, usage[i].start_time, usage[i].sec_per_cap[DISCHARGING],
-                               usage[i].cap_counter[DISCHARGING], usage[i].sec_per_cap[CHARGING],
-                               usage[i].cap_counter[CHARGING]);
-       }
-       return RESOURCED_ERROR_NONE;
-};
-
-static int heart_battery_load_prediction(char *key, struct battery_prediction *prediction)
-{
-       int ret, i;
-       char *token;
-       char buf[BATTERY_DATA_MAX] = {0, };
-       char *saveptr;
-
-       if (!key || !prediction)
-               return RESOURCED_ERROR_FAIL;
-
-       ret = logging_leveldb_read(key, strlen(key), buf, sizeof(buf));
-       if (ret != RESOURCED_ERROR_NONE) {
-               _E("Failed to read leveldb key: %s", key);
-               return RESOURCED_ERROR_FAIL;
-       }
-       token = strtok_r(buf, " ", &saveptr);
-       if (!token) {
-               _E("Failed to token value");
-               return RESOURCED_ERROR_FAIL;
-       }
-       for (i = 0; i < MAX_STRATEGY && token; i++) {
-               prediction[DISCHARGING].sec_per_cap[i] = atol(token);
-               token = strtok_r(NULL, " ", &saveptr);
-               if (!token) {
-                       _E("Failed to token value");
-                       return RESOURCED_ERROR_FAIL;
-               }
-               prediction[DISCHARGING].cap_counter[i] = atol(token);
-               token = strtok_r(NULL, " ", &saveptr);
-               if (!token) {
-                       _E("Failed to token value");
-                       return RESOURCED_ERROR_FAIL;
-               }
-               prediction[DISCHARGING].time_pred_min[i] = atol(token);
-               token = strtok_r(NULL, " ", &saveptr);
-               if (!token) {
-                       _E("Failed to token value");
-                       return RESOURCED_ERROR_FAIL;
-               }
-               prediction[CHARGING].sec_per_cap[i] = atol(token);
-               token = strtok_r(NULL, " ", &saveptr);
-               if (!token) {
-                       _E("Failed to token value");
-                       return RESOURCED_ERROR_FAIL;
-               }
-               prediction[CHARGING].cap_counter[i] = atol(token);
-               token = strtok_r(NULL, " ", &saveptr);
-               if (!token) {
-                       _E("Failed to token value");
-                       return RESOURCED_ERROR_FAIL;
-               }
-               prediction[CHARGING].time_pred_min[i] = atol(token);
-               token = strtok_r(NULL, " ", &saveptr);
-       }
-       return RESOURCED_ERROR_NONE;
-};
-
-static void heart_battery_update_used_time(time_t now, enum charger_status_type status)
-{
-       if (batt_used.last_charger_status == DISCHARGING)
-               batt_used.used_time_sec +=
-                       now - batt_used.last_update_time;
-       batt_used.last_charger_status = status;
-       batt_used.last_update_time = now;
-       heart_battery_save_used_time(BATTERY_USED_TIME, &batt_used);
-}
-
-static int heart_battery_get_capacity_history_size(void)
-{
-       int size, ret;
-
-       ret = pthread_mutex_lock(&heart_battery_mutex);
-       if (ret) {
-               _E("pthread_mutex_lock() failed, %d", ret);
-               return RESOURCED_ERROR_FAIL;
-       }
-       size = g_slist_length(capacity_history_list);
-       if (!size) {
-               _I("capacity history is empty");
-               ret = pthread_mutex_unlock(&heart_battery_mutex);
-               if (ret) {
-                       _E("pthread_mutex_unlock() failed, %d", ret);
-                       return RESOURCED_ERROR_FAIL;
-               }
-               return RESOURCED_ERROR_NONE;
-       }
-       ret = pthread_mutex_unlock(&heart_battery_mutex);
-       if (ret) {
-               _E("pthread_mutex_unlock() failed, %d", ret);
-               return RESOURCED_ERROR_FAIL;
-       }
-       return size;
-}
-
-static void heart_battery_insert_capacity(GSList **history_list, int capacity,
-               int diff_capacity, time_t timestamp, long used_time, long charging_time,
-               enum charger_status_type charger_status, int reset_mark, int clear)
-{
-       static int old_reset_mark = 0;
-       GSList *iter, *next;
-       int ret, count;
-       struct heart_battery_capacity *lbc, *tlbc;
-
-       lbc = malloc(sizeof(struct heart_battery_capacity));
-       if (!lbc) {
-               _E("malloc failed");
-               return;
-       }
-       lbc->capacity = capacity;
-       lbc->diff_capacity = diff_capacity;
-       lbc->used_time = used_time;
-       lbc->charging_time = charging_time;
-       lbc->charger_status = charger_status;
-       lbc->reset_mark = reset_mark;
-       lbc->timestamp = timestamp;
-
-       ret = pthread_mutex_lock(&heart_battery_mutex);
-       if (ret) {
-               _E("pthread_mutex_lock() failed, %d", ret);
-               free(lbc);
-               return;
-       }
-       /* clean all history when reset event */
-       if (clear && *history_list && lbc->reset_mark != old_reset_mark) {
-               g_slist_free_full(*history_list, free);
-               *history_list = NULL;
-       }
-
-       /* history reached maximum limitation number */
-       if (*history_list && g_slist_length(*history_list) > BATTERY_CAPACITY_MAX) {
-               count = 0;
-               gslist_for_each_safe(*history_list, iter, next, tlbc) {
-                       *history_list = g_slist_remove(*history_list, (gpointer)tlbc);
-                       free(tlbc);
-                       if (BATTERY_CLEAN_MAX < count++)
-                               break;
-               }
-       }
-       old_reset_mark = lbc->reset_mark;
-       *history_list = g_slist_append(*history_list, (gpointer)lbc);
-       ret = pthread_mutex_unlock(&heart_battery_mutex);
-       if (ret)
-               _E("pthread_mutex_unlock() failed, %d", ret);
-}
-
-/* ======================== Serialization/Deserialization ==================== */
-
-static void heart_battery_status_save_to_db(void)
-{
-       heart_battery_save_used_time(BATTERY_USED_TIME, &batt_used);
-       heart_battery_save_status(BATTERY_STATUS, &batt_stat);
-
-       heart_battery_save_usage(BATTERY_RESET_USAGE, batt_stat.batt_reset_usage, sizeof(batt_stat.batt_reset_usage));
-       heart_battery_save_usage(BATTERY_WEEK_DAY_USAGE, batt_stat.week_day_usage, sizeof(batt_stat.week_day_usage));
-       heart_battery_save_usage(BATTERY_LEVEL_USAGE, batt_stat.batt_lvl_usage, sizeof(batt_stat.batt_lvl_usage));
-
-       heart_battery_save_prediction(BATTERY_PREDICTION, batt_stat.prediction);
-}
-
-static int heart_battery_status_read_from_db(void)
-{
-       bool ok = true;
-
-       ok &= (RESOURCED_ERROR_NONE == heart_battery_load_used_time(BATTERY_USED_TIME, &batt_used));
-       ok &= (RESOURCED_ERROR_NONE == heart_battery_load_status(BATTERY_STATUS, &batt_stat));
-
-       ok &= (RESOURCED_ERROR_NONE == heart_battery_load_usage(BATTERY_RESET_USAGE, batt_stat.batt_reset_usage, sizeof(batt_stat.batt_reset_usage)));
-       ok &= (RESOURCED_ERROR_NONE == heart_battery_load_usage(BATTERY_WEEK_DAY_USAGE, batt_stat.week_day_usage, sizeof(batt_stat.week_day_usage)));
-       ok &= (RESOURCED_ERROR_NONE == heart_battery_load_usage(BATTERY_LEVEL_USAGE, batt_stat.batt_lvl_usage, sizeof(batt_stat.batt_lvl_usage)));
-
-       ok &= (RESOURCED_ERROR_NONE == heart_battery_load_prediction(BATTERY_PREDICTION, batt_stat.prediction));
-
-       return ok ? RESOURCED_ERROR_NONE : RESOURCED_ERROR_FAIL;
-}
-
-static int heart_battery_capacity_save_to_file(char *filename)
-{
-       int size, ret, count, len = 0;
-       struct heart_battery_capacity *lbc;
-       GSList *iter, *next;
-       FILE *fp;
-       char buf[BATTERY_DATA_MAX] = {0, };
-
-       if (!capacity_history_list) {
-               _E("capacity history is NULL!");
-               return RESOURCED_ERROR_NONE;
-       }
-       ret = pthread_mutex_lock(&heart_battery_mutex);
-       if (ret) {
-               _E("pthread_mutex_lock() failed, %d", ret);
-               return RESOURCED_ERROR_FAIL;
-       }
-       size = g_slist_length(capacity_history_list);
-       if (!size) {
-               _I("capacity history is empty");
-               ret = pthread_mutex_unlock(&heart_battery_mutex);
-               if (ret) {
-                       _E("pthread_mutex_unlock() failed, %d", ret);
-                       return RESOURCED_ERROR_FAIL;
-               }
-               return RESOURCED_ERROR_NONE;
-       }
-       fp = fopen(filename, "w");
-       if (!fp) {
-               _E("%s fopen failed %d", filename, errno);
-               ret = pthread_mutex_unlock(&heart_battery_mutex);
-               if (ret) {
-                       _E("pthread_mutex_unlock() failed, %d", ret);
-                       return RESOURCED_ERROR_FAIL;
-               }
-               return RESOURCED_ERROR_FAIL;
-       }
-       gslist_for_each_item(iter, capacity_history_list) {
-               lbc = (struct heart_battery_capacity *)iter->data;
-               if (!lbc)
-                       break;
-               len += snprintf(buf + len, BATTERY_DATA_MAX - len, "%d %d %ld %ld %ld %d %d\n",
-                               lbc->capacity, lbc->diff_capacity, lbc->timestamp, lbc->used_time,
-                               lbc->charging_time, lbc->charger_status,
-                               lbc->reset_mark);
-               if (BATTERY_DATA_MAX < len + BATTERY_LINE_MAX) {
-                       fputs(buf, fp);
-                       len = 0;
-               }
-       }
-       fputs(buf, fp);
-       fclose(fp);
-       if (BATTERY_CAPACITY_MAX < size) {
-               count = 0;
-               gslist_for_each_safe(capacity_history_list, iter, next, lbc) {
-                       capacity_history_list = g_slist_remove(capacity_history_list, (gpointer)lbc);
-                       free(lbc);
-                       if (BATTERY_CLEAN_MAX < count++)
-                               break;
-               }
-       }
-       ret = pthread_mutex_unlock(&heart_battery_mutex);
-       if (ret) {
-               _E("pthread_mutex_unlock() failed, %d", ret);
-               return RESOURCED_ERROR_FAIL;
-       }
-       return RESOURCED_ERROR_NONE;
-}
-
-static int heart_battery_capacity_read_from_file(char *filename)
-{
-       int len;
-       int capacity, diff_capacity, charger_status, reset_mark;
-       long used_time, charging_time;
-       time_t timestamp;
-       FILE *fp;
-       char buf[BATTERY_DATA_MAX] = {0, };
-       int ret;
-
-       fp = fopen(filename, "r");
-       if (!fp) {
-               if (errno != ENOENT) {
-                       _E("Fail to open %s (%d)", buf, errno);
-                       return RESOURCED_ERROR_FAIL;
-               }
-
-               _D("%s doesn't exist. Make new one.", buf);
-               ret = mkdir(HEART_FILE_PATH, S_IRWXU | S_IRWXG | S_IROTH);
-               if (ret != 0 && errno != EEXIST) {
-                       _E("Fail to create %s (%d)", buf, errno);
-                       return RESOURCED_ERROR_FAIL;
-               }
-
-               fp = fopen(filename, "w+");
-               if (!fp) {
-                       _E("Fail to create %s (%d)", buf, errno);
-                       return RESOURCED_ERROR_FAIL;
-               }
-               fclose(fp);
-               return RESOURCED_ERROR_NONE;
-       }
-
-       while (fgets(buf, BATTERY_DATA_MAX, fp)) {
-               len = sscanf(buf, "%d %d %ld %ld %ld %d %d", &capacity, &diff_capacity,
-                               &timestamp, &used_time, &charging_time,
-                               &charger_status, &reset_mark);
-               if (len < 0) {
-                       _E("sscanf failed");
-                       fclose(fp);
-                       return RESOURCED_ERROR_FAIL;
-               }
-               heart_battery_insert_capacity(&capacity_history_list, capacity, diff_capacity,
-                               timestamp, used_time, charging_time,
-                               charger_status, reset_mark, true);
-       }
-       fclose(fp);
-       return RESOURCED_ERROR_NONE;
-}
-
-/* ==================== Serialization/Deserialization END ==================== */
-
-static void heart_battery_save_to_file(bool force)
-{
-       int ret;
-       time_t now = logging_get_time(CLOCK_BOOTTIME);
-
-       heart_battery_update_used_time(now, batt_stat.curr_charger_status);
-
-       if (!force &&
-           heart_battery_get_file_commit_timestamp() + HEART_BATTERY_SAVE_INTERVAL >= now)
-               return;
-
-       heart_battery_status_save_to_db();
-
-       ret = heart_battery_capacity_save_to_file(HEART_BATTERY_CAPACITY_DATA_FILE);
-       if (ret)
-               _E("failed to save capacity file");
-       heart_battery_set_file_commit_timestamp(now);
-}
-
-/*
- * This function will open the '.battery_data.dat' file and write all battery
- * related data into it.
- */
-static void heart_battery_write_data_to_file(void)
-{
-       int i;
-       int len = 0;
-       char buff[BATTERY_DATA_MAX] = {0, 0};
-       _cleanup_fclose_ FILE *fp = NULL;
-
-       fp = fopen(HEART_BATTERY_DATA_FILE, "w");
-       if (fp == NULL) {
-               _E("Could not open file battery_data file\n");
-               return;
-       }
-
-       for (i = 0; i < INDEX_WINDOW_SIZE; i++) {
-               len += snprintf(buff + len, BATTERY_DATA_MAX - len, "%ld %lf\n", \
-                       batt_stat.last_wall_time[i], batt_stat.last_volt_intg[i]);
-
-               if (BATTERY_DATA_MAX < len + BATTERY_LINE_MAX) {
-                       fputs(buff, fp);
-                       len = 0;
-               }
-       }
-       len += snprintf(buff + len, BATTERY_DATA_MAX - len, "%d %d %d %d %lf %d", \
-               batt_stat.curr_index, batt_stat.last_capacity, batt_stat.remaining_time, \
-               batt_stat.remaining_time_ups, batt_stat.last_pwr_bchg, batt_stat.data_available);
-
-       fputs(buff, fp);
-}
-
-/*
- * This function will open the '.battery_data.dat' file and read all battery
- * related data from it and store in variable 'batt_stat'
- */
-static void heart_battery_read_data_from_file(void)
-{
-       int i;
-       int len = 0;
-       char buff[BATTERY_DATA_MAX] = {0, 0};
-       char *ch;
-       _cleanup_fclose_ FILE *fp = NULL;
-
-       fp = fopen(HEART_BATTERY_DATA_FILE, "r");
-       if (fp == NULL) {
-               _E("Could not open battery_data file\n");
-               return;
-       }
-
-       for (i = 0; i < INDEX_WINDOW_SIZE; i++) {
-               ch = fgets(buff, BATTERY_DATA_MAX, fp);
-               if (ch == NULL)
-                       /*if file is empty then return from here */
-                       return;
-
-               len += sscanf(buff, "%ld %lf", \
-                               &batt_stat.last_wall_time[i], &batt_stat.last_volt_intg[i]);
-       }
-
-       ch = fgets(buff, BATTERY_DATA_MAX, fp);
-       if (ch != NULL)
-               len += sscanf(buff, "%d %d %d %d %lf %d", \
-                       &batt_stat.curr_index, &batt_stat.last_capacity, &batt_stat.remaining_time, \
-                       &batt_stat.remaining_time_ups, &batt_stat.last_pwr_bchg, &batt_stat.data_available);
-}
-
-/*
- * This function will reject all the battery related data which were stored earlier
- */
-static void heart_battery_reject_data(void)
-{
-       int i;
-
-       for (i = 0; i < INDEX_WINDOW_SIZE; i++) {
-               batt_stat.last_wall_time[i] = 0;
-               batt_stat.last_volt_intg[i] = 0.0;
-       }
-
-       /* Do not reject this, once data available, do not change untill next binary flash */
-       /*batt_stat.data_available = 0;   */
-       batt_stat.last_capacity = 0;
-       batt_stat.curr_index = 0;
-       batt_stat.remaining_time = 0;
-       batt_stat.remaining_time_ups = 0;
-       /* do not flush this value. When proper power value is not present, previously
-       calculated power only will be used. */
-       /*batt_stat.last_pwr_bchg = 0.0;  */
-
-       heart_battery_write_data_to_file();
-}
-
-/*
- * This function will calculate the voltage integral(energy) at battery level 100.
- * We will calculate Pivot using fast discharge and slow discharge rate for
- * estimating the battery time in normal mode
- */
-static void heart_battery_calculate_pivot(void)
-{
-       int i;
-
-       for (i = 0; i < ocv_degree; i++)
-               volt_intg_full += (intg[i] /(i+1)) * pow(100 , i+1);
-       volt_intg_full = volt_intg_full/100000.0;
-
-       pivot_nor = ((sqrt(discharge_fast) + sqrt(discharge_slow))/2);
-       pivot_nor = pivot_nor * pivot_nor; // taking square of Tpivot
-
-       pivot_ups = ((sqrt(discharge_fast*UPS_FACTOR) + sqrt(discharge_slow*UPS_FACTOR))/2);
-       pivot_ups = pivot_ups * pivot_ups; // taking square of Tpivot
-}
-
-/* function to return the time(in seconds) since the  Epoch*/
-static long heart_battery_logging_get_time_sec_new(void)
-{
-       struct timeval tv;
-
-       gettimeofday(&tv, NULL);
-
-       return (tv.tv_sec + tv.tv_usec / 1000000);
-}
-
-/*
- * This function will read the current time and will compare with previously stored time.
- * If time difference is more then it is assumed that device was powered off and it will
- * adjust all stored time values
- */
-static void heart_battery_power_off_time_adjustment(void)
-{
-       int i;
-       int index;
-       int clock_tick_diff = 0;
-       long int curr_time;
-       long int time_diff = 0;
-
-       curr_time = heart_battery_logging_get_time_sec_new();
-
-       index = BATTERY_WINDOW_INDEX(batt_stat.curr_index - 1);
-       if (batt_stat.last_wall_time[index] == 0)
-               index = 0;
-
-       clock_tick_diff = logging_get_time(CLOCK_BOOTTIME) - batt_stat.last_clock_tick;
-
-       /* check if we have store last time value or not */
-       if (batt_stat.last_wall_time[index] != 0) {
-               time_diff = curr_time - batt_stat.last_wall_time[index];
-               time_diff -= clock_tick_diff;
-       }
-
-       _I("All store time value will be scaled up by %ld secs\n", time_diff);
-
-       /*scale up all stored time value */
-       for (i = 0; i < INDEX_WINDOW_SIZE; i++) {
-               if (batt_stat.last_wall_time[i] == 0) {
-                       /* we do not have stored time value from this point onwards, stop updating*/
-                       break;
-               } else
-                       batt_stat.last_wall_time[i] += time_diff;
-       }
-
-       /* update same value in battery data file*/
-       heart_battery_write_data_to_file();
-
-       /*
-        * during charge time
-        */
-       time_diff = curr_time - batt_stat.last_wall_time_chg;
-       time_diff -= clock_tick_diff;
-       /*
-         * update last_wall_time_chg as per previous and new time diff
-         * it will take care of positive of negative difference
-         */
-       batt_stat.last_wall_time_chg += time_diff;
-       _I("last_wall_time_chg got updated by %ld\n", time_diff);
-       /*
-         * make first_level_change as TRUE so that charge remaining time
-         * should not vary much
-         */
-       first_level_change = TRUE;
-
-       /* for pivot data */
-       if (batt_stat.pvt.start_time_dischg != 0) {
-               time_diff = curr_time - batt_stat.pvt.start_time_dischg;
-               clock_tick_diff = logging_get_time(CLOCK_BOOTTIME) - batt_stat.pvt.last_clock_tick;
-               time_diff -= clock_tick_diff;
-               batt_stat.pvt.start_time_dischg += time_diff;
-       }
-}
-
-/*
- * In case of any time change in the device, this callback get called and it
- * will do the time adjustment
- */
-static void time_change_notify_cb(keynode_t *key, void *data)
-{
-       heart_battery_power_off_time_adjustment();
-}
-
-static int get_battery_remaining_time_new(void)
-{
-       return batt_stat.remaining_time;
-}
-
-static int get_battery_remaining_time_ups()
-{
-       return batt_stat.remaining_time_ups;
-}
-
-/*
- * This function will return the average of stored time diff values
- */
-static int heart_battery_get_time_diff_avg(int time_diff_avg)
-{
-       int temp_index;
-       int i;
-
-       if (data_avail_chg == true) {
-               /*
-                * calculate the average of last 5(including current) time diff values
-                */
-               temp_index = ((batt_stat.index_chg-1) + BATTERY_LEVEL_GAP) % BATTERY_LEVEL_GAP;
-               for (i = 1; i < BATTERY_LEVEL_GAP; i++) {
-                       time_diff_avg += batt_stat.last_wall_time_chg_diff[temp_index];
-                       temp_index = ((temp_index-1) + BATTERY_LEVEL_GAP) % BATTERY_LEVEL_GAP;
-               }
-               time_diff_avg = time_diff_avg/BATTERY_LEVEL_GAP;
-       } else {
-               /*
-                * take average of only available data. Do not include 1st value so
-                * i stared from 1.
-                */
-               for (i = 1; i < batt_stat.index_chg; i++)
-                       time_diff_avg += batt_stat.last_wall_time_chg_diff[i];
-
-               time_diff_avg = time_diff_avg/i;
-       }
-       /*
-        * to minimize the time diff fluctuation
-        */
-       time_diff_avg = (time_diff_avg+BATTERY_C_RATE)/2;
-       _I("time_diff after averaging= %d seconds\n", time_diff_avg);
-
-       return time_diff_avg;
-}
-
-/*
- * This function will return the time diff between last and current battery
- * level change
- */
-int heart_battery_get_time_diff(long curr_wall_time)
-{
-       if (batt_stat.last_wall_time_chg == 0)
-               /*
-                * First time estimation
-                * In this case charge rate will be considered as time diff
-                */
-               return BATTERY_C_RATE;
-
-       return (curr_wall_time - batt_stat.last_wall_time_chg);
-}
-
-static void heart_battery_print_prev_charge_data(void)
-{
-       int i;
-
-       _I("Charging stored data, current index = %d", batt_stat.index_chg);
-
-       for (i = 0; i < BATTERY_LEVEL_GAP; i++)
-               _I("Index = %d, time_diff = %d", i, batt_stat.last_wall_time_chg_diff[i]);
-}
-
-/*
- * This function will flush the stored charge data
- */
-static void heart_battery_flush_charge_data(void)
-{
-       int i;
-
-        _I("Prev and curr battery lvl gap = %d, flush charge data",
-               batt_stat.last_capacity_chg - batt_stat.curr_capacity);
-
-        for (i = 0; i < BATTERY_LEVEL_GAP; i++)
-               batt_stat.last_wall_time_chg_diff[i] = 0;
-
-        batt_stat.last_wall_time_chg = 0;
-        batt_stat.index_chg = 0;
-        data_avail_chg = false;
-}
-
-/*
- * store the discharge start time and capacity to calculte the
- * time taken for the discharge period
- */
-static void heart_battery_collect_discharge_data(void)
-{
-       batt_stat.pvt.start_cap_dischg = batt_stat.curr_capacity;
-       batt_stat.pvt.start_time_dischg = heart_battery_logging_get_time_sec_new();
-       batt_stat.pvt.last_clock_tick = logging_get_time(CLOCK_BOOTTIME);
-}
-
-/*
- * Read all the stored pivot data from file and keep it in
- * local variable batt_stat.pvt
- */
-static void heart_battery_read_pivot_info_from_file(void)
-{
-       int i;
-       char buf[BATTERY_DATA_MAX] = {0, };
-       char *p;
-       _cleanup_fclose_ FILE *fp = NULL;
-
-       fp = fopen(HEART_BATTERY_PIVOT_INFO, "r");
-       if (fp == NULL) {
-               _E("Could not open pivot info file");
-               return;
-       }
-
-       for (i = 0; i < INDEX_WINDOW_SIZE; i++) {
-               p = fgets(buf, BATTERY_DATA_MAX, fp);
-               if (p == NULL)
-                       return;
-
-               if (sscanf(buf, "%d", &batt_stat.pvt.total_dischg_time[i]) == -1)
-                       return;
-       }
-
-       p = fgets(buf, BATTERY_DATA_MAX, fp);
-       if (!p)
-               return;
-       if (sscanf(buf, "%d", &batt_stat.pvt.pvt_data_ind) == -1)
-               return;
-
-}
-
-/*
- * Store all the local  pivot data to a file
- */
-static void heart_battery_save_pivot_info(void)
-{
-       int len = 0;
-       int i;
-       char buf[BATTERY_DATA_MAX] = {0, };
-       _cleanup_fclose_ FILE *fp = NULL;
-
-       fp = fopen(HEART_BATTERY_PIVOT_INFO, "w");
-       if (fp == NULL) {
-               _E("Could not open pivot info file");
-               return;
-       }
-
-       for (i = 0; i < INDEX_WINDOW_SIZE; i++) {
-               len += snprintf(buf + len, BATTERY_DATA_MAX - len, "%d\n",
-                               batt_stat.pvt.total_dischg_time[i]);
-
-               if (BATTERY_DATA_MAX < len + BATTERY_LINE_MAX) {
-                       fputs(buf, fp);
-                       len = 0;
-               }
-       }
-       len += snprintf(buf + len, BATTERY_DATA_MAX - len, "%d",
-                       batt_stat.pvt.pvt_data_ind);
-
-       fputs(buf, fp);
-}
-
-/*
- * Calculate the remaining enery in battery based on current capacity
- */
-static double heart_battery_get_energy(int capacity)
-{
-       int i;
-       double volt_intg = 0;
-
-       for (i = 0; i < ocv_degree; i++)
-               volt_intg += (intg[i] /(i+1)) * pow(capacity , i+1);
-
-       return (volt_intg /100000.0);
-}
-
-/*
- * Update the pivot based on device learning data
- */
-static void heart_battery_update_pivot(void)
-{
-       int i;
-       int avg = 0;
-
-       static int count = 1;
-
-       for (i = 0; i < INDEX_WINDOW_SIZE; i++) {
-               if(batt_stat.pvt.total_dischg_time[i] == 0)
-                       break;
-               avg += batt_stat.pvt.total_dischg_time[i];
-       }
-
-       if (avg == 0)
-               return;
-       if (i != 0)
-               avg = (avg  / i);
-
-       /*
-        * Total 10 discharge cycle data will be stored and based on those values
-        * new pivot will be calculted. Untill 10 cycles data are not available, take
-        * count/10 % from new pivot and 1-count/10 % from existing pivot. By
-        * doing this, sudden jump in pivot can be avoided
-        */
-       if (count <= 10) {
-               avg = NEW_PIVOT_WEIGHTAGE(count) * avg + OLD_PIVOT_WEIGHTAGE(count) * pivot_nor;
-               count++;
-       }
-
-       _I("Old pivot = %lf, New pivot =%d, count = %d", pivot_nor, avg, count);
-
-       pivot_nor = avg;
-       pivot_ups = pivot_nor * UPS_FACTOR;
-}
-
-/*
- * This function will take the average of last 10 discharge time period and
- * update the pivot
- */
-static void heart_battery_collect_pivot_info(void)
-{
-       long curr_time;
-       int time_diff;
-       int cap_diff;
-       int total_time;
-
-       double energy_dis;
-       double energy_chg;
-       double energy_total;
-
-       if (batt_stat.pvt.start_time_dischg == 0)
-               return;
-
-       curr_time = heart_battery_logging_get_time_sec_new();
-       time_diff = curr_time - batt_stat.pvt.start_time_dischg;
-       cap_diff = batt_stat.pvt.start_cap_dischg - batt_stat.curr_capacity;
-
-       /* discharge period is too less so do not consider this period */
-       if (cap_diff < MIN_DISCHARGE_PERIOD)
-               return;
-
-       energy_dis = heart_battery_get_energy(batt_stat.pvt.start_cap_dischg);
-       energy_chg = heart_battery_get_energy(batt_stat.curr_capacity);
-       energy_total = heart_battery_get_energy(FULL_CAPACITY);
-
-       total_time = (energy_total * time_diff) /(energy_dis - energy_chg);
-
-       _I("Energy discharge = %lf, Energy charge = %lf, Energy Total = %lf, Total time = %d",
-                               energy_dis, energy_chg, energy_total, total_time);
-
-       batt_stat.pvt.total_dischg_time[batt_stat.pvt.pvt_data_ind] = SEC_TO_MIN(total_time);
-       batt_stat.pvt.pvt_data_ind = (batt_stat.pvt.pvt_data_ind + 1) % INDEX_WINDOW_SIZE;
-
-       /* update the pivot */
-       heart_battery_update_pivot();
-       /* save pivot info into file */
-       heart_battery_save_pivot_info();
-}
-
-/*
- * This function will calculate the battery charging remaining time
- */
-static void heart_battery_cal_charging_rem_time(void)
-{
-       long curr_wall_time = 0;
-       int rem_time;
-       int time_diff;
-       int time_diff_avg;
-       double temp_cv;
-
-       if (batt_stat.last_capacity_chg == batt_stat.curr_capacity) {
-               _I("Last capacity %d is same as current capacity %d\n",
-                       batt_stat.last_capacity_chg, batt_stat.curr_capacity);
-               return;
-       }
-
-       curr_wall_time = heart_battery_logging_get_time_sec_new();
-
-       time_diff = heart_battery_get_time_diff(curr_wall_time);
-
-       /*
-        * just after inserting the charger, if time diff between two level
-        * is less than MIN_TIME_FOR_LVL_CHANGE value then consider time diff
-        * as BATTERY_C_RATE so that there will not be sudden fall in charge
-        * remaining time
-        */
-       if (time_diff < MIN_TIME_FOR_LVL_CHANGE && first_level_change == TRUE) {
-               /*
-                * first_level_change will be set to TRUE in function
-                * heart_battery_charger_status() and set to FALSE in function
-                * heart_battery_capacity_status()
-                */
-               _I("time diff %d is less than min value of lvl change %d\n",
-                       time_diff, MIN_TIME_FOR_LVL_CHANGE);
-               time_diff = BATTERY_C_RATE;
-       }
-
-       _I("data_avail_chg = %d, index_chg = %d\n",
-               data_avail_chg, batt_stat.index_chg);
-       _I("last_wall_time_chg = %ld, curr_wall_time = %ld\n",
-               batt_stat.last_wall_time_chg, curr_wall_time);
-       _I("time diff before averaging = %d seconds\n", time_diff);
-
-       /*
-        * get the average of all time diff values stored including current
-        */
-       time_diff_avg = heart_battery_get_time_diff_avg(time_diff);
-
-       if (time_diff_avg > BATTERY_C_RATE && batt_stat.curr_capacity <= 30)
-               time_diff_avg = BATTERY_C_RATE;
-
-       if (batt_stat.curr_capacity == FULL_CAPACITY) {
-               batt_stat.remaining_time_chg = 0;
-       } else {
-               /*
-                * calculate the remaining charge time based on constant current
-                * and constant votlage(CCCV) logic. 'time_diff_avg' is for CC and
-                * 'temp_cv' is for CV part.
-                */
-               temp_cv = ((double)time_diff_avg)/((double)BATTERY_C_RATE);
-               temp_cv = temp_cv * temp_cv;
-               rem_time = (time_diff_avg + temp_cv)*(FULL_CAPACITY - batt_stat.curr_capacity);
-               batt_stat.remaining_time_chg = SEC_TO_MIN(rem_time);
-       }
-
-       batt_stat.last_wall_time_chg = curr_wall_time;
-       batt_stat.last_wall_time_chg_diff[batt_stat.index_chg] = time_diff;
-       batt_stat.index_chg = (batt_stat.index_chg+1)%BATTERY_LEVEL_GAP;
-       batt_stat.last_capacity_chg = batt_stat.curr_capacity;
-       batt_stat.last_clock_tick =  logging_get_time(CLOCK_BOOTTIME);
-
-       _I("Capacity = %d, charging remaining time = %d minutes\n",
-               batt_stat.curr_capacity, batt_stat.remaining_time_chg);
-
-       if (batt_stat.index_chg+1 == BATTERY_LEVEL_GAP)
-               data_avail_chg = true;
-}
-
-/*
- * This function will calculate the battery estimation time for every battery
- * level change
- */
-static void heart_battery_cal_discharge_rem_time(void)
-{
-       double curr_volt_intg = 0;
-       double volt_intg_diff = 0;
-       double ps, pt;
-       double batt_pwr;
-       int rem_time = 0;
-       int index = 0;
-       int temp_index = 0;
-       int index_count;
-       int i;
-       int update_time;
-       long curr_wall_time = 0;
-       long time_diff1, time_diff2;
-
-       _I("last capacity = %d, current capacity = %d\n", batt_stat.last_capacity, batt_stat.curr_capacity);
-
-       /* if battery level change happen then only calculate the new time*/
-       if (batt_stat.last_capacity != batt_stat.curr_capacity) {
-               /* calculate the voltage integral(energy) for current capacity */
-               for (i = 0; i < ocv_degree; i++)
-                       curr_volt_intg += (intg[i] /(i+1)) * pow(batt_stat.curr_capacity , i+1);
-               curr_volt_intg = curr_volt_intg /100000.0;
-
-               /*current time*/
-               curr_wall_time = heart_battery_logging_get_time_sec_new();
-
-               _I("curr_volt_intg = %lf, curr_wall_time = %ld\n", curr_volt_intg, curr_wall_time);
-
-               if (batt_stat.last_capacity < batt_stat.curr_capacity) {
-                       /*
-                        *this indicates that device was put for charging so need to reject
-                        *all the previous data except 'batt_stat.data_available' and
-                        *'batt_stat.last_pwr_bchg'. Use last available battery power
-                        *before connecting the charger as current average power.
-                        */
-                       batt_pwr = batt_stat.last_pwr_bchg;
-                       heart_battery_reject_data();
-               } else {
-                       index = BATTERY_WINDOW_INDEX(batt_stat.curr_index - BATTERY_LEVEL_GAP);
-                       if (batt_stat.last_wall_time[index] == 0 &&
-                               batt_stat.last_volt_intg[index] == 0) {
-                               /*
-                                *do not have enough previous data so take 1st stored data
-                                *as reference
-                                */
-                               time_diff1 = curr_wall_time - batt_stat.last_wall_time[0];
-                               volt_intg_diff = batt_stat.last_volt_intg[0] - curr_volt_intg;
-                               if (volt_intg_diff < DOUBLE_ZERO)
-                                       volt_intg_diff = volt_intg_full - curr_volt_intg;
-                       } else {
-                               /* time differenc since last battery level change*/
-                               time_diff1 = curr_wall_time - batt_stat.last_wall_time[index];
-                               /* voltage integral(energy) change since last battery level change */
-                               volt_intg_diff = batt_stat.last_volt_intg[index] - curr_volt_intg;
-                       }
-                       _I("time_diff1 = %ld, volt_intg_diff = %lf\n", time_diff1, volt_intg_diff);
-
-                       time_diff1 = SEC_TO_MIN(time_diff1); /*convert second to minute */
-
-                       /* calculate short term average power component*/
-                       if (time_diff1 != 0)
-                               ps = (total_battery_capacity *volt_intg_diff) / time_diff1;
-                       else
-                               ps = 0;
-
-                       _I("ps = %lf\n", ps);
-
-                       /* find the voltage integral(energy) of 1 hr back battery level.
-                       1. Place the index at proper location
-                       2. get the time stored at that index
-                       3. if difference between last time and current time is >= 60 then take that voltage integral
-                       */
-                       index_count = INDEX_WINDOW_SIZE;
-                       time_diff2 = 0;
-                       temp_index = BATTERY_WINDOW_INDEX(batt_stat.curr_index - 1);
-                       while ((index_count > 0) && (time_diff2 < 60)) {
-                               if  (batt_stat.last_wall_time[temp_index] == 0)
-                                       /* data not available so break the loop */
-                                       break;
-
-                               time_diff2 = SEC_TO_MIN(curr_wall_time - batt_stat.last_wall_time[temp_index]);
-                               temp_index = BATTERY_WINDOW_INDEX(temp_index - 1);
-                               index_count--;
-                       }
-
-                       /* calculate long term average power component*/
-                       if (time_diff2 < 60) {
-                               pt = 0;
-                       } else {
-                               temp_index = BATTERY_WINDOW_INDEX(temp_index + 1);
-                               volt_intg_diff = batt_stat.last_volt_intg[temp_index] - curr_volt_intg ;
-                               if (volt_intg_diff < DOUBLE_ZERO)
-                                       pt = 0;
-                               else
-                                       pt = (total_battery_capacity  * volt_intg_diff) / time_diff2;
-                       }
-
-                       _I("time_diff2 = %ld, volt_intg_diff = %lf, pt = %lf\n", time_diff2, volt_intg_diff, pt);
-
-                       /* calculate the average power from the short component and long component*/
-                       if ((pt + ps) != 0)
-                               batt_pwr = (((pt  * pt) + (ps * ps)) / (pt + ps));
-                       else
-                               batt_pwr = batt_stat.last_pwr_bchg;
-               }
-
-               /* total remaining time based on current battery level*/
-               rem_time = (total_battery_capacity * curr_volt_intg) / batt_pwr;
-
-               _I("pivot_nor = %lf, curr_volt_intg = %lf , volt_intg_full %lf, batt_pwr = %lf", pivot_nor, curr_volt_intg, volt_intg_full, batt_pwr);
-
-               /* calculate remaining time for normal mode */
-               update_time = (pivot_nor * curr_volt_intg) / volt_intg_full;
-               batt_stat.remaining_time = (LONG_TIME_WEIGHT * update_time + SHORT_TIME_WEIGHT * CAL_MIN(update_time, rem_time));
-
-                /* calculate remaining time for UPS mode */
-               update_time = (pivot_ups * curr_volt_intg) / volt_intg_full;
-               batt_stat.remaining_time_ups = (LONG_TIME_WEIGHT * update_time + SHORT_TIME_WEIGHT * CAL_MIN(update_time, rem_time));
-
-               _I("normal mode remaining time = %d minutes, ups remaining time = %d minutes\n",
-                       batt_stat.remaining_time, batt_stat.remaining_time_ups);
-
-               batt_stat.last_volt_intg[batt_stat.curr_index] = curr_volt_intg;
-               batt_stat.last_wall_time[batt_stat.curr_index] = curr_wall_time;
-               batt_stat.last_capacity = batt_stat.curr_capacity;
-               batt_stat.curr_index = (batt_stat.curr_index + 1) % INDEX_WINDOW_SIZE;
-               batt_stat.last_clock_tick =  logging_get_time(CLOCK_BOOTTIME);
-
-               if (batt_pwr > DOUBLE_ZERO) {
-                       /*
-                        *when battery percentage is 0 then available power will be 0 so
-                        *do not store this value. keep previous value only.
-                        */
-                       batt_stat.last_pwr_bchg = batt_pwr;
-               }
-
-               if (batt_stat.curr_index > BATTERY_LEVEL_GAP) {
-                       /*
-                        *When enough data to estimate the available battery time are
-                        *stored, no need to update the status of batt_stat. data_available
-                        *untill we are flashing new binary.
-                        */
-                       batt_stat.data_available = TRUE;
-               }
-
-               /* save all calculated battery data to file*/
-               heart_battery_write_data_to_file();
-       }
-}
-
-void heart_battery_update(struct logging_table_form *data, void *user_data)
-{
-       heart_battery_save_to_file(false);
-}
-
-static int heart_battery_get_level_usage_index(int capacity)
-{
-       return (capacity > 49) ? BATTERY_LEVEL_HIGH :
-               (capacity < 16) ? BATTERY_LEVEL_LOW : BATTERY_LEVEL_MID;
-}
-
-static int heart_battery_get_week_day_usage_index(time_t timestamp)
-{
-       int i;
-
-       for (i = 0; i < BATTERY_HISTORY_DAY_MAX; i++) {
-               if (!heart_battery_get_usage_week_stime(i))
-                       return i;
-               else if (abs(timestamp - heart_battery_get_usage_week_stime(i)) < DAY_TO_SEC(1))
-                       return i;
-       }
-       for (i = 0; i < BATTERY_HISTORY_DAY_MAX - 1; i++) {
-               batt_stat.week_day_usage[i].start_time =
-                       batt_stat.week_day_usage[i + 1].start_time;
-               batt_stat.week_day_usage[i].sec_per_cap[DISCHARGING] =
-                       batt_stat.week_day_usage[i + 1].sec_per_cap[DISCHARGING];
-               batt_stat.week_day_usage[i].sec_per_cap[CHARGING] =
-                       batt_stat.week_day_usage[i + 1].sec_per_cap[CHARGING];
-               batt_stat.week_day_usage[i].cap_counter[DISCHARGING] =
-                       batt_stat.week_day_usage[i + 1].cap_counter[DISCHARGING];
-               batt_stat.week_day_usage[i].cap_counter[CHARGING] =
-                       batt_stat.week_day_usage[i + 1].cap_counter[CHARGING];
-       }
-       return BATTERY_HISTORY_DAY_MAX - 1;
-}
-
-static int heart_battery_get_batt_reset_usage_index(void)
-{
-       int i;
-
-       for (i = 0; i < BATTERY_HISTORY_RESET_MAX; i++) {
-               if (heart_battery_get_usage_reset_count(i, DISCHARGING) < BATTERY_HISTORY_COUNT_MAX
-                       && heart_battery_get_usage_reset_count(i, CHARGING) < BATTERY_HISTORY_COUNT_MAX)
-                       return i;
-       }
-       for (i = 0; i < BATTERY_HISTORY_RESET_MAX - 1; i++) {
-               batt_stat.batt_reset_usage[i].start_time =
-                       batt_stat.batt_reset_usage[i + 1].start_time;
-               batt_stat.batt_reset_usage[i].sec_per_cap[DISCHARGING] =
-                       batt_stat.batt_reset_usage[i + 1].sec_per_cap[DISCHARGING];
-               batt_stat.batt_reset_usage[i].sec_per_cap[CHARGING] =
-                       batt_stat.batt_reset_usage[i + 1].sec_per_cap[CHARGING];
-               batt_stat.batt_reset_usage[i].cap_counter[DISCHARGING] =
-                       batt_stat.batt_reset_usage[i + 1].cap_counter[DISCHARGING];
-               batt_stat.batt_reset_usage[i].cap_counter[CHARGING] =
-                       batt_stat.batt_reset_usage[i + 1].cap_counter[CHARGING];
-       }
-       return BATTERY_HISTORY_RESET_CURRENT;
-}
-
-static int heart_battery_reset(void *data)
-{
-       int idx;
-       long total_time, total_count, sec_per_cap;
-
-       idx = heart_battery_get_batt_reset_usage_index();
-
-       /* DISCHARGING */
-       total_time = 0; total_count = 0;
-       total_time = heart_battery_get_usage_reset_total_time(idx, DISCHARGING) + batt_stat.curr_run_time_sec[DISCHARGING];
-       total_count = heart_battery_get_usage_reset_count(idx, DISCHARGING) + batt_stat.curr_cap_counter[DISCHARGING];
-
-       if (total_time && total_count) {
-               sec_per_cap = total_time / total_count;
-               if (sec_per_cap < default_sec_per_cap[DISCHARGING][DEFAULT_MIN])
-                       sec_per_cap = default_sec_per_cap[DISCHARGING][DEFAULT_MIN];
-               else if (sec_per_cap > default_sec_per_cap[DISCHARGING][DEFAULT_MAX])
-                       sec_per_cap = default_sec_per_cap[DISCHARGING][DEFAULT_MAX];
-               heart_battery_set_usage_reset(idx, DISCHARGING, sec_per_cap, total_count);
-       }
-       /* CHARGING */
-       total_time = 0; total_count = 0;
-       total_time = heart_battery_get_usage_reset_total_time(idx, CHARGING)
-               + batt_stat.curr_run_time_sec[CHARGING];
-       total_count = heart_battery_get_usage_reset_count(idx, CHARGING) + batt_stat.curr_cap_counter[CHARGING];
-
-       if (total_time && total_count) {
-               sec_per_cap = total_time / total_count;
-               if (sec_per_cap < default_sec_per_cap[CHARGING][DEFAULT_MIN])
-                       sec_per_cap = default_sec_per_cap[CHARGING][DEFAULT_MIN];
-               else if (sec_per_cap > default_sec_per_cap[CHARGING][DEFAULT_MAX])
-                       sec_per_cap = default_sec_per_cap[CHARGING][DEFAULT_MAX];
-               heart_battery_set_usage_reset(idx, CHARGING, sec_per_cap, total_count);
-       }
-
-       batt_stat.reset_mark = batt_stat.reset_mark ? 0 : 1; /* Swap reset_mark */
-       batt_stat.reset_mark_timestamp = time(NULL);
-       batt_stat.curr_run_time_sec[DISCHARGING] = 0;
-       batt_stat.curr_run_time_sec[CHARGING] = 0;
-       batt_stat.curr_cap_counter[DISCHARGING] = 0;
-       batt_stat.curr_cap_counter[CHARGING] = 0;
-       batt_used.used_time_sec = 0;
-       batt_used.last_update_time = logging_get_time(CLOCK_BOOTTIME);
-
-       return RESOURCED_ERROR_NONE;
-}
-
-static long heart_battery_compute_remaining_time_in_min(int capacity_count, long sec_per_cap)
-{
-       /*
-        * Calculates and returns remaining time in minutes based on number
-        * of capacity changes and time needed for one change.
-        */
-       long time;
-
-       time = (capacity_count * sec_per_cap); /* seconds */
-       time = time + 30; /* add 30s margin */
-       time = time / 60; /* change to minutes */
-       return time;
-}
-
-static void heart_battery_calculate_prediction(enum charger_status_type goal)
-{
-       int i, capacity, level;
-       long total_time, total_count, sec_per_cap, pred_min;
-       long low_count, mid_count, high_count;
-       struct heart_battery_capacity *lbc = NULL;
-       GArray *arrays = NULL;
-
-       if (goal == CHARGING)
-               capacity = REMAIN_CAPACITY(batt_stat.curr_capacity);
-       else {
-               capacity = batt_stat.curr_capacity;
-
-               if (goal != DISCHARGING) {
-                       _E("Wrong charging status is written. Suppose discharging");
-                       goal = DISCHARGING;
-               }
-       }
-
-       /* PREDICTION METHOD: total average */
-       total_time = 0;
-       total_count = 0;
-       for (i = 0; i < BATTERY_HISTORY_RESET_MAX; i++) {
-               total_time += heart_battery_get_usage_reset_total_time(i, goal);
-               total_count += heart_battery_get_usage_reset_count(i, goal);
-       }
-       total_time += batt_stat.curr_run_time_sec[goal];
-       total_count += batt_stat.curr_cap_counter[goal];
-
-       if (total_time && total_count >= BATTERY_PREDICTION_DATA_MIN) {
-               sec_per_cap = total_time / total_count;
-               if (sec_per_cap < default_sec_per_cap[goal][DEFAULT_MIN])
-                       sec_per_cap = default_sec_per_cap[goal][DEFAULT_MIN];
-               else if (sec_per_cap > default_sec_per_cap[goal][DEFAULT_MAX])
-                       sec_per_cap = default_sec_per_cap[goal][DEFAULT_MAX];
-               pred_min = heart_battery_compute_remaining_time_in_min(capacity, sec_per_cap);
-               heart_battery_set_prediction(TA, goal,
-                               sec_per_cap, total_count,
-                               pred_min);
-       } else {
-               heart_battery_set_prediction(TA, goal, 0, 0, 0);
-       }
-
-
-       /* PREDICTION METHOD:
-        * Prediction of battery remaining usage time
-        * considering users' psychological usage patterns
-        * by batt_lvl_usage of battery charge
-        * */
-       pred_min = 0;
-       sec_per_cap = 0;
-       level = heart_battery_get_level_usage_index(capacity);
-       low_count = heart_battery_get_usage_level_count(BATTERY_LEVEL_LOW, goal);
-       mid_count = heart_battery_get_usage_level_count(BATTERY_LEVEL_MID, goal);
-       high_count = heart_battery_get_usage_level_count(BATTERY_LEVEL_HIGH, goal);
-
-       if (level == BATTERY_LEVEL_LOW && low_count) {
-               sec_per_cap = heart_battery_get_usage_level_spc(BATTERY_LEVEL_LOW, goal);
-               pred_min = heart_battery_compute_remaining_time_in_min(capacity, sec_per_cap);
-       } else if (level == BATTERY_LEVEL_MID && low_count && mid_count) {
-               sec_per_cap = heart_battery_get_usage_level_spc(BATTERY_LEVEL_LOW, goal);
-               pred_min = heart_battery_compute_remaining_time_in_min(15, sec_per_cap);
-               sec_per_cap = heart_battery_get_usage_level_spc(BATTERY_LEVEL_MID, goal);
-               pred_min +=
-               heart_battery_compute_remaining_time_in_min(capacity - 15, sec_per_cap);
-       } else if (level == BATTERY_LEVEL_HIGH && low_count && mid_count && high_count) {
-               sec_per_cap = heart_battery_get_usage_level_spc(BATTERY_LEVEL_LOW, goal);
-               pred_min = heart_battery_compute_remaining_time_in_min(15, sec_per_cap);
-               sec_per_cap = heart_battery_get_usage_level_spc(BATTERY_LEVEL_MID, goal);
-               pred_min +=
-                       heart_battery_compute_remaining_time_in_min(35, sec_per_cap);
-               sec_per_cap = heart_battery_get_usage_level_spc(BATTERY_LEVEL_HIGH, goal);
-               pred_min +=
-                       heart_battery_compute_remaining_time_in_min(capacity - 50, sec_per_cap);
-       }
-       heart_battery_set_prediction(PCB, goal, 0, 0, pred_min);
-
-
-       /* PREDICTION METHOD: week average */
-       total_time = 0;
-       total_count = 0;
-       for (i = 0; i < BATTERY_HISTORY_DAY_MAX; i++) {
-               total_time += heart_battery_get_usage_week_total_time(i, goal);
-               total_count += heart_battery_get_usage_week_count(i, goal);
-       }
-       if (total_time && total_count >= BATTERY_PREDICTION_DATA_MIN) {
-               sec_per_cap = total_time / total_count;
-               if (sec_per_cap < default_sec_per_cap[goal][DEFAULT_MIN])
-                       sec_per_cap = default_sec_per_cap[goal][DEFAULT_MIN];
-               else if (sec_per_cap > default_sec_per_cap[goal][DEFAULT_MAX])
-                       sec_per_cap = default_sec_per_cap[goal][DEFAULT_MAX];
-               pred_min =
-                       heart_battery_compute_remaining_time_in_min(capacity, sec_per_cap);
-               heart_battery_set_prediction(WEEK, goal, sec_per_cap, total_count, pred_min);
-       } else
-               heart_battery_set_prediction(WEEK, goal, 0, 0, 0);
-
-
-       /* PREDICTION METHOD:  last BATTERY_PREDICTION_COUNT data average */
-       arrays = g_array_new(FALSE, FALSE, sizeof(struct heart_battery_capacity *));
-       if (!arrays) {
-               _E("Failed to alloc array");
-               return;
-       }
-       if (heart_battery_get_capacity_history_latest(arrays, goal, BATTERY_PREDICTION_LATEST_COUNT)
-                       != RESOURCED_ERROR_NONE) {
-               _E("Failed to get battery capacity history");
-               g_array_free(arrays, TRUE);
-               arrays = NULL;
-               return;
-       }
-       total_time = 0;
-       total_count = 0;
-       for (i = 0; i < arrays->len; i++) {
-               lbc = g_array_index(arrays, struct heart_battery_capacity *, i);
-               if (!lbc)
-                       break;
-               total_count += lbc->diff_capacity;
-               if (goal == CHARGING)
-                       total_time += lbc->charging_time;
-               else
-                       total_time += lbc->used_time;
-               free(lbc);
-       }
-       if (total_time && total_count >= BATTERY_PREDICTION_DATA_MIN) {
-               sec_per_cap = total_time / total_count;
-               if (sec_per_cap < default_sec_per_cap[goal][DEFAULT_MIN])
-                       sec_per_cap = default_sec_per_cap[goal][DEFAULT_MIN];
-               else if (sec_per_cap > default_sec_per_cap[goal][DEFAULT_MAX])
-                       sec_per_cap = default_sec_per_cap[goal][DEFAULT_MAX];
-
-               pred_min =
-                       heart_battery_compute_remaining_time_in_min(capacity, sec_per_cap);
-               heart_battery_set_prediction(COUNT, goal, sec_per_cap, total_count, pred_min);
-               /* check current discharge rate */
-               if (sec_per_cap && goal == DISCHARGING) {
-                       batt_stat.discharge_rate_level =
-                               heart_battery_calculate_discharge_rate_level(sec_per_cap);
-                       _I("discharge rate level : %d", batt_stat.discharge_rate_level);
-               }
-       } else
-               heart_battery_set_prediction(COUNT, goal, 0, 0, 0);
-       g_array_free(arrays, TRUE);
-       arrays = NULL;
-
-
-       /* PREDICTION METHOD: last BATTERY_PREDICTION_PERIOD hours average */
-       arrays = g_array_new(FALSE, FALSE, sizeof(struct heart_battery_capacity *));
-       if (!arrays) {
-               _E("Failed to alloc array");
-               return;
-       }
-       if (heart_battery_get_capacity_history(arrays, BATTERY_PREDICTION_PERIOD) != RESOURCED_ERROR_NONE) {
-               _E("Failed to get battery capacity history");
-               g_array_free(arrays, TRUE);
-               arrays =  NULL;
-               return;
-       }
-       total_time = 0;
-       total_count = 0;
-       for (i = 0; i < arrays->len; i++) {
-               lbc = g_array_index(arrays, struct heart_battery_capacity *, i);
-               if (!lbc)
-                       break;
-               if (goal == CHARGING) {
-                       if (lbc->charger_status != CHARGING) {
-                               free(lbc);
-                               continue;
-                       }
-                       total_time += lbc->charging_time;
-                       total_count += lbc->diff_capacity;
-               } else {
-                       if (lbc->charger_status != DISCHARGING) {
-                               free(lbc);
-                               continue;
-                       }
-                       total_time += lbc->used_time;
-                       total_count += lbc->diff_capacity;
-               }
-               free(lbc);
-       }
-       g_array_free(arrays, TRUE);
-       arrays = NULL;
-       if (total_time && total_count >= BATTERY_PREDICTION_DATA_MIN) {
-               sec_per_cap = total_time / total_count;
-               if (sec_per_cap < default_sec_per_cap[goal][DEFAULT_MIN])
-                       sec_per_cap = default_sec_per_cap[goal][DEFAULT_MIN];
-               else if (sec_per_cap > default_sec_per_cap[goal][DEFAULT_MAX])
-                       sec_per_cap = default_sec_per_cap[goal][DEFAULT_MAX];
-               pred_min =
-                       heart_battery_compute_remaining_time_in_min(capacity, sec_per_cap);
-               heart_battery_set_prediction(PERIOD, goal, sec_per_cap, total_count, pred_min);
-
-       } else
-               heart_battery_set_prediction(PERIOD, goal, 0, 0, 0);
-
-       /* Log values of all predictions calculated */
-       for (i = 0; i < MAX_STRATEGY; i++) {
-               _I("%s %d %ld %ld %ld",
-                               (goal == DISCHARGING) ? "TimeToEmpty:" : "TimeToFull:",
-                               batt_stat.curr_capacity,
-                               batt_stat.prediction[goal].sec_per_cap[i],
-                               batt_stat.prediction[goal].cap_counter[i],
-                               batt_stat.prediction[goal].time_pred_min[i]);
-       }
-}
-
-static int heart_battery_add_capacity(int capacity)
-{
-       char info[BATTERY_DATA_MAX];
-       int ret, idx, status;
-       long time_diff_capacity_lvl[MAX_CHARGER_STATE];
-       int diff_capacity_lvl;
-       long total_time, total_count, sec_per_cap;
-       time_t timestamp = time(NULL);
-       time_t curr_wall_time = logging_get_time(CLOCK_BOOTTIME);
-
-       status = batt_stat.curr_charger_status;
-       /* calculate diff */
-       time_diff_capacity_lvl[status] = curr_wall_time - batt_stat.last_event_wall_time;
-
-       if (time_diff_capacity_lvl[status] < 0) {
-               batt_stat.last_event_wall_time = curr_wall_time;
-               return 0;
-       }
-
-       time_diff_capacity_lvl[!status] = 0;
-
-       if (!batt_stat.curr_capacity)
-               diff_capacity_lvl = 1;
-       else
-               diff_capacity_lvl = abs(batt_stat.curr_capacity - capacity);
-
-       _I("%d -> %d %ld %ld", batt_stat.curr_capacity, capacity,
-                       timestamp, time_diff_capacity_lvl[status]);
-
-       /* update battery current status */
-       batt_stat.last_event_wall_time = curr_wall_time;
-       batt_stat.curr_capacity = capacity;
-
-       /* Full Charging status */
-       if (status == CHARGING && !REMAIN_CAPACITY(capacity) && !diff_capacity_lvl)
-               return 0;
-
-       /* update run usage */
-       batt_stat.curr_run_time_sec[status] += time_diff_capacity_lvl[status];
-       batt_stat.curr_cap_counter[status] += diff_capacity_lvl;
-
-       /* update batt_lvl_usage usage */
-       total_time = 0;
-       total_count = 0;
-
-       if (status == CHARGING)
-               idx = heart_battery_get_level_usage_index(REMAIN_CAPACITY(capacity));
-       else
-               idx = heart_battery_get_level_usage_index(capacity);
-
-       total_time = heart_battery_get_usage_level_total_time(idx, status) + time_diff_capacity_lvl[status];
-       if (total_time)
-               total_count = heart_battery_get_usage_level_count(idx, status) + diff_capacity_lvl;
-
-       if (total_count) {
-               sec_per_cap = total_time / total_count;
-               if (sec_per_cap == 0)
-                       sec_per_cap = default_sec_per_cap[status][DEFAULT_AVG];
-               else if (sec_per_cap < default_sec_per_cap[status][DEFAULT_MIN])
-                       sec_per_cap = default_sec_per_cap[status][DEFAULT_MIN];
-               else if (sec_per_cap > default_sec_per_cap[status][DEFAULT_MAX])
-                       sec_per_cap = default_sec_per_cap[status][DEFAULT_MAX];
-               /*
-                * If counts reached MAXIMUM number,
-                * counts is divided by 2 to reduce previous data's effect to equation
-                */
-               if (total_count >= BATTERY_HISTORY_COUNT_MAX)
-                       total_count = total_count >> 1;
-
-               heart_battery_set_usage_level(idx, status, sec_per_cap, total_count);
-               heart_battery_set_usage_level_stime(idx, timestamp);
-       }
-
-       /* update day usage */
-       total_time = 0;
-       total_count = 0;
-
-       idx = heart_battery_get_week_day_usage_index(timestamp);
-       total_time = heart_battery_get_usage_week_total_time(idx, status) + time_diff_capacity_lvl[status];
-       if (total_time)
-               total_count = heart_battery_get_usage_week_count(idx, status) + diff_capacity_lvl;
-
-       if (total_count) {
-               sec_per_cap = total_time / total_count;
-               if (sec_per_cap == 0)
-                       sec_per_cap = default_sec_per_cap[status][DEFAULT_AVG];
-               else if (sec_per_cap < default_sec_per_cap[status][DEFAULT_MIN])
-                       sec_per_cap = default_sec_per_cap[status][DEFAULT_MIN];
-               else if (sec_per_cap > default_sec_per_cap[status][DEFAULT_MAX])
-                       sec_per_cap = default_sec_per_cap[status][DEFAULT_MAX];
-               heart_battery_set_usage_week(idx, status, sec_per_cap, total_count);
-               heart_battery_set_usage_week_stime(idx, CALCULATE_DAY_BASE_TIME(timestamp));
-       }
-
-       heart_battery_calculate_prediction(batt_stat.curr_charger_status);
-
-       /* db backup */
-       snprintf(info, sizeof(info), "%d %d %ld %ld %d %d ",
-                       capacity, diff_capacity_lvl,
-                       time_diff_capacity_lvl[DISCHARGING], time_diff_capacity_lvl[CHARGING],
-                       batt_stat.curr_charger_status, batt_stat.reset_mark);
-       ret = logging_write(PID_FOR_ROOT, BATTERY_NAME, TIZEN_SYSTEM_BATTERY_APPID,
-                       TIZEN_SYSTEM_APPID, timestamp, info);
-       if (ret != RESOURCED_ERROR_NONE)
-               return ret;
-
-       /* insert capacity history list */
-       heart_battery_insert_capacity(&capacity_history_list, capacity, diff_capacity_lvl,
-                       timestamp, time_diff_capacity_lvl[DISCHARGING],
-                       time_diff_capacity_lvl[CHARGING], batt_stat.curr_charger_status,
-                       batt_stat.reset_mark, true);
-
-       _D("battery_heart_capacity_write %d diff_capacity %d, used time %ld, charging time %ld, charger status %d, reset_mark %d",
-                       capacity, diff_capacity_lvl,
-                       time_diff_capacity_lvl[DISCHARGING], time_diff_capacity_lvl[CHARGING],
-                       batt_stat.curr_charger_status, batt_stat.reset_mark);
-
-       resourced_notify(RESOURCED_NOTIFIER_LOGGING_START, NULL);
-       return RESOURCED_ERROR_NONE;
-}
-
-static void rul_display_state_changed_cb(device_callback_e type, void *value, void *user_data)
-{
-       int display_state = (int) ((intptr_t) value), charger_status;
-       /* 0 : on, 1 : dim, 2: off */
-
-       /*
-        * If charger_status==CHARGING and raw capacity calculation ongoing,
-        * then, handle display_on time for RUL
-        */
-
-       charger_status = heart_battery_get_charger_status();
-       if ((charger_status == CHARGING) && (rul.charging_start_time != 0)) {
-               if (type != DEVICE_CALLBACK_DISPLAY_STATE)
-                       return;
-
-               if (display_state == DISPLAY_STATE_NORMAL) {
-                       _I("DISPLAY: NORMAL/DIM");
-                       rul.lcd_data.state = DISPLAY_STATE_NORMAL;
-                       if (rul.lcd_data.on_start_time == 0) {
-                               rul.lcd_data.on_start_time = logging_get_time(CLOCK_BOOTTIME);
-                       }
-               } else if (display_state == DISPLAY_STATE_SCREEN_OFF) {
-                       _I("DISPLAY: OFF");
-                       rul.lcd_data.state = DISPLAY_STATE_SCREEN_OFF;
-                       if (rul.lcd_data.on_start_time > 0) {
-                               rul.lcd_data.on_stop_time = logging_get_time(CLOCK_BOOTTIME);
-                               rul.lcd_data.on_time += rul.lcd_data.on_stop_time - rul.lcd_data.on_start_time;
-                               rul.lcd_data.on_start_time = 0;
-                               rul.lcd_data.on_stop_time = 0;
-                       }
-               }
-       }
-}
-
-static void rul_write_data_to_file(void)
-{
-       int len = 0;
-       char buff[RUL_DATA_SIZE] = {0};
-       _cleanup_fclose_ FILE *fp = NULL, *fp1 = NULL;
-       float fullcapnom = 0, fullcapnom_mAh = 0;
-
-       /* Update count of Charging cycles*/
-       rul.charging_cycles += 1;
-
-       /* Calculate normalized capacity, i.e., extrapolate for 0% to 100% */
-       fullcapnom = rul.raw_capacity / ((rul.soc_stop/100.0f) - (rul.soc_start/100.0f));
-       fullcapnom_mAh = fullcapnom / 3.6f;
-       _I("rul : raw_capacity = %.4f As, fullcapnom = %.4f As = %.4f mAh", rul.raw_capacity, fullcapnom, fullcapnom_mAh);
-
-       /* Update RUL data file */
-       fp = fopen(RUL_DATA_FILE, "a");
-       if (fp == NULL) {
-               _E("Could not open file - RUL_DATA_FILE");
-               return;
-       }
-
-       len = snprintf(buff, RUL_DATA_SIZE, "%d %.4f\n", rul.charging_cycles, fullcapnom_mAh);
-
-       if (len < RUL_DATA_SIZE)
-               fputs(buff, fp);
-
-       /* Write Charging cycles count to file */
-       fp1 = fopen(RUL_CHARGING_CYCLES_FILE, "w");
-       if (fp1 == NULL) {
-               _E("Could not open file for write - RUL_CHARGING_CYCLES_FILE");
-               return;
-       }
-       fprintf(fp1, "%d", rul.charging_cycles);
-
-}
-
-static void rul_charging_cycle_end_work(void)
-{
-       int capacity;
-       long total_charging_time;
-       bool lcd_on_time_check;
-       float lcd_on_ratio = 1.0f;
-
-       capacity = heart_battery_get_capacity();
-
-       rul.soc_stop = capacity;
-       rul.charging_stop_time = logging_get_time(CLOCK_BOOTTIME);
-
-       /* If LCD was on before disconnecting charger, update display_on time */
-       if (rul.lcd_data.on_start_time != 0) {
-               rul.lcd_data.on_stop_time = logging_get_time(CLOCK_BOOTTIME);
-               rul.lcd_data.on_time += rul.lcd_data.on_stop_time - rul.lcd_data.on_start_time;
-       }
-
-       /* Max LCD ON Time ratio criteria met ? */
-       total_charging_time = rul.charging_stop_time - rul.charging_start_time;
-       if (total_charging_time != 0)
-               lcd_on_ratio = (rul.lcd_data.on_time / (total_charging_time * 1.0f));
-       lcd_on_time_check = lcd_on_ratio <= RUL_DISPLAY_ON_CUTOFF_RATIO;
-
-       /* write data to file if condititons met*/
-       if ((rul.charging_start_time != 0) && (lcd_on_time_check == true) &&
-           (rul.soc_stop - rul.soc_start >= RUL_MIN_CAPACITY_DIFF))
-               rul_write_data_to_file();
-
-       /* init for next charging cycle */
-       rul.soc_start = 0;
-       rul.soc_stop = 0;
-       rul.charging_start_time = 0;
-       rul.charging_stop_time = 0;
-       rul.lcd_data.on_start_time = 0;
-       rul.lcd_data.on_stop_time = 0;
-       rul.lcd_data.on_time = 0;
-}
-
-static void rul_calculate_raw_capacity(void)
-{
-       /*
-        * This function updates Raw Capacity every 1% SoC change.
-        *
-        * Upon first time 1% SoC change, initialize rul_info variables.
-        *
-        * Subsequently, Update Raw Capacity using time interval and
-        * current_now sys node values.
-        *
-        * If capacity = 100%, dump collected data
-        */
-
-       long rul_curr_time, rul_time_interval;
-       static long prev_charging_time;
-       int fg_curr_inst, capacity, ret;
-       float fg_curr_inst_f;
-       static float prev_fg_curr_inst_f = 0.0f;
-
-       capacity = heart_battery_get_capacity();
-
-       if (rul.charging_start_time == 0) {
-               rul.charging_start_time = logging_get_time(CLOCK_BOOTTIME);
-               rul.soc_start = capacity;
-               rul.raw_capacity = 0.0f;
-               prev_charging_time = rul.charging_start_time;
-               prev_fg_curr_inst_f = 0.0f;
-               rul.lcd_data.on_start_time = 0;
-               rul.lcd_data.on_stop_time = 0;
-               rul.lcd_data.on_time = 0;
-
-               /* Get display status at time of initiating RUL calculations */
-               ret = device_display_get_state(&rul.lcd_data.state);
-               if (ret != DEVICE_ERROR_NONE) {
-                       _E("Failed to get device display state with err = %d", ret);
-                       return;
-               }
-               if ((rul.lcd_data.state == DISPLAY_STATE_NORMAL) || (rul.lcd_data.state == DISPLAY_STATE_SCREEN_DIM))
-                       rul.lcd_data.on_start_time = logging_get_time(CLOCK_BOOTTIME);
-       } else {
-               rul_curr_time = logging_get_time(CLOCK_BOOTTIME);
-               rul_time_interval = rul_curr_time - prev_charging_time;
-               prev_charging_time = rul_curr_time;
-
-               ret = fread_int("/sys/class/power_supply/battery/current_now", &fg_curr_inst);
-               if (ret != RESOURCED_ERROR_NONE) {
-                       _E("This device doesn't support FG CURRENT_NOW information. Disable LOGIC_RUL");
-                       return;
-               }
-
-               fg_curr_inst_f = fg_curr_inst / 1000.0f;
-               rul.raw_capacity += ((fg_curr_inst_f + prev_fg_curr_inst_f) / 2.0f)*rul_time_interval;
-               prev_fg_curr_inst_f = fg_curr_inst_f;
-       }
-
-       if (capacity == 100) {
-               rul_charging_cycle_end_work();
-       }
-}
-
-/* ============================ DBUS -> DEVICED on demand ==================== */
-
-static int heart_battery_direct_get_capacity(void)
-{
-       int capacity;
-
-       capacity = d_bus_call_method_sync_gvariant(DEVICED_BUS_NAME, DEVICED_PATH_BATTERY,
-                       DEVICED_INTERFACE_BATTERY,
-                       GET_BATTERY_CAPACITY,
-                       NULL);
-       if (capacity < 0) {
-               _E("Failed to sync DBUS message.");
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       return capacity;
-}
-
-static enum charger_status_type heart_battery_direct_get_charger_status(void)
-{
-       int status;
-
-       status = d_bus_call_method_sync_gvariant(DEVICED_BUS_NAME, DEVICED_PATH_BATTERY,
-                       DEVICED_INTERFACE_BATTERY,
-                       GET_CHARGER_STATUS,
-                       NULL);
-       if (status < 0) {
-               _E("Failed to sync DBUS message.");
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       if (status > 0)
-               return CHARGING;
-       return DISCHARGING;
-}
-
-/* =========================  DBUS -> DEVICED  on demand END ================= */
-
-/* ============================ DBUS -> DEVICED handler ====================== */
-static void heart_battery_capacity_status(GVariant *params)
-{
-       /*
-        * This handler is called when battery capacity value change in 1%
-        *
-        * The message have current percent value of capacity
-        *
-        * (This requires deviced with commit at least:
-        * "f1ae1d1f270e9 battery: add battery capacity dbus signal broadcast")
-        */
-
-       int capacity = -1;
-       int bat_trigger = -1;
-       int bat_ups_est = -1;
-       int bat_normal_est = -1;
-
-       do_expr_unless_g_variant_get_typechecked(return, params, "(i)", &capacity);
-       if (capacity < 0) {
-               _E("Failed: dbus_message_get_args()");
-               return;
-       }
-       heart_battery_add_capacity(capacity);
-       heart_battery_update_used_time(logging_get_time(CLOCK_BOOTTIME),
-                       batt_stat.curr_charger_status);
-
-       if (logic_v2) {
-               /* get the device mode */
-               if (vconf_get_int(VCONFKEY_HEART_BATTERY_DEVICE_MODE, &device_mode))
-                       _E("failed to get VCONFKEY_HEART_BATTERY_DEVICE_MODE\n");
-
-               /* for every battery level change, calculate the battery estimation time using new logic*/
-               heart_battery_cal_discharge_rem_time();
-
-               if (batt_stat.curr_charger_status == CHARGING &&
-                       batt_stat.last_capacity_chg < batt_stat.curr_capacity) {
-                       heart_battery_cal_charging_rem_time();
-                       first_level_change = FALSE;
-               } else {
-                       /*
-                        * if battery is very very low then update the pivot before power off
-                        */
-                       if (batt_stat.curr_capacity == LOW_CAPACITY)
-                               heart_battery_collect_pivot_info();
-               }
-       }
-       if (logic_rul) {
-               /* Update prev_soc, curr_soc */
-               rul.prev_soc = rul.curr_soc;
-               rul.curr_soc = capacity;
-
-               /*
-                * If charger_status==CHARGING and SOC_INCREASING, start/continue raw capacity calculation.
-                * Else, if raw capacity calculation was ongoing, then dump collected data.
-                */
-               if ((batt_stat.curr_charger_status == CHARGING) && (rul.curr_soc >= rul.prev_soc))
-                       rul_calculate_raw_capacity();
-               else if (rul.charging_start_time != 0)
-                       rul_charging_cycle_end_work();
-       }
-
-       /* Get the UPSM trigger value and remaining estimate */
-       if (vconf_get_int(VCONFKEY_SETAPPL_MANAGE_BATTERY_TRIGGER_TIME, &bat_trigger)) {
-               _E("failed to get VCONFKEY_SETAPPL_MANAGE_BATTERY_TRIGGER_TIME\n");
-               return;
-       }
-       if (bat_trigger > 0) { /* Battery planner is enabled*/
-               bat_ups_est = get_battery_remaining_time(ULTRA_SAVING_MODE, DISCHARGING);
-               bat_normal_est = get_battery_remaining_time(POWER_NORMAL_MODE, DISCHARGING);
-               _I(" trigger time: %d,  ups est:%d, normal est:%d", bat_trigger, bat_ups_est, bat_normal_est);
-               if (bat_ups_est > 0 && bat_trigger >= bat_ups_est) {
-                       char *args[4] = { "_SYSPOPUP_CONTENT_", "manage_battery",
-                                               "_BAT_POPUP_TYPE_", "enable_mbp"};
-
-                       d_bus_call_method_sync(SYSTEM_POPUP_BUS_NAME,
-                                       SYSTEM_POPUP_PATH_SYSTEM, SYSTEM_POPUP_IFACE_SYSTEM,
-                                       "PopupLaunch", "ssss", args);
-               }
-               if (bat_normal_est > 0 && bat_normal_est >= bat_trigger) {
-                       char *args[4] = { "_SYSPOPUP_CONTENT_", "manage_battery",\
-                                               "_BAT_POPUP_TYPE_", "disable_mbp"};
-
-                       d_bus_call_method_sync(SYSTEM_POPUP_BUS_NAME,
-                                       SYSTEM_POPUP_PATH_SYSTEM, SYSTEM_POPUP_IFACE_SYSTEM,
-                                       "PopupLaunch", "ssss", args);
-               }
-       }
-}
-
-static void heart_battery_charger_status(GVariant *params)
-{
-       /*
-        * This handler is called when USB cable with charging capabilities
-        * is connected or disconnected from the device.
-        *
-        * The message have current status of charger connection.
-        * STATUSES:
-        * 0 - charger was disconnected
-        * 1 - charger was connected
-        */
-       int charger_status = -1, cap_history_size;
-
-       do_expr_unless_g_variant_get_typechecked(return, params, "(i)", &charger_status);
-       if (charger_status < 0) {
-               _E("Failed: dbus_message_get_args()");
-               return;
-       }
-
-       /* Update the statistics with capacity when charger state was changed */
-       heart_battery_add_capacity(batt_stat.curr_capacity);
-
-       cap_history_size = heart_battery_get_capacity_history_size();
-
-       if (charger_status == DISCHARGING && batt_stat.curr_capacity >= 90) {
-               /*
-                * If battery is charged over 90 and charger was disconnected.
-                * So most probably the phone was "charged".
-                * Let's reset the statistics.
-                */
-               resourced_notify(RESOURCED_NOTIFIER_DATA_RESET, NULL);
-       } else if (charger_status == DISCHARGING && cap_history_size >= BATTERY_CAPACITY_MAX) {
-               /*
-                * Charger is not connected and the battery history is over limit.
-                * Let's reset the statistics.
-                */
-               resourced_notify(RESOURCED_NOTIFIER_DATA_RESET, NULL);
-       }
-       /* Update current charger connection status */
-       batt_stat.curr_charger_status = charger_status;
-       heart_battery_update_used_time(logging_get_time(CLOCK_BOOTTIME),
-                       batt_stat.curr_charger_status);
-       heart_battery_calculate_prediction(batt_stat.curr_charger_status);
-
-       if (logic_v2) {
-               /*
-                * If charger removed/inserted then update the battery estimation time
-                */
-               heart_battery_cal_discharge_rem_time();
-
-               if (charger_status == CHARGING) {
-                       /*
-                        * if diff is more than 10% then flush the previous charge data
-                        */
-                       if ((batt_stat.last_capacity_chg > 0) &&
-                           (batt_stat.last_capacity_chg - batt_stat.curr_capacity > BATT_CHG_FLUSH_DATA))
-                               heart_battery_flush_charge_data();
-
-                       /* collect the data for pivot update */
-                       heart_battery_collect_pivot_info();
-
-                       batt_stat.last_wall_time_chg = 0;
-                       first_level_change = TRUE;
-                       heart_battery_print_prev_charge_data();
-                       heart_battery_cal_charging_rem_time();
-               } else {
-                       heart_battery_collect_discharge_data();
-               }
-       }
-       if (logic_rul) {
-               /*
-                * If charger disconnected and raw capacity calculation was ongoing,
-                * then dump collected data.
-                */
-               if ((charger_status == DISCHARGING) && (rul.charging_start_time != 0))
-                       rul_charging_cycle_end_work();
-       }
-}
-
-/* =========================  DBUS -> DEVICED handler END ==================== */
-
-int heart_battery_get_capacity_history_latest(GArray *arrays, int charge, int max_size)
-{
-       int ret, size, count;
-       struct heart_battery_capacity *lbc, *lbci;
-       GSList *iter, *rlist;
-
-       if (!capacity_history_list) {
-               _E("empty capacity history list");
-               return RESOURCED_ERROR_FAIL;
-       }
-       size = g_slist_length(capacity_history_list);
-       if (!size) {
-               _I("capacity history is empty");
-               return RESOURCED_ERROR_NONE;
-       }
-       ret = pthread_mutex_lock(&heart_battery_mutex);
-       if (ret) {
-               _E("pthread_mutex_lock() failed, %d", ret);
-               return RESOURCED_ERROR_FAIL;
-       }
-       count = 0;
-
-       rlist = g_slist_copy(capacity_history_list);
-
-       rlist = g_slist_reverse(rlist);
-
-       gslist_for_each_item(iter, rlist) {
-               lbc = (struct heart_battery_capacity *)iter->data;
-               if (!lbc)
-                       break;
-               if (charge < MAX_CHARGER_STATE && charge != lbc->charger_status)
-                       continue;
-               count++;
-               if (max_size < count)
-                       break;
-               lbci = malloc(sizeof(struct heart_battery_capacity));
-               if (!lbci) {
-                       _E("malloc failed");
-                       goto unlock_exit;
-               }
-               lbci->capacity = lbc->capacity;
-               lbci->diff_capacity = lbc->diff_capacity;
-               if (!lbc->diff_capacity)
-                       count--;
-               lbci->used_time = lbc->used_time;
-               lbci->charging_time = lbc->charging_time;
-               lbci->charger_status = lbc->charger_status;
-               g_array_prepend_val(arrays, lbci);
-       }
-unlock_exit:
-       g_slist_free(rlist);
-       ret = pthread_mutex_unlock(&heart_battery_mutex);
-       if (ret) {
-               _E("pthread_mutex_unlock() failed, %d", ret);
-               return RESOURCED_ERROR_FAIL;
-       }
-       return RESOURCED_ERROR_NONE;
-}
-
-int heart_battery_get_capacity_history(GArray *arrays, enum heart_data_period period)
-{
-       int ret, index, size;
-       struct heart_battery_capacity *lbc, *lbci;
-       GSList *iter;
-       time_t curr = time(NULL);
-
-       switch (period) {
-       case DATA_LATEST:
-               index = 0;
-               break;
-       case DATA_3HOUR:
-               index = 3;
-               break;
-       case DATA_6HOUR:
-               index = 6;
-               break;
-       case DATA_12HOUR:
-               index = 12;
-               break;
-       case DATA_1DAY:
-               index = 24;
-               break;
-       default:
-               _E("Wrong message arguments! %d", period);
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       if (!capacity_history_list) {
-               _E("empty capacity history list");
-               return RESOURCED_ERROR_FAIL;
-       }
-       size = g_slist_length(capacity_history_list);
-       if (!size) {
-               _I("capacity history is empty");
-               return RESOURCED_ERROR_NONE;
-       }
-       ret = pthread_mutex_lock(&heart_battery_mutex);
-       if (ret) {
-               _E("pthread_mutex_lock() failed, %d", ret);
-               return RESOURCED_ERROR_FAIL;
-       }
-       gslist_for_each_item(iter, capacity_history_list) {
-               lbc = (struct heart_battery_capacity *)iter->data;
-               if (!lbc)
-                       break;
-               if (index && (lbc->timestamp < curr - (index * 3600)))
-                       continue;
-               lbci = malloc(sizeof(struct heart_battery_capacity));
-               if (!lbci) {
-                       _E("malloc failed");
-                       ret = pthread_mutex_unlock(&heart_battery_mutex);
-                       if (ret) {
-                               _E("pthread_mutex_unlock() failed, %d", ret);
-                               return RESOURCED_ERROR_FAIL;
-                       }
-                       return RESOURCED_ERROR_OUT_OF_MEMORY;
-               }
-               lbci->capacity = lbc->capacity;
-               lbci->diff_capacity = lbc->diff_capacity;
-               lbci->used_time = lbc->used_time;
-               lbci->charging_time = lbc->charging_time;
-               lbci->charger_status = lbc->charger_status;
-               g_array_append_val(arrays, lbci);
-       }
-       ret = pthread_mutex_unlock(&heart_battery_mutex);
-       if (ret) {
-               _E("pthread_mutex_unlock() failed, %d", ret);
-               return RESOURCED_ERROR_FAIL;
-       }
-       return RESOURCED_ERROR_NONE;
-}
-
-/* ============================ DBUS interface ====================== */
-
-static void dbus_get_battery_capacity_history_latest(GDBusMethodInvocation *invocation, GVariant *params)
-{
-       int i, size, charge, max_size;
-       GArray *arrays = NULL;
-       GVariantBuilder builder, *sub_builder;
-
-       do_expr_unless_g_variant_get_typechecked(goto failure, params, "(ii)", &charge, &max_size);
-       if (charge < 0 || max_size < 0) {
-               _E("Wrong message arguments!");
-               goto failure;
-       }
-
-       size = g_slist_length(capacity_history_list);
-       if (!size) {
-               _I("capacity history is empty");
-               goto failure;
-       }
-       arrays = g_array_new(FALSE, FALSE, sizeof(struct heart_battery_capacity *));
-       if (!arrays) {
-               _E("Failed to alloc array");
-               goto failure;
-       }
-       if (heart_battery_get_capacity_history_latest(arrays, charge, max_size) != RESOURCED_ERROR_NONE) {
-               _E("Failed to get capacity history latest");
-               D_BUS_REPLY_ERR(invocation);
-               return;
-       }
-
-       g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
-       sub_builder = g_variant_builder_new(G_VARIANT_TYPE("a(iii)"));
-       if (!arrays->len) {
-               _E("No battery capacity history data");
-               goto exit;
-       }
-
-       for (i = 0; i < arrays->len; i++) {
-               struct heart_battery_capacity *lbc;
-               lbc = g_array_index(arrays, struct heart_battery_capacity *, i);
-               if (!lbc)
-                       break;
-
-               g_variant_builder_add(sub_builder, "(iii)", lbc->capacity,
-                                                       lbc->used_time, lbc->charging_time);
-               free(lbc);
-       }
-exit:
-       g_variant_builder_add_value(&builder, g_variant_new("a(iii)", sub_builder));
-       g_variant_builder_unref(sub_builder);
-       g_array_free(arrays, TRUE);
-       g_dbus_method_invocation_return_value(invocation, g_variant_builder_end(&builder));
-       return;
-
-failure:
-       D_BUS_REPLY_ERR(invocation);
-}
-
-static void dbus_get_battery_capacity_history(GDBusMethodInvocation *invocation, GVariant *params)
-{
-       int ret, size, period = -1, index;
-       struct heart_battery_capacity *lbc;
-       GSList *iter;
-       time_t curr = time(NULL);
-       GVariantBuilder builder, *sub_builder;
-
-       do_expr_unless_g_variant_get_typechecked(goto failure, params, "(i)", &period);
-       if (period < 0) {
-               _E("Wrong message arguments!");
-               goto failure;
-       }
-       switch (period) {
-       case DATA_LATEST:
-               index = 0;
-               break;
-       case DATA_3HOUR:
-               index = 3;
-               break;
-       case DATA_6HOUR:
-               index = 6;
-               break;
-       case DATA_12HOUR:
-               index = 12;
-               break;
-       case DATA_1DAY:
-               index = 24;
-               break;
-       default:
-               _E("Wrong message arguments! %d", period);
-               goto failure;
-       }
-       size = g_slist_length(capacity_history_list);
-       if (!size) {
-               _I("capacity history is empty");
-               goto failure;
-       }
-       ret = pthread_mutex_lock(&heart_battery_mutex);
-       if (ret) {
-               _E("pthread_mutex_lock() failed, %d", ret);
-               goto failure;
-       }
-
-       g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
-       sub_builder = g_variant_builder_new(G_VARIANT_TYPE("a(su)"));
-
-       gslist_for_each_item(iter, capacity_history_list) {
-               lbc = (struct heart_battery_capacity *)iter->data;
-               if (!lbc)
-                       break;
-               if (index && (lbc->timestamp < curr - (index * 3600)))
-                       continue;
-
-               g_variant_builder_add(sub_builder, "(iii)", lbc->capacity,
-                                                       lbc->used_time, lbc->charging_time);
-       }
-
-       ret = pthread_mutex_unlock(&heart_battery_mutex);
-       if (ret) {
-               _E("pthread_mutex_unlock() failed, %d", ret);
-               g_variant_builder_unref(sub_builder);
-               goto failure;
-       }
-
-       g_variant_builder_add_value(&builder, g_variant_new("a(iii)", sub_builder));
-       g_variant_builder_unref(sub_builder);
-
-       g_dbus_method_invocation_return_value(invocation, g_variant_builder_end(&builder));
-       return;
-
-failure:
-       D_BUS_REPLY_ERR(invocation);
-}
-
-static void dbus_get_battery_used_time(GDBusMethodInvocation *invocation, GVariant *params)
-{
-       heart_battery_update_used_time(logging_get_time(CLOCK_BOOTTIME),
-                       batt_stat.curr_charger_status);
-
-       g_dbus_method_invocation_return_value(invocation,
-                       g_variant_new("(i)", batt_used.used_time_sec));
-}
-
-static int get_battery_remaining_time(int mode, enum charger_status_type status)
-{
-       int i, ret, count;
-       long sum, time, cumul_average, trend_average;
-       double result;
-
-       ret = count = 0;
-       sum = time = 0;
-       cumul_average = trend_average = 0;
-       /* get prediction time of cumulative value */
-       for (i = 0; i <= WEEK; i++) {
-               time = heart_battery_get_prediction_time(i, status);
-               if (time) {
-                       sum += time;
-                       count++;
-               }
-       }
-       if (count)
-               cumul_average = sum / count;
-
-       count = 0;
-       sum = 0;
-       /* get prediction time of trend value */
-       for (i = COUNT; i < MAX_STRATEGY; i++) {
-               time = heart_battery_get_prediction_time(i, status);
-               if (time) {
-                       sum += time;
-                       count++;
-               }
-       }
-       if (count)
-               trend_average = sum / count;
-
-       /* failed to get prediction so return learning mode */
-       if (!cumul_average && !trend_average) {
-               if (batt_stat.curr_capacity != 100 && batt_stat.curr_capacity != 0)
-                       ret = BATTERY_USAGE_LEARNING;
-       } else if (cumul_average && !trend_average) {
-               /* failed to get prediction of trend average */
-               ret = cumul_average;
-       } else if (!cumul_average && trend_average) {
-               /* failed to get prediction of cumulative average */
-               ret = trend_average;
-       } else
-               ret = ((cumul_average * CUMUL_WEIGHT) + (trend_average * TREND_WEIGHT));
-
-       if (status == CHARGING) {
-               if (logic_v2)  /* new logic */
-                       return batt_stat.remaining_time_chg;
-               return ret; /* old logic */
-       }
-
-       if (logic_v2) { /* new logic */
-               switch (mode) {
-               case POWER_SAVING_MODE:
-                       /* Fall through */
-               case ULTRA_SAVING_MODE:
-                       ret = get_battery_remaining_time_ups();
-                       break;
-               case POWER_NORMAL_MODE:
-                       ret = get_battery_remaining_time_new();
-                       break;
-               default:
-                       break;
-               }
-               return ret;
-       }
-
-       if (ret <= 0)
-               return BATTERY_USAGE_LEARNING;
-
-        /* old logic */
-       switch (mode) {
-       case ULTRA_SAVING_MODE:
-               /* Fall through */
-       case POWER_SAVING_MODE:
-               result = (double)ret * default_mode_factor[mode];
-               return (int)result;
-       case POWER_NORMAL_MODE:
-               /* Fall through */
-       default:
-               return ret;
-       }
-}
-
-static void dbus_get_battery_remaining_time(GDBusMethodInvocation *invocation, GVariant *params)
-{
-       int ret, mode = -1;
-
-       do_expr_unless_g_variant_get_typechecked(goto failure, params, "(i)", &mode);
-       if (mode < 0) {
-               _E("Wrong message arguments!");
-               goto failure;
-       }
-
-       if (!battery_learning_mode)
-               battery_learning_mode = heart_battery_get_learning_mode();
-
-       if (!battery_learning_mode) {
-               _E("data is not enough to calculate prediction");
-               ret = BATTERY_USAGE_LEARNING;
-       } else {
-               if (batt_stat.curr_capacity <= 0) {
-                       _I("Last capacity read may not be proper so read again");
-                       batt_stat.curr_capacity = heart_battery_direct_get_capacity();
-                       if (batt_stat.curr_capacity <= 0) {
-                               /*
-                                * still not proper ? return learning mode
-                                */
-                               ret = BATTERY_USAGE_LEARNING;
-                       } else {
-                               heart_battery_cal_discharge_rem_time();
-                               ret = get_battery_remaining_time(mode, DISCHARGING);
-                       }
-               } else {
-                       ret = get_battery_remaining_time(mode, DISCHARGING);
-               }
-       }
-
-       _I("Remaining_time %d (mode: %d)", ret, mode);
-       g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", ret));
-       return;
-
-failure:
-       D_BUS_REPLY_ERR(invocation);
-}
-
-static void dbus_get_battery_charging_time(GDBusMethodInvocation *invocation, GVariant *params)
-{
-       int ret = get_battery_remaining_time(POWER_NORMAL_MODE, CHARGING);
-       _I("Remaining_charging_time %d", ret);
-       g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", ret));
-}
-
-static void dbus_get_battery_discharge_rate_level(GDBusMethodInvocation *invocation, GVariant *params)
-{
-       int ret = batt_stat.discharge_rate_level;
-       _I("discharge_rate_level %d", ret);
-       g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", ret));
-}
-
-static void dbus_battery_save_to_file(GDBusMethodInvocation *invocation, GVariant *params)
-{
-       heart_battery_status_save_to_db();
-
-       int ret = heart_battery_capacity_save_to_file(HEART_BATTERY_CAPACITY_DATA_FILE);
-       if (ret) {
-               _E("save to file failed");
-               D_BUS_REPLY_ERR(invocation)
-               return;
-       }
-
-       g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", ret));
-}
-
-static const char dbus_methods_xml[] =
-"              <method name='GetBatteryCapacityHistory'>"
-"                      <arg type='i' name='Period' direction='in'/>"
-"                      <arg type='a(iii)' name='CapacityHistory' direction='out'/>"
-"              </method>"
-"              <method name='GetBatteryCapacityHistoryLatest'>"
-"                      <arg type='i' name='Charge' direction='in'/>"
-"                      <arg type='i' name='MaxSize' direction='in'/>"
-"                      <arg type='a(iii)' name='CapacityHistory' direction='out'/>"
-"              </method>"
-"              <method name='GetBatteryUsedTime'>"
-"                      <arg type='i' name='UsedTime' direction='out'/>"
-"              </method>"
-"              <method name='GetBatteryRemainingTime'>"
-"                      <arg type='i' name='Mode' direction='in'/>"
-"                      <arg type='i' name='RemainingTime' direction='out'/>"
-"              </method>"
-"              <method name='GetBatteryChargingTime'>"
-"                      <arg type='i' name='ChargingTime' direction='out'/>"
-"              </method>"
-"              <method name='GetBatteryDischargeRateLevel'>"
-"                      <arg type='i' name='DischargeRateLevel' direction='out'/>"
-"              </method>"
-"              <method name='SaveBatteryData'>"
-"                      <arg type='i' name='ZeroOnSuccess' direction='out'/>"
-"              </method>";
-
-static struct d_bus_method dbus_methods[] = {
-       { "GetBatteryCapacityHistory",       dbus_get_battery_capacity_history },
-       { "GetBatteryCapacityHistoryLatest", dbus_get_battery_capacity_history_latest },
-       { "GetBatteryUsedTime",              dbus_get_battery_used_time },
-       { "GetBatteryRemainingTime",         dbus_get_battery_remaining_time },
-       { "GetBatteryChargingTime",          dbus_get_battery_charging_time },
-       { "GetBatteryDischargeRateLevel",    dbus_get_battery_discharge_rate_level },
-       { "SaveBatteryData",                 dbus_battery_save_to_file },
-};
-
-/* =========================  DBUS interface END ==================== */
-static void heart_battery_used_time_init(enum charger_status_type status)
-{
-       batt_used.last_charger_status = status;
-       batt_used.last_update_time = logging_get_time(CLOCK_BOOTTIME);
-}
-
-static void heart_battery_status_init(void)
-{
-       int i, ret, status, capacity;
-
-       batt_stat.curr_capacity = 0;
-       batt_stat.curr_run_time_sec[DISCHARGING] = 0;
-       batt_stat.curr_run_time_sec[CHARGING] = 0;
-       batt_stat.curr_cap_counter[DISCHARGING] = 0;
-       batt_stat.curr_cap_counter[CHARGING] = 0;
-       batt_stat.curr_charger_status = 0;
-       batt_stat.reset_mark = 0;
-
-       for (i = 0; i < BATTERY_HISTORY_RESET_MAX; i++) {
-               heart_battery_set_usage_reset_stime(i, 0);
-               heart_battery_set_usage_reset(i, DISCHARGING, 0, 0);
-               heart_battery_set_usage_reset(i, CHARGING, 0, 0);
-       }
-
-
-       for (i = 0; i < BATTERY_LEVEL_MAX; i++) {
-               heart_battery_set_usage_level_stime(i, 0);
-               heart_battery_set_usage_level(i, DISCHARGING, default_sec_per_cap[DISCHARGING][DEFAULT_AVG], 0);
-               heart_battery_set_usage_level(i, CHARGING, default_sec_per_cap[CHARGING][DEFAULT_AVG], 0);
-       }
-
-       for (i = 0; i < BATTERY_HISTORY_DAY_MAX; i++) {
-               heart_battery_set_usage_week_stime(i, 0);
-               heart_battery_set_usage_week(i, DISCHARGING, 0, 0);
-               heart_battery_set_usage_week(i, CHARGING, 0, 0);
-       }
-
-       for (i = 0; i < MAX_STRATEGY; i++) {
-               heart_battery_set_prediction(i, DISCHARGING, 0, 0, 0);
-               heart_battery_set_prediction(i, CHARGING, 0, 0, 0);
-       }
-
-       ret = heart_battery_status_read_from_db();
-       if (ret < 0)
-               _E("Failed to read battery status data");
-
-       if (logic_v2) {
-               for (i = 0; i < INDEX_WINDOW_SIZE; i++) {
-                       batt_stat.last_wall_time[i] = 0;
-                       batt_stat.last_volt_intg[i] = 0.0;
-               }
-               for (i = 0; i < BATTERY_LEVEL_GAP; i++)
-                       batt_stat.last_wall_time_chg_diff[i] = 0;
-
-               batt_stat.data_available = 0;
-               batt_stat.last_capacity = 0;
-               batt_stat.last_capacity_chg = 0;
-               first_level_change = FALSE;
-               batt_stat.curr_index = 0;
-               batt_stat.remaining_time = 0;
-               batt_stat.remaining_time_ups = 0;
-               batt_stat.last_pwr_bchg = average_pwr;
-               batt_stat.last_wall_time_chg = 0;
-               batt_stat.index_chg = 0;
-               batt_stat.remaining_time_chg = 0;
-               batt_stat.last_clock_tick =  logging_get_time(CLOCK_BOOTTIME);
-               for (i = 0; i < INDEX_WINDOW_SIZE; i++)
-                       batt_stat.pvt.total_dischg_time[i] = 0;
-               batt_stat.pvt.pvt_data_ind = 0;
-               batt_stat.pvt.start_cap_dischg = 0;
-               batt_stat.pvt.start_time_dischg = 0;
-               batt_stat.pvt.last_clock_tick = 0;
-
-               /* During the device boot-up, calculate energy for 100% battery and calcuate
-               pivot(norma and UPS mode) for time remaining time estimation*/
-               heart_battery_calculate_pivot();
-               /*get all the previousely stored data from file to program variable*/
-               heart_battery_read_data_from_file();
-               /* get all the previosly stored pivot info */
-               heart_battery_read_pivot_info_from_file();
-               /* if enough pivot data present then update the pivot */
-               heart_battery_update_pivot();
-               /*
-               * check whether was device power off for long time. If yes then adjust
-               * our stored time values
-               */
-               heart_battery_power_off_time_adjustment();
-               /*
-               * register callback for any time change from user side.
-               * If any time change happen then adjust whole data as per new time
-               */
-               vconf_notify_key_changed(VCONFKEY_SETAPPL_TIMEZONE_INT, time_change_notify_cb, NULL);
-               vconf_notify_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED, time_change_notify_cb, NULL);
-               vconf_notify_key_changed(VCONFKEY_REGIONFORMAT, time_change_notify_cb, NULL);
-       }
-
-       battery_learning_mode = heart_battery_get_learning_mode();
-
-       ret = heart_battery_capacity_read_from_file(HEART_BATTERY_CAPACITY_DATA_FILE);
-       if (ret < 0)
-               _E("Failed to read battery capacity data");
-
-       capacity = heart_battery_direct_get_capacity();
-       status = heart_battery_direct_get_charger_status();
-
-       /*
-        * Consider power off charing mode
-        * If new capacity is higher than old capacity and it is full, reset heart data
-        */
-       if (capacity > batt_stat.curr_capacity && status == DISCHARGING && capacity >= 90)
-               heart_battery_reset(NULL);
-       else
-               heart_battery_used_time_init(batt_stat.curr_charger_status);
-
-       if (capacity > 0)
-               batt_stat.curr_capacity = capacity;
-       if (status >= 0)
-               batt_stat.curr_charger_status = status;
-
-       heart_battery_calculate_prediction(batt_stat.curr_charger_status);
-       batt_stat.last_event_wall_time = logging_get_time(CLOCK_BOOTTIME);
-       batt_stat.discharge_rate_level = BATTERY_DISCHARGE_NONE;
-
-       if (logic_v2) {
-               heart_battery_cal_discharge_rem_time();
-
-               if (batt_stat.curr_charger_status == CHARGING) {
-                       heart_battery_cal_charging_rem_time();
-                       first_level_change = TRUE;
-               } else {
-                       heart_battery_collect_discharge_data();
-               }
-       }
-}
-
-static int low_battery_handler(void *data)
-{
-       heart_battery_save_to_file(false);
-       return RESOURCED_ERROR_NONE;
-}
-
-static int heart_battery_config(struct parse_result *result, void *user_data)
-{
-       int val;
-       int battery_capacity = 0;
-
-       if (!result)
-               return -EINVAL;
-
-       if (!strncmp(result->section, HEART_BATTERY_CONF_SECTION, sizeof(HEART_BATTERY_CONF_SECTION) + 1)) {
-               if (!strncmp(result->name, "POWER_NORMAL_MODE", sizeof("POWER_NORMAL_MODE") + 1)) {
-                       val = atoi(result->value);
-                       if (val > 0)
-                               default_mode_spc[POWER_NORMAL_MODE] = val;
-                       _D("POWER_NORMAL_MODE SPC: %d", val);
-               } else if (!strncmp(result->name, "POWER_SAVING_MODE", sizeof("POWER_SAVING_MODE") + 1)) {
-                       val = atoi(result->value);
-                       if (val > 0)
-                               default_mode_spc[POWER_SAVING_MODE] = val;
-                       _D("POWER_SAVING_MODE SPC: %d", val);
-               } else if (!strncmp(result->name, "ULTRA_SAVING_MODE", sizeof("ULTRA_SAVING_MODE") + 1)) {
-                       val = atoi(result->value);
-                       if (val > 0)
-                               default_mode_spc[ULTRA_SAVING_MODE] = val;
-                       _D("ULTRA_POWER_SAVING_MODE SPC: %d", val);
-               }
-       } else if (!strncmp(result->section, battery_header, sizeof(battery_header) + 1)) {
-               if (!strncmp(result->name, "LOGIC_V2", sizeof("LOGIC_V2") + 1)) {
-                       logic_v2 = atoi(result->value);
-                       _I("logic_v2 : %d", logic_v2);
-               } else if (!strncmp(result->name, "LOGIC_RUL", sizeof("LOGIC_RUL") + 1)) {
-                       logic_rul = atoi(result->value);
-                       _I("logic_rul : %d", logic_rul);
-               } else if (!strncmp(result->name, "BATTERY_CAPACITY", sizeof("BATTERY_CAPACITY") + 1)) {
-                       battery_capacity = atoi(result->value);
-                       _I("total battery capacity: %d", battery_capacity);
-
-                       if(total_battery_capacity == 0 && !battery_capacity) {
-                               /* sys interface battery capacity path not found, read from conf file */
-                               total_battery_capacity = battery_capacity * 60; /* mAm */
-                       }
-               } else if (!strncmp(result->name, "DISCHARGE_FAST", sizeof("DISCHARGE_FAST") + 1)) {
-                       discharge_fast = atoi(result->value);
-                       _I("discharge_fast: %d", discharge_fast);
-               } else if (!strncmp(result->name, "DISCHARGE_SLOW", sizeof("DISCHARGE_SLOW") + 1)) {
-                       discharge_slow = atoi(result->value);
-                       _I("discharge_slow: %d", discharge_slow);
-               } else if (!strncmp(result->name, "AVERAGE_PWR", sizeof("AVERAGE_PWR") + 1)) {
-                       average_pwr = atof(result->value);
-                       _I("average_power: %lf", average_pwr);
-               } else if (!strncmp(result->name, "OCV_SOC_POLY_COEF", sizeof("OCV_SOC_POLY_COEF") + 1)) {
-                       char *token, *saveptr = NULL;
-                       int i;
-                       token = strtok_r(result->value, " ", &saveptr);
-                       if (token) {
-                               ocv_degree = atoi(token);
-                               if (ocv_degree <= 0) {
-                                       _E("ocv_degree should be positive if you decide to use logic_v2");
-                                       return -EINVAL;
-                               }
-                               intg = calloc(ocv_degree, sizeof(double));
-                               if (!intg) {
-                                       _E("Out of memory");
-                                       return -ENOMEM;
-                               }
-                               _I("Degree of OCV_SOC_POLY = %d", ocv_degree);
-
-                               for (i = 0; i < ocv_degree; i++) {
-                                       token = strtok_r(NULL, " ", &saveptr);
-                                       if (!token) {
-                                               _E("There is no OCV_SOC_POLY_COEF_%d", i + 1);
-                                               return -EINVAL;
-                                       }
-                                       intg[i] = atof(token);
-                                       _I("OCV_SOC_POLY_COEF_%d = %.9g", i + 1, intg[i]);
-                               }
-                       }
-               }
-       }  else if (!strncmp(result->section, "POWER_PROFILE", sizeof("POWER_PROFILE") + 1)) {
-               if (!strncmp(result->name, "WIFI_ACTIVE", sizeof("WIFI_ACTIVE") + 1)) {
-                       power_profile.wifi_active = atof(result->value);
-                       _D("HEART WIFI_ACTIVE: %f", power_profile.wifi_active);
-               } else if (!strncmp(result->name, "WIFI_ON", sizeof("WIFI_ON") + 1)) {
-                       power_profile.wifi_on = atof(result->value);
-                       _D("HEART WIFI_ON: %f", power_profile.wifi_on);
-               }
-       }
-       return RESOURCED_ERROR_NONE;
-}
-
-static void heart_battery_mode_factor_init(void)
-{
-       double val;
-
-       val = default_mode_spc[POWER_SAVING_MODE]/default_mode_spc[POWER_NORMAL_MODE];
-
-       if (1.0 < val)
-               default_mode_factor[POWER_SAVING_MODE] = val;
-       _I("POWER_SAVING_MODE factor: %f", val);
-
-       val = default_mode_spc[ULTRA_SAVING_MODE]/default_mode_spc[POWER_NORMAL_MODE];
-
-       if (1.0 < val)
-               default_mode_factor[ULTRA_SAVING_MODE] = val;
-       _I("ULTRA_POWER_SAVING_MODE factor: %f", val);
-}
-
-/*
- * This function will read total battery capacity from sys interface
- * example - 1500mAh or 2600mAh
- */
-static void heart_read_battery_total_capacity(void)
-{
-       u_int32_t batt_capacity;
-
-       /*
-        * read the battery total capacity from sys interface path
-        * "/sys/class/power_supply/battery/batt_capacity"
-        * which is provided by kernel
-        */
-       if (fread_uint("/sys/class/power_supply/battery/batt_capacity",
-                                       &batt_capacity) != RESOURCED_ERROR_NONE) {
-               _D("This device doesn't support battery capacity information. Disable LOGIC_V2");
-               return;
-       }
-
-       snprintf(battery_header, sizeof(battery_header), "BATTERY_%d",
-                       batt_capacity);
-
-       /*
-        * convert battery capacity from mAh to mAm
-        */
-       total_battery_capacity = batt_capacity * 60;
-       _I("battery capacity = %d, battery header = %s",
-                       batt_capacity, battery_header);
-}
-
-/* Database related operations for heart-battery tables */
-
-static int heart_battery_stats_init_db(void)
-{
-       sqlite3 *battery_stats_db;
-       char *err_msg = NULL;
-       char buf[HEART_BATTERY_STATS_MAX] = {0, };
-       int ret;
-
-       ret = sqlite3_open(BATTERY_STATS_DB_FILE_NAME, &battery_stats_db);
-       if (ret != SQLITE_OK) {
-               _E("Can't open database %s: %s", BATTERY_STATS_DB_FILE_NAME,
-                  sqlite3_errmsg(battery_stats_db));
-               goto error_db_open;
-       }
-
-       snprintf(buf, HEART_BATTERY_STATS_MAX, "%s", QUERY_CREATE_BATTERY_STATS);
-       ret = sqlite3_exec(battery_stats_db, buf, NULL, NULL, &err_msg);
-       if (ret != SQLITE_OK) {
-               _E("create failed: %s", err_msg);
-               sqlite3_free(err_msg);
-               goto error_db_open;
-       }
-       _I("Create db Success");
-
-error_db_open:
-       sqlite3_close(battery_stats_db);
-       return ret;
-}
-
-static int heart_battery_stats_db_open_transaction(sqlite3 *db)
-{
-       char *err_msg = NULL;
-
-       if (sqlite3_exec(db, "PRAGMA journal_mode = PERSIST", NULL, NULL, &err_msg) != SQLITE_OK) {
-               _E("sqlite3_exec(\"PRAGMA journal_mode = PERSIST\") failed! -> %s", err_msg);
-               sqlite3_free(err_msg);
-               return RESOURCED_ERROR_DB_FAILED;
-       }
-
-       if (sqlite3_exec(db, "BEGIN EXCLUSIVE", NULL, NULL, &err_msg) != SQLITE_OK) {
-               _E("sqlite3_exec(\"BEGIN EXCLUSIVE\") failed! -> %s", err_msg);
-               sqlite3_free(err_msg);
-               return RESOURCED_ERROR_DB_FAILED;
-       }
-
-       return RESOURCED_ERROR_NONE;
-}
-
-int heart_battery_stats_execute_insert_db(char buf[])
-{
-       sqlite3 *battery_stats_db;
-       char *err_msg = NULL;
-       int ret;
-
-       if (sqlite3_open(BATTERY_STATS_DB_FILE_NAME, &battery_stats_db) != SQLITE_OK) {
-               _E("Can't open database %s: %s", BATTERY_STATS_DB_FILE_NAME,
-                  sqlite3_errmsg(battery_stats_db));
-               return RESOURCED_ERROR_DB_FAILED;
-       }
-       ret = heart_battery_stats_db_open_transaction(battery_stats_db);
-       if (ret != RESOURCED_ERROR_NONE)
-               goto error_close;
-
-       if (sqlite3_exec(battery_stats_db, buf, NULL, NULL, &err_msg) != SQLITE_OK) {
-               _E("sqlite3_exec(\"%s\") failed! -> %s", buf, err_msg);
-               sqlite3_free(err_msg);
-               goto error_db;
-       }
-
-       if (sqlite3_exec(battery_stats_db, "COMMIT", NULL, NULL, NULL) != SQLITE_OK) {
-               _E("sqlite3_exec(\"COMMIT\") failed!");
-               goto error_db;
-       }
-       _I("QUERY: %s SUCCESS", buf);
-
-       sqlite3_close(battery_stats_db);
-       return RESOURCED_ERROR_NONE;
-
-error_db:
-       if (sqlite3_exec(battery_stats_db, "ROLLBACK", NULL, NULL, NULL) != SQLITE_OK)
-               _E("sqlite3_exec(\"ROLLBACK\") failed!");
-       _I("QUERY: %s FAILED", buf);
-error_close:
-       sqlite3_close(battery_stats_db);
-       return RESOURCED_ERROR_DB_FAILED;
-}
-
-long heart_battery_stats_execute_select_total_db(char buf[])
-{
-       sqlite3 *battery_stats_db;
-       sqlite3_stmt *stmt;
-       long totaltime = 0;
-       int ret;
-
-       if (sqlite3_open(BATTERY_STATS_DB_FILE_NAME, &battery_stats_db) != SQLITE_OK) {
-               _E("Can't open database %s: %s", BATTERY_STATS_DB_FILE_NAME,
-                  sqlite3_errmsg(battery_stats_db));
-               return 0;
-       }
-
-       ret = sqlite3_prepare_v2(battery_stats_db, buf, -1, &stmt, NULL);
-       if (ret != SQLITE_OK) {
-               _E("Failed to prepare query %s", sqlite3_errmsg(battery_stats_db));
-               goto error_db;
-       }
-
-       ret = sqlite3_step(stmt);
-       switch (ret) {
-       case SQLITE_ROW:
-               _I("QUERY: %s SUCCESS", buf);
-               totaltime = (long)sqlite3_column_int(stmt, 0);
-               _D("totaltime: (%ld)", totaltime);
-               break;
-       case SQLITE_DONE:
-               _D("SQLITE_DONE");
-               break;
-       case SQLITE_ERROR:
-               /* FALLTHROUGH */
-               _E("sqlite3_step failed %s", sqlite3_errmsg(battery_stats_db));
-       default:
-               _E("RESOURCED_ERROR_DB_FAILED");
-               break;
-       }
-       sqlite3_finalize(stmt);
-error_db:
-       sqlite3_close(battery_stats_db);
-       return totaltime;
-}
-
-static void rul_data_init(void)
-{
-       _cleanup_fclose_ FILE *fp = NULL;
-       int ret, check;
-
-       rul.charging_start_time = 0;
-       rul.charging_stop_time = 0;
-       rul.raw_capacity = 0;
-       rul.soc_start = 0;
-       rul.soc_stop = 0;
-       rul.curr_soc = heart_battery_direct_get_capacity();
-       rul.prev_soc = rul.curr_soc;
-
-       /* Init LCD related data */
-       rul.lcd_data.on_start_time = 0;
-       rul.lcd_data.on_stop_time = 0;
-       rul.lcd_data.on_time = 0;
-       ret = device_display_get_state(&rul.lcd_data.state);
-       if (ret != DEVICE_ERROR_NONE) {
-               _E("Failed to get device display state with err = %d", ret);
-               return;
-       }
-
-       /* Register callback for LCD state change */
-       check = device_add_callback(DEVICE_CALLBACK_DISPLAY_STATE, rul_display_state_changed_cb, NULL);
-       if (check != DEVICE_ERROR_NONE) {
-               _E("Failed to add calback with err = %d", check);
-               //TODO: consider "rul.charging_cycles = 0;"
-               return;
-       }
-
-       /* Read Charging cycles count from file */
-       fp = fopen(RUL_CHARGING_CYCLES_FILE, "r");
-       if (fp == NULL) {
-               _E("Can't open RUL_CHARGING_CYCLES_FILE");
-               rul.charging_cycles = 0;
-               return;
-       }
-
-       if (fscanf(fp, "%d", &rul.charging_cycles) != 1) {
-               _E("Unable to assign charging cycles from file");
-               rul.charging_cycles = 0;
-               return;
-       }
-}
-
-static int heart_battery_init(void *data)
-{
-       int ret;
-       bool supported;
-
-       ret = system_info_get_platform_bool("tizen.org/feature/battery", &supported);
-       if (ret != SYSTEM_INFO_ERROR_NONE || !supported) {
-               return RESOURCED_ERROR_NOTIMPL;
-       }
-
-       ret = heart_battery_stats_init_db();
-       if (ret != RESOURCED_ERROR_NONE) {
-               _E("heart module init failed at db creation");
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       heart_dbus_declare_methods(dbus_methods_xml, dbus_methods, ARRAY_SIZE(dbus_methods));
-
-       ret = d_bus_register_signal(DEVICED_PATH_BATTERY,
-                       DEVICED_INTERFACE_BATTERY, GET_BATTERY_CAPACITY,
-                       heart_battery_capacity_status, NULL);
-       if (ret < 0)
-               _E("heart module failed to add a capacity status signal handler");
-
-       ret = d_bus_register_signal(DEVICED_PATH_BATTERY,
-                       DEVICED_INTERFACE_BATTERY, GET_CHARGER_STATUS,
-                       heart_battery_charger_status, NULL);
-       if (ret < 0)
-               _E("heart module failed to add a charger status signal handler");
-
-       heart_read_battery_total_capacity();
-
-       config_parse(HEART_CONF_FILE_PATH, heart_battery_config, NULL);
-       _I("heart config init");
-
-
-       heart_battery_mode_factor_init();
-
-       heart_battery_status_init();
-
-       if (logic_rul)
-               rul_data_init();
-
-       register_notifier(RESOURCED_NOTIFIER_LOW_BATTERY, low_battery_handler);
-       register_notifier(RESOURCED_NOTIFIER_DATA_RESET, heart_battery_reset);
-
-       heart_battery_set_file_commit_timestamp(logging_get_time(CLOCK_BOOTTIME));
-
-       ret = logging_module_init(BATTERY_NAME, ONE_DAY, TEN_MINUTE, heart_battery_update,
-                                                       HEART_BATTERY_UPDATE_INTERVAL, SYSTEM_DEFAULT);
-       if (ret != RESOURCED_ERROR_NONE) {
-               _E("logging module init failed");
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       _D("heart battery init finished");
-       return RESOURCED_ERROR_NONE;
-}
-
-void heart_capacity_history_update(struct logging_table_form *data, void *user_data)
-{
-       int status, reset, capacity, diff;
-       unsigned long discharging = 0, charging = 0;
-       GSList **history_list = NULL;
-
-       if (user_data)
-               history_list = (GSList **)user_data;
-       else
-               history_list = &capacity_history_list;
-
-       _D("%s %s %ld %s", data->appid, data->pkgid, data->time, data->data);
-       if (sscanf(data->data, "%d %d %ld %ld %d %d ",
-                               &capacity, &diff,
-                               &discharging, &charging,
-                               &status, &reset) < 0) {
-               _E("sscanf failed");
-               return;
-       }
-       heart_battery_insert_capacity(history_list, capacity,
-                       diff, data->time, discharging, charging, status,
-                       reset, false);
-}
-
-static int heart_battery_dump(FILE *fp, int mode, void *data)
-{
-       struct heart_battery_capacity *lbc;
-       GSList *iter;
-       char buf[BATTERY_DATA_MAX] = {0, };
-       int ret, size, len = 0;
-       time_t starttime;
-       char timestr[80];
-       struct tm loc_tm;
-       GSList *history_list = NULL;
-
-       starttime = time(NULL);
-       starttime -= mode;
-       localtime_r(&starttime, &loc_tm);
-       /* print timestamp */
-       strftime(timestr, sizeof(timestr),
-                       "%Y-%m-%d %H:%M:%S%z", &loc_tm);
-
-       logging_read_foreach(BATTERY_NAME, NULL, NULL, starttime, 0,
-                       heart_capacity_history_update, &history_list);
-
-       if (!history_list) {
-               _E("capacity history is NULL!");
-               return RESOURCED_ERROR_NONE;
-       }
-       LOG_DUMP(fp, "[BATTERY CAPACITY HISTORY] since %s\n", timestr);
-       LOG_DUMP(fp, "capacity diff timestamp used_time charging_time charger_status, reset_mark\n");
-       ret = pthread_mutex_lock(&heart_battery_mutex);
-       if (ret) {
-               _E("pthread_mutex_lock() failed, %d", ret);
-               return RESOURCED_ERROR_FAIL;
-       }
-       size = g_slist_length(history_list);
-       if (!size) {
-               _I("capacity history is empty");
-               ret = pthread_mutex_unlock(&heart_battery_mutex);
-               if (ret) {
-                       _E("pthread_mutex_unlock() failed, %d", ret);
-                       return RESOURCED_ERROR_FAIL;
-               }
-               return RESOURCED_ERROR_NONE;
-       }
-       gslist_for_each_item(iter, history_list) {
-               lbc = (struct heart_battery_capacity *)iter->data;
-               if (!lbc)
-                       break;
-               len += snprintf(buf + len, BATTERY_DATA_MAX - len, "%d %d %ld %ld %ld %d %d\n",
-                               lbc->capacity, lbc->diff_capacity, lbc->timestamp, lbc->used_time,
-                               lbc->charging_time, lbc->charger_status,
-                               lbc->reset_mark);
-               if (BATTERY_DATA_MAX < len + BATTERY_LINE_MAX) {
-                       LOG_DUMP(fp, "%s\n", buf);
-                       len = 0;
-               }
-       }
-       LOG_DUMP(fp, "%s\n", buf);
-       ret = pthread_mutex_unlock(&heart_battery_mutex);
-       if (ret) {
-               _E("pthread_mutex_unlock() failed, %d", ret);
-               return RESOURCED_ERROR_FAIL;
-       }
-       fflush(fp);
-       if (history_list) {
-               g_slist_free_full(history_list, free);
-               history_list = NULL;
-       }
-
-       return RESOURCED_ERROR_NONE;
-}
-
-static int heart_battery_exit(void *data)
-{
-       int ret;
-       GSList *iter, *next;
-       struct heart_battery_capacity *lbc;
-
-       heart_battery_save_to_file(true);
-       ret = pthread_mutex_lock(&heart_battery_mutex);
-       if (ret)
-               _E("pthread_mutex_lock() failed, %d", ret);
-
-       gslist_for_each_safe(capacity_history_list, iter, next, lbc) {
-               capacity_history_list = g_slist_remove(capacity_history_list, lbc);
-               free(lbc);
-       }
-       capacity_history_list = NULL;
-
-       ret = pthread_mutex_unlock(&heart_battery_mutex);
-       if (ret)
-               _E("pthread_mutex_unlock() failed, %d", ret);
-
-       unregister_notifier(RESOURCED_NOTIFIER_LOW_BATTERY, low_battery_handler);
-       unregister_notifier(RESOURCED_NOTIFIER_DATA_RESET, heart_battery_reset);
-
-       logging_module_exit();
-
-       _D("heart battery exit");
-       return RESOURCED_ERROR_NONE;
-}
-
-static const struct heart_module_ops heart_battery_ops = {
-       .name           = "BATTERY",
-       .init           = heart_battery_init,
-       .dump           = heart_battery_dump,
-       .exit           = heart_battery_exit,
-};
-HEART_MODULE_REGISTER(&heart_battery_ops)
diff --git a/src/resource-monitor/cpu/heart-cpu.c b/src/resource-monitor/cpu/heart-cpu.c
deleted file mode 100644 (file)
index 39bed76..0000000
+++ /dev/null
@@ -1,1495 +0,0 @@
-/*
- * resourced
- *
- * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * @file heart-cpu.c
- *
- * @desc heart cpu module
- *
- * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <glib.h>
-#include <math.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include "proc-common.h"
-#include "notifier.h"
-#include "resourced.h"
-#include "dbus-handler.h"
-#include "heart.h"
-#include "logging.h"
-#include "heart-common.h"
-#include "trace.h"
-#include "module.h"
-#include "macro.h"
-#include "userinfo-list.h"
-#include "proc-main.h"
-
-#define PROC_PATH                              "/proc/%d"
-#define PROC_STAT_PATH                         "/proc/%d/stat"
-#define CPU_NAME                               "cpu"
-#define CPU_DATA_MAX                           1024
-#define CPU_ARRAY_MAX                          24
-#define HEART_CPU_SAVE_INTERVAL                        3600
-#define HEART_CPU_DATA_FILE                    HEART_USER_FILE_PATH"/.cpu.dat"
-
-enum {
-       SERVICE = 0,
-       FOREG = 1,
-       BACKG = 2
-};
-
-struct heart_cpu_info {
-       unsigned long utime;
-       unsigned long stime;
-       int state;
-       pid_t pid;
-};
-
-struct heart_cpu_table {
-       char appid[MAX_APPID_LENGTH];
-       char pkgid[MAX_PKGNAME_LENGTH];
-       unsigned long total_utime;
-       unsigned long total_stime;
-       unsigned long utime;
-       unsigned long stime;
-       int fg_count;
-       unsigned long fg_time;
-       unsigned long bg_time;
-       GSList *last_pid_info;
-       pid_t last_pid;
-       time_t last_renew_time;
-       GArray *cpu_info;
-};
-
-struct heart_cpu_dat_cache {
-       char *path;
-       GHashTable *list;
-       time_t last_file_commit_time;
-};
-
-static GHashTable *heart_cpu_app_list;
-static pthread_mutex_t heart_cpu_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-static void heart_cpu_remove_last_pid_info_exited(struct heart_cpu_table *table)
-{
-       char proc_path[sizeof(PROC_PATH) + MAX_DEC_SIZE(int)];
-       GSList *iter, *next;
-       struct heart_cpu_info *ci = NULL;
-
-       if (!table || !table->last_pid_info)
-               return;
-
-       gslist_for_each_safe(table->last_pid_info, iter, next, ci) {
-               snprintf(proc_path, sizeof(proc_path), PROC_PATH, ci->pid);
-               if (!access(proc_path, F_OK))
-                       continue;
-               table->last_pid_info = g_slist_remove(table->last_pid_info, ci);
-               free(ci);
-       }
-}
-
-static struct heart_cpu_info *find_pid_info(struct heart_cpu_table *table, pid_t pid)
-{
-       GSList *iter = NULL;
-       struct heart_cpu_info *ci = NULL;
-
-       if (!table || !table->last_pid_info)
-               return NULL;
-
-       gslist_for_each_item(iter, table->last_pid_info) {
-               ci = (struct heart_cpu_info *)iter->data;
-               if (ci && ci->pid == pid)
-                       return ci;
-       }
-       return NULL;
-}
-
-static int heart_cpu_get_cpu_time(pid_t pid, unsigned long *utime,
-               unsigned long *stime)
-{
-       char proc_path[sizeof(PROC_STAT_PATH) + MAX_DEC_SIZE(int)];
-       FILE *fp;
-
-       assert(utime != NULL);
-       assert(stime != NULL);
-
-       snprintf(proc_path, sizeof(proc_path), PROC_STAT_PATH, pid);
-       fp = fopen(proc_path, "r");
-       if (fp == NULL)
-               return RESOURCED_ERROR_FAIL;
-
-       if (fscanf(fp, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s") < 0) {
-               fclose(fp);
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       if (fscanf(fp, "%lu %lu", utime, stime) < 1) {
-               fclose(fp);
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       fclose(fp);
-
-       return RESOURCED_ERROR_NONE;
-}
-
-static GHashTable* heart_cpu_get_user_app_list(int uid)
-{
-       struct heart_cpu_dat_cache *cache;
-
-       cache = (struct heart_cpu_dat_cache*)g_hash_table_lookup(heart_cpu_app_list, (gconstpointer)&uid);
-       if (!cache) {
-               _E("There is no table of uid %d", uid);
-               return NULL;
-       }
-
-       return cache->list;
-}
-
-static int heart_cpu_write_data(struct proc_status *ps, pid_t pid, int type)
-{
-       int ret;
-       unsigned long utime, stime;
-       char info[CPU_DATA_MAX];
-       char *appid, *pkgid;
-
-       ret = heart_cpu_get_cpu_time(pid, &utime, &stime);
-       if (ret != RESOURCED_ERROR_NONE)
-               return ret;
-
-       snprintf(info, sizeof(info), "%lu %lu %d %d ", utime, stime, pid, type);
-
-       ret = proc_get_id_info(ps, &appid, &pkgid);
-       if (ret != RESOURCED_ERROR_NONE) {
-               _E("Failed to proc_get_id_info");
-               return ret;
-       }
-       ret = logging_write(pid, CPU_NAME, appid, pkgid, time(NULL), info);
-       _D("heart_cpu_write_data : pid = %d, appname = %s, pkgname = %s, type=%d",
-                       pid, appid, pkgid, type);
-       return ret;
-}
-
-static int heart_cpu_service_launch(void *data)
-{
-       int ret;
-       struct proc_status *ps = (struct proc_status *)data;
-
-       ret = heart_cpu_write_data(ps, ps->pid, SERVICE);
-       if (ret != RESOURCED_ERROR_NONE) {
-               _E("Failed to write cpu info %d", ps->pid);
-               return ret;
-       }
-       resourced_notify(RESOURCED_NOTIFIER_LOGGING_START, NULL);
-       return RESOURCED_ERROR_NONE;
-}
-
-static int heart_cpu_foreground_state(void *data)
-{
-       int ret;
-       struct proc_status *ps = (struct proc_status *)data;
-
-       ret = heart_cpu_write_data(ps, ps->pid, FOREG);
-       if (ret != RESOURCED_ERROR_NONE) {
-               _E("Failed to write cpu info %d", ps->pid);
-               return ret;
-       }
-       resourced_notify(RESOURCED_NOTIFIER_LOGGING_START, NULL);
-       return RESOURCED_ERROR_NONE;
-}
-
-static int heart_cpu_background_state(void *data)
-{
-       int ret;
-       GSList *giter = NULL;
-       struct proc_status *ps = (struct proc_status *)data;
-
-       ret = heart_cpu_write_data(ps, ps->pid, BACKG);
-       if (ret != RESOURCED_ERROR_NONE) {
-               _E("Failed to write cpu info %d", ps->pid);
-               return ret;
-       }
-       if (!ps->pai->childs)
-               return RESOURCED_ERROR_NONE;
-       gslist_for_each_item(giter, ps->pai->childs) {
-               pid_t child = GPOINTER_TO_PID(giter->data);
-               ret = heart_cpu_write_data(ps, child, BACKG);
-               if (ret != RESOURCED_ERROR_NONE) {
-                       _E("Failed to write child cpu info %d", child);
-                       return ret;
-               }
-       }
-       resourced_notify(RESOURCED_NOTIFIER_LOGGING_START, NULL);
-       return RESOURCED_ERROR_NONE;
-}
-
-static int heart_cpu_update_state(void *data)
-{
-       int ret, state;
-       GSList *giter = NULL;
-       struct proc_status *ps = (struct proc_status *)data;
-
-       if (!ps->pai) {
-               _E("Invalid parameter");
-               return RESOURCED_ERROR_INVALID_PARAMETER;
-       }
-       if (ps->pai->lru_state == PROC_FOREGROUND)
-               state = FOREG;
-       else
-               state = BACKG;
-
-       ret = heart_cpu_write_data(ps, ps->pid, state);
-       if (ret != RESOURCED_ERROR_NONE) {
-               _E("Failed to write cpu info %d", ps->pid);
-               return ret;
-       }
-       _D("heart_cpu_update_state : pid = %d, state = %d",
-                       ps->pid, state);
-       if (!ps->pai->childs)
-               return RESOURCED_ERROR_NONE;
-       gslist_for_each_item(giter, ps->pai->childs) {
-               pid_t child = GPOINTER_TO_PID(giter->data);
-               ret = heart_cpu_write_data(ps, child, state);
-               if (ret != RESOURCED_ERROR_NONE) {
-                       _E("Failed to write cpu info %d", child);
-                       return ret;
-               }
-       }
-       resourced_notify(RESOURCED_NOTIFIER_LOGGING_START, NULL);
-       return RESOURCED_ERROR_NONE;
-}
-
-static int heart_cpu_update_app_list(void *data)
-{
-       _cleanup_app_list_close_ GSList *proc_app_list = PAL_INIT_VALUE;
-       GSList *giter = NULL;
-       struct proc_app_info *pai = NULL;
-
-       proc_app_list = proc_app_list_open();
-       gslist_for_each_item(giter, proc_app_list) {
-               struct proc_status ps;
-               pai = (struct proc_app_info *)giter->data;
-               if (!pai->ai)
-                       continue;
-               ps.pid = pai->main_pid;
-               ps.pai = pai;
-               heart_cpu_update_state(&ps);
-       }
-       return RESOURCED_ERROR_NONE;
-}
-
-static void heart_cpu_free_uid(gpointer data)
-{
-       if (data)
-               free(data);
-}
-
-static void heart_cpu_free_dat_cache(gpointer data)
-{
-       struct heart_cpu_dat_cache *cache = (struct heart_cpu_dat_cache*)data;
-       if (cache) {
-               free(cache->path);
-               g_hash_table_destroy(cache->list);
-               free(cache);
-       }
-}
-
-static void heart_free_value(gpointer value)
-{
-       int i;
-       struct heart_cpu_info *info;
-       struct heart_cpu_table *table = (struct heart_cpu_table *)value;
-
-       if (!table)
-               return;
-
-       if (table->last_pid_info)
-               g_slist_free_full(table->last_pid_info, free);
-
-       if (table->cpu_info) {
-               for (i = 0; i < table->cpu_info->len; i++) {
-                       info = g_array_index(table->cpu_info,
-                                       struct heart_cpu_info *, i);
-                       free(info);
-               }
-               g_array_free(table->cpu_info, TRUE);
-       }
-
-       free(table);
-}
-
-static int heart_cpu_read_length(char *buf, int count)
-{
-       int i, find = 0;
-       int len = strlen(buf);
-
-       for (i = 0; i < len; i++) {
-               if (buf[i] == ' ')
-                       find++;
-               if (find == count)
-                       return i + 1;
-       }
-       return RESOURCED_ERROR_FAIL;
-}
-
-static int heart_cpu_read_from_file(struct heart_cpu_dat_cache *cache)
-{
-       int i, len, ret, fg_count, state;
-       unsigned long total_utime, total_stime;
-       unsigned long utime, stime;
-       unsigned long fg_time, bg_time;
-       pid_t pid;
-       FILE *fp;
-       struct heart_cpu_table *table;
-       char appid[MAX_APPID_LENGTH] = {0, };
-       char pkgid[MAX_PKGNAME_LENGTH] = {0, };
-       char buf[CPU_DATA_MAX] = {0, };
-
-       if (!cache) {
-               _E("Cache doesn't exist");
-               return RESOURCED_ERROR_INVALID_PARAMETER;
-       }
-
-       snprintf(buf, CPU_DATA_MAX, HEART_CPU_DATA_FILE, cache->path);
-       fp = fopen(buf, "r");
-       if (!fp) {
-               if (errno != ENOENT) {
-                       _E("Fail to open %s (%d)", buf, errno);
-                       return RESOURCED_ERROR_FAIL;
-               }
-
-               _D("%s doesn't exist. Make new one.", buf);
-               snprintf(buf, CPU_DATA_MAX, HEART_USER_FILE_PATH, cache->path);
-               ret = mkdir(buf, S_IRWXU | S_IRWXG | S_IROTH);
-               if (ret != 0 && errno != EEXIST) {
-                       _E("Fail to create %s (%d)", buf, errno);
-                       return RESOURCED_ERROR_FAIL;
-               }
-
-               snprintf(buf, CPU_DATA_MAX, HEART_CPU_DATA_FILE, cache->path);
-               fp = fopen(buf, "w+");
-               if (!fp) {
-                       _E("Fail to create %s (%d)", buf, errno);
-                       return RESOURCED_ERROR_FAIL;
-               }
-               fclose(fp);
-               return RESOURCED_ERROR_NONE;
-       }
-
-       while (fgets(buf, CPU_DATA_MAX, fp)) {
-               table = malloc(sizeof(struct heart_cpu_table));
-
-               if (!table) {
-                       _E("malloc failed");
-                       fclose(fp);
-                       return RESOURCED_ERROR_OUT_OF_MEMORY;
-               }
-
-               /* make return values */
-               ret = sscanf(buf, STR_FS(MAX_APPID_LENGTH_M1)" "STR_FS(MAX_PKGNAME_LENGTH_M1)" %lu %lu %lu %lu %lu %lu %d ",
-                               appid, pkgid,
-                               &total_utime, &total_stime,
-                               &utime, &stime,
-                               &fg_time, &bg_time, &fg_count);
-
-               if (ret <= 0) {
-                       _E("sscanf failed");
-                       free(table);
-                       fclose(fp);
-                       return RESOURCED_ERROR_FAIL;
-               }
-
-               if (snprintf(table->appid, MAX_APPID_LENGTH, "%s", appid) < 0) {
-                       _E("sprintf failed");
-                       free(table);
-                       fclose(fp);
-                       return RESOURCED_ERROR_OUT_OF_MEMORY;
-               }
-
-               if (snprintf(table->pkgid, MAX_PKGNAME_LENGTH, "%s", pkgid) < 0) {
-                       _E("snprintf failed");
-                       free(table);
-                       fclose(fp);
-                       return RESOURCED_ERROR_OUT_OF_MEMORY;
-               }
-               len = heart_cpu_read_length(buf, 9);
-               if (len <= 0) {
-                       _E("sscanf failed");
-                       free(table);
-                       fclose(fp);
-                       return RESOURCED_ERROR_FAIL;
-               }
-               table->total_utime = total_utime;
-               table->total_stime = total_stime;
-               table->utime = utime;
-               table->stime = stime;
-               table->last_pid_info = NULL;
-               table->last_pid = 0;
-               table->fg_time = fg_time;
-               table->bg_time = bg_time;
-               table->fg_count = fg_count;
-               table->last_renew_time = 0;
-               table->cpu_info =
-                       g_array_new(FALSE, FALSE, sizeof(struct heart_cpu_info *));
-
-               for (i = 0; i < CPU_ARRAY_MAX; i++) {
-                       struct heart_cpu_info *ci;
-
-                       ret = sscanf(buf + len, "%lu %lu %d %d ", &utime, &stime, &pid, &state);
-                       if (ret <= 0) {
-                               _E("file read fail %s", buf + len);
-                               free(table);
-                               fclose(fp);
-                               return RESOURCED_ERROR_FAIL;
-                       }
-                       ci = malloc(sizeof(struct heart_cpu_info));
-                       if (!ci) {
-                               free(table);
-                               fclose(fp);
-                               return RESOURCED_ERROR_OUT_OF_MEMORY;
-                       }
-                       ci->utime = utime;
-                       ci->stime = stime;
-                       ci->pid = pid;
-                       ci->state = state;
-                       len += heart_cpu_read_length(buf + len, 4);
-                       g_array_append_val(table->cpu_info, ci);
-               }
-
-               ret = pthread_mutex_lock(&heart_cpu_mutex);
-               if (ret) {
-                       _E("pthread_mutex_lock() failed, %d", ret);
-                       g_array_free(table->cpu_info, TRUE);
-                       free(table);
-                       fclose(fp);
-                       return RESOURCED_ERROR_FAIL;
-               }
-               g_hash_table_insert(cache->list, (gpointer)table->appid, (gpointer)table);
-               ret = pthread_mutex_unlock(&heart_cpu_mutex);
-               if (ret) {
-                       _E("pthread_mutex_unlock() failed, %d", ret);
-                       fclose(fp);
-                       return RESOURCED_ERROR_FAIL;
-               }
-       }
-
-       fclose(fp);
-
-       return RESOURCED_ERROR_NONE;
-}
-
-static int heart_cpu_save_to_file(struct heart_cpu_dat_cache *cache)
-{
-       int i, len, ret, array_len;
-       gpointer value;
-       gpointer key;
-       GHashTableIter iter;
-       struct heart_cpu_table *table;
-       FILE *fp;
-       char buf[CPU_DATA_MAX] = {0, };
-
-       if (!cache) {
-               _D("Cache is empty. Do nothing.");
-               return RESOURCED_ERROR_NONE;
-       }
-
-       snprintf(buf, CPU_DATA_MAX, HEART_CPU_DATA_FILE, cache->path);
-       fp = fopen(buf, "w");
-       if (!fp) {
-               _E("%s fopen failed %d", buf, errno);
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       if (!(cache->list)) {
-               _E("empty app list");
-               fclose(fp);
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       if (!g_hash_table_size(cache->list)) {
-               _E("hash table is empty");
-               fclose(fp);
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       ret = pthread_mutex_lock(&heart_cpu_mutex);
-       if (ret) {
-               _E("pthread_mutex_lock() failed, %d", ret);
-               fclose(fp);
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       g_hash_table_iter_init(&iter, cache->list);
-
-       while (g_hash_table_iter_next(&iter, &key, &value)) {
-               table = (struct heart_cpu_table *)value;
-               array_len = table->cpu_info->len;
-               len = snprintf(buf, CPU_DATA_MAX, "%s %s %lu %lu %lu %lu %lu %lu %d ",
-                               table->appid, table->pkgid,
-                               table->total_utime,
-                               table->total_stime,
-                               table->utime,
-                               table->stime,
-                               table->fg_time,
-                               table->bg_time,
-                               table->fg_count);
-
-               for (i = 0; i < CPU_ARRAY_MAX; i++) {
-                       struct heart_cpu_info *ci;
-                       if (array_len <= i) {
-                               len += snprintf(buf + len, CPU_DATA_MAX - len, "0 0 0 0 ");
-                       } else {
-                               ci = g_array_index(table->cpu_info, struct heart_cpu_info *, i);
-                               if (!ci)
-                                       break;
-                               len += snprintf(buf + len, CPU_DATA_MAX - len, "%lu %lu %d %d ",
-                                               ci->utime,
-                                               ci->stime,
-                                               ci->pid,
-                                               ci->state);
-                       }
-               }
-               snprintf(buf + len, CPU_DATA_MAX - len, "\n");
-               fputs(buf, fp);
-       }
-       ret = pthread_mutex_unlock(&heart_cpu_mutex);
-       if (ret) {
-               _E("pthread_mutex_unlock() failed, %d", ret);
-               fclose(fp);
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       fclose(fp);
-
-       return RESOURCED_ERROR_NONE;
-}
-
-static int heart_cpu_hashtable_renew(GHashTable *hashtable, time_t now)
-{
-       int ret;
-       gpointer value;
-       gpointer key;
-       GHashTableIter iter;
-       struct heart_cpu_table *table;
-
-       if (!hashtable) {
-               _E("empty app list");
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       if (!g_hash_table_size(hashtable)) {
-               _E("hash table is empty");
-               return RESOURCED_ERROR_FAIL;
-       }
-       ret = pthread_mutex_lock(&heart_cpu_mutex);
-       if (ret) {
-               _E("pthread_mutex_lock() failed, %d", ret);
-               return RESOURCED_ERROR_FAIL;
-       }
-       g_hash_table_iter_init(&iter, hashtable);
-
-       while (g_hash_table_iter_next(&iter, &key, &value)) {
-               table = (struct heart_cpu_table *)value;
-               table->total_utime = 0;
-               table->total_stime = 0;
-               table->last_renew_time = now;
-               table->fg_count = 0;
-               table->fg_time = 0;
-               table->bg_time = 0;
-       }
-       ret = pthread_mutex_unlock(&heart_cpu_mutex);
-       if (ret) {
-               _E("pthread_mutex_unlock() failed, %d", ret);
-               return RESOURCED_ERROR_FAIL;
-       }
-       return RESOURCED_ERROR_NONE;
-}
-
-void heart_cpu_update(struct logging_table_form *data, void *user_data)
-{
-       const char *path;
-       int ret;
-       pid_t pid;
-       uid_t *uid;
-       int state;
-       unsigned long utime, stime;
-       unsigned long utime_diff = 0, stime_diff = 0;
-       time_t curr_time = logging_get_time(CLOCK_BOOTTIME);
-       struct heart_cpu_table *table;
-       struct heart_cpu_info *ci = NULL;
-       struct heart_cpu_dat_cache *cache;
-       GHashTable *cpu_usage_list = NULL;
-
-       cache = (struct heart_cpu_dat_cache*)g_hash_table_lookup(
-                       heart_cpu_app_list, (gpointer)(&(data->uid)));
-       if (!cache) {
-               path = userinfo_find_home_dir((uid_t)data->uid);
-               if (!path) {
-                       _E("uid %d doesn't existed", data->uid);
-                       return;
-               }
-
-               cache = (struct heart_cpu_dat_cache*)malloc(sizeof(struct heart_cpu_dat_cache));
-               if (!cache) {
-                       _E("malloc failed");
-                       return;
-               }
-
-               cache->path = strndup(path, strlen(path));
-               if (!cache->path) {
-                       _E("strndup failed");
-                       free(cache);
-                       return;
-               }
-
-               cache->list = g_hash_table_new_full(
-                               g_str_hash,
-                               g_str_equal,
-                               NULL,
-                               heart_free_value);
-               if (!cache->list) {
-                       _E("g_hash_table_new_full failed");
-                       free(cache->path);
-                       free(cache);
-                       return;
-               }
-
-               uid = malloc(sizeof(uid_t));
-               if (!uid) {
-                       _E("malloc failed");
-                       g_hash_table_unref(cache->list);
-                       free(cache->path);
-                       free(cache);
-                       return;
-               }
-               *uid = (uid_t)data->uid;
-
-               g_hash_table_insert(heart_cpu_app_list, (gpointer)uid, (gpointer)cache);
-       }
-       cpu_usage_list = cache->list;
-
-       _D("%d %s %s %ld %s", data->uid, data->appid, data->pkgid, data->time, data->data);
-       if (sscanf(data->data, "%lu %lu %d %d ", &utime, &stime, &pid, &state) < 0) {
-               _E("sscanf failed");
-               return;
-       }
-
-       ret = pthread_mutex_lock(&heart_cpu_mutex);
-       if (ret) {
-               _E("pthread_mutex_lock() failed, %d", ret);
-               return;
-       }
-
-       /* update */
-       table = g_hash_table_lookup(cpu_usage_list, data->appid);
-       if (table) {
-
-               if (table->last_renew_time > data->time)
-                       goto unlock_exit;
-
-               ci = find_pid_info(table, pid);
-               if (table->last_pid_info && ci) {
-                       utime_diff = utime - ci->utime;
-                       table->utime += utime_diff;
-                       table->total_utime += utime_diff;
-                       stime_diff = stime - ci->stime;
-                       table->stime += stime_diff;
-                       table->total_stime += stime_diff;
-                       ci->utime = utime;
-                       ci->stime = stime;
-                       if (ci->state == BACKG || ci->state == SERVICE) {
-                               table->bg_time += utime_diff + stime_diff;
-                               if (state == FOREG)
-                                       table->fg_count++;
-                       } else
-                               table->fg_time += utime_diff + stime_diff;
-                       ci->state = state;
-               } else {
-                       table->utime += utime;
-                       table->total_utime += utime;
-                       table->stime += stime;
-                       table->total_stime += stime;
-                       if (table->last_pid_info)
-                               heart_cpu_remove_last_pid_info_exited(table);
-                       ci = malloc(sizeof(struct heart_cpu_info));
-                       if (!ci) {
-                               _E("malloc failed");
-                               goto unlock_exit;
-                       }
-                       ci->pid = pid;
-                       ci->utime = utime;
-                       ci->stime = stime;
-                       ci->state = state;
-                       if (ci->state == FOREG)
-                               table->fg_count++;
-                       table->last_pid_info = g_slist_prepend(table->last_pid_info, ci);
-                       table->last_pid = pid;
-               }
-       } else {
-               table = calloc(1, sizeof(struct heart_cpu_table));
-
-               if (!table) {
-                       _E("malloc failed");
-                       goto unlock_exit;
-               }
-
-               if (snprintf(table->appid, MAX_APPID_LENGTH,  "%s", data->appid) < 0) {
-                       free(table);
-                       _E("snprintf failed");
-                       goto unlock_exit;
-               }
-
-               if (snprintf(table->pkgid, MAX_PKGNAME_LENGTH, "%s", data->pkgid) < 0) {
-                       free(table);
-                       _E("snprintf failed");
-                       goto unlock_exit;
-               }
-               table->total_utime = utime;
-               table->total_stime = stime;
-               table->utime = utime;
-               table->stime = stime;
-               table->fg_count = 0;
-               table->fg_time = 0;
-               table->bg_time = 0;
-               if (state == FOREG)
-                       table->fg_count = 1;
-
-               table->cpu_info =
-                       g_array_new(FALSE, FALSE, sizeof(struct heart_cpu_info *));
-               if (!table->cpu_info) {
-                       free(table);
-                       _E("g_array_new failed");
-                       goto unlock_exit;
-               }
-
-               ci = malloc(sizeof(struct heart_cpu_info));
-               if (!ci) {
-                       _E("malloc failed");
-                       free(table);
-                       goto unlock_exit;
-               }
-               ci->pid = pid;
-               ci->utime = utime;
-               ci->stime = stime;
-               ci->state = state;
-               table->last_pid_info = g_slist_prepend(NULL, ci);
-               table->last_pid = pid;
-
-               g_hash_table_insert(cpu_usage_list, (gpointer)table->appid, (gpointer)table);
-       }
-       ret = pthread_mutex_unlock(&heart_cpu_mutex);
-       if (ret) {
-               _E("pthread_mutex_unlock() failed, %d", ret);
-               return;
-       }
-
-       if (cache->last_file_commit_time + HEART_CPU_SAVE_INTERVAL < curr_time) {
-               /* all hash table update and make new array */
-               gpointer value;
-               gpointer key;
-               GHashTableIter iter;
-               struct heart_cpu_table *search;
-               struct heart_cpu_info *ci;
-
-               ret = pthread_mutex_lock(&heart_cpu_mutex);
-               if (ret) {
-                       _E("pthread_mutex_lock() failed, %d", ret);
-                       return;
-               }
-
-               g_hash_table_iter_init(&iter, cpu_usage_list);
-
-               while (g_hash_table_iter_next(&iter, &key, &value)) {
-                       search = (struct heart_cpu_table *)value;
-
-                       ci = malloc(sizeof(struct heart_cpu_info));
-
-                       if (!ci) {
-                               _E("malloc failed");
-                               goto unlock_exit;
-                       }
-                       /* make new array node */
-                       ci->pid = search->last_pid;
-                       ci->utime = search->utime;
-                       ci->stime = search->stime;
-                       search->utime = 0;
-                       search->stime = 0;
-                       /* hashtable sliding : remove last node and make new one */
-                       if (search->cpu_info->len == CPU_ARRAY_MAX)
-                               g_array_remove_index(search->cpu_info, CPU_ARRAY_MAX - 1);
-                       g_array_prepend_val(search->cpu_info, ci);
-               }
-               ret = pthread_mutex_unlock(&heart_cpu_mutex);
-               if (ret) {
-                       _E("pthread_mutex_unlock() failed, %d", ret);
-                       return;
-               }
-               /* rewrite hashtable list file */
-               ret = heart_cpu_save_to_file(cache);
-               if (ret) {
-                       _E("save to file failed");
-                       goto unlock_exit;
-               }
-
-               cache->last_file_commit_time = curr_time;
-       }
-
-       return;
-
-unlock_exit:
-       ret = pthread_mutex_unlock(&heart_cpu_mutex);
-       if (ret) {
-               _E("pthread_mutex_unlock() failed, %d", ret);
-               return;
-       }
-}
-
-struct heart_cpu_data *heart_cpu_get_data(int uid, char *appid, enum heart_data_period period, struct heart_cpu_data *data)
-{
-       int index, i, ret;
-       struct heart_cpu_table *table;
-       GHashTable *hashtable;
-
-       if (!appid) {
-               _E("Wrong arguments!");
-               return NULL;
-       }
-
-       hashtable = heart_cpu_get_user_app_list(uid);
-       if (!hashtable) {
-               _E("Fail to get app list");
-               return NULL;
-       }
-
-       if (!g_hash_table_size(hashtable)) {
-               _D("hash table is empty");
-               return NULL;
-       }
-
-       switch (period) {
-       case DATA_LATEST:
-               index = 0;
-               break;
-       case DATA_3HOUR:
-               index = 3;
-               break;
-       case DATA_6HOUR:
-               index = 6;
-               break;
-       case DATA_12HOUR:
-               index = 12;
-               break;
-       case DATA_1DAY:
-               index = 24;
-               break;
-       default:
-               _E("Wrong message arguments! %d", period);
-               return NULL;
-       }
-
-       ret = pthread_mutex_lock(&heart_cpu_mutex);
-       if (ret) {
-               _E("pthread_mutex_lock() failed, %d", ret);
-               return NULL;
-       }
-
-       table = g_hash_table_lookup(hashtable, (gconstpointer)appid);
-       if (!table) {
-               data = NULL;
-               goto unlock_exit;
-       }
-       if (snprintf(data->appid, MAX_APPID_LENGTH, "%s", table->appid) < 0) {
-               _E("snprintf failed");
-               data = NULL;
-               goto unlock_exit;
-       }
-       if (snprintf(data->pkgid, MAX_PKGNAME_LENGTH, "%s", table->pkgid) < 0) {
-               _E("snprintf failed");
-               data = NULL;
-               goto unlock_exit;
-       }
-       if (period == DATA_LATEST) {
-               data->utime = table->total_utime;
-               data->stime = table->total_stime;
-       } else {
-               data->utime = table->utime;
-               data->stime = table->stime;
-               i = table->cpu_info->len;
-               if (i == 0) {
-                       data = NULL;
-                       goto unlock_exit;
-               }
-               if (i < index)
-                       index = i;
-               for (i = 0; i < index; i++) {
-                       struct heart_cpu_info *cpu_info;
-                       cpu_info =
-                               g_array_index(table->cpu_info, struct heart_cpu_info *, i);
-                       if (!cpu_info)
-                               break;
-                       data->utime += cpu_info->utime;
-                       data->stime += cpu_info->stime;
-               }
-       }
-unlock_exit:
-       ret = pthread_mutex_unlock(&heart_cpu_mutex);
-       if (ret) {
-               _E("pthread_mutex_unlock() failed, %d", ret);
-               return NULL;
-       }
-       return data;
-}
-
-static int compare_usage(const struct heart_app_usage *lau_a,
-           const struct heart_app_usage *lau_b)
-{
-       if (lau_a->point != lau_b->point)
-               return (lau_b->point - lau_a->point);
-
-       return 0;
-}
-
-/*
- * Calculate application usage using frequency and time
- */
-static double heart_cpu_get_point(int freq, int time)
-{
-       double weightForFrequence = 3;
-       double point = 0;
-       point = sqrt(time + (freq*weightForFrequence));
-       return point;
-}
-
-int heart_cpu_get_appusage_list(int uid, GHashTable *lists, int top)
-{
-       int index = top, i, ret;
-       gpointer value;
-       gpointer key;
-       GHashTableIter h_iter;
-       struct heart_cpu_table *table;
-       struct heart_app_usage lau;
-       GArray *app_lists = NULL;
-       GHashTable *hashtable;
-
-       hashtable = heart_cpu_get_user_app_list(uid);
-       if (!hashtable) {
-               _E("Fail to get app list");
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       if (!g_hash_table_size(hashtable)) {
-               _E("hash table is empty");
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       app_lists = g_array_new(false, false, sizeof(struct heart_app_usage));
-       ret = pthread_mutex_lock(&heart_cpu_mutex);
-       if (ret) {
-               _E("pthread_mutex_lock() failed, %d", ret);
-               g_array_free(app_lists, true);
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       g_hash_table_iter_init(&h_iter, hashtable);
-
-       while (g_hash_table_iter_next(&h_iter, &key, &value)) {
-
-               table = (struct heart_cpu_table *)value;
-               if (!table->fg_count)
-                       continue;
-
-               lau.appid = table->appid;
-               lau.pkgid = table->pkgid;
-               lau.fg_count = table->fg_count;
-               lau.used_time = table->fg_time;
-               lau.point = (int)heart_cpu_get_point(lau.fg_count, lau.used_time);
-               /*
-                * make all application lists with weighted point value excepting service application
-                */
-               g_array_append_val(app_lists, lau);
-       }
-       ret = pthread_mutex_unlock(&heart_cpu_mutex);
-       if (ret) {
-               _E("pthread_mutex_unlock() failed, %d", ret);
-               g_array_free(app_lists, true);
-               return RESOURCED_ERROR_FAIL;
-       }
-       if (app_lists->len < top) {
-               _I("too small data for making app usage lists");
-               g_array_free(app_lists, true);
-               return RESOURCED_ERROR_NO_DATA;
-       }
-
-       g_array_sort(app_lists, (GCompareFunc)compare_usage);
-
-       if (!top)
-               index = app_lists->len;
-
-       /*
-        * replace application usage lists with sorted usage arrays
-        */
-       g_hash_table_remove_all(lists);
-       for (i = 0; i < index; i++) {
-               struct heart_app_usage *usage = &g_array_index(app_lists, struct heart_app_usage, i);
-               _D("appid : %s, point : %d", usage->appid, usage->point);
-               g_hash_table_insert(lists, g_strndup(usage->appid, strlen(usage->appid)), GINT_TO_POINTER(1));
-       }
-       g_array_free(app_lists, true);
-       return RESOURCED_ERROR_NONE;
-}
-
-static int heart_cpu_update_appid(void *data)
-{
-       int pid;
-       char old_appid[MAX_APPID_LENGTH], new_appid[MAX_APPID_LENGTH];
-       char *info;
-
-       if (!data) {
-               _E("Invalid parameter");
-               return RESOURCED_ERROR_INVALID_PARAMETER;
-       }
-
-       info = (char*)data;
-       if (sscanf(info, "%d "STR_FS(MAX_APPID_LENGTH_M1)" "STR_FS(MAX_APPID_LENGTH_M1),
-                       &pid, old_appid, new_appid) < 0) {
-               _E("sscanf failed, %m");
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       return logging_modify_appid(CPU_NAME, old_appid, new_appid, pid);
-}
-
-static void dbus_heart_get_cpu_data(GDBusMethodInvocation *invocation, GVariant *params)
-{
-       int period = -1;
-       char *appid = NULL;
-       struct heart_cpu_data *data = NULL;
-
-       int uid = -1;
-
-       do_expr_unless_g_variant_get_typechecked(goto failure, params, "(i&si)", &uid, &appid, &period);
-       if (uid < 0 || !appid || period < 0) {
-               _E("Wrong message arguments!");
-               goto failure;
-       }
-
-       data = malloc(sizeof(struct heart_cpu_data));
-       if (!data) {
-               _E("malloc failed");
-               goto failure;
-       }
-
-       if (heart_cpu_get_data(uid, appid, period, data) == NULL)
-               goto failure;
-
-       g_dbus_method_invocation_return_value(invocation, g_variant_new("(ii)",
-                               data->utime, data->stime));
-       free(data);
-       return;
-
-failure:
-       if (data)
-               free(data);
-       D_BUS_REPLY_ERR(invocation);
-}
-
-static void dbus_heart_get_cpu_data_list(GDBusMethodInvocation *invocation, GVariant *params)
-{
-       int period = -1, index, i, ret;
-       gpointer value;
-       gpointer key;
-       GHashTableIter h_iter;
-       struct heart_cpu_table *table;
-
-       char *appid;
-       unsigned long utime, stime, ftime, total;
-
-       int uid = -1;
-       GHashTable *hashtable;
-
-       GVariantBuilder builder, *sub_builder;
-
-       utime = stime = ftime = total = 0;
-
-       do_expr_unless_g_variant_get_typechecked(goto failure, params, "(ii)", &uid, &period);
-       if (uid < 0 || period < 0) {
-               _E("Wrong message arguments!");
-               goto failure;
-       }
-
-       heart_cpu_update_app_list(NULL);
-
-       logging_save_to_storage(true);
-       /* update data list from db */
-       logging_update(true);
-
-       switch (period) {
-       case DATA_LATEST:
-               index = 0;
-               break;
-       case DATA_3HOUR:
-               index = 3;
-               break;
-       case DATA_6HOUR:
-               index = 6;
-               break;
-       case DATA_12HOUR:
-               index = 12;
-               break;
-       case DATA_1DAY:
-               index = 24;
-               break;
-       default:
-               _E("Wrong message arguments! %d", period);
-               goto failure;
-       }
-
-       hashtable = heart_cpu_get_user_app_list(uid);
-       if (!hashtable) {
-               _E("Fail to get app list");
-               goto failure;
-       }
-
-       if (!g_hash_table_size(hashtable)) {
-               _E("hash table is empty");
-               goto failure;
-       }
-
-       ret = pthread_mutex_lock(&heart_cpu_mutex);
-       if (ret) {
-               _E("pthread_mutex_lock() failed, %d", ret);
-               goto failure;
-       }
-
-       g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
-       sub_builder = g_variant_builder_new(G_VARIANT_TYPE("a(sii)"));
-
-       g_hash_table_iter_init(&h_iter, hashtable);
-       while (g_hash_table_iter_next(&h_iter, &key, &value)) {
-               table = (struct heart_cpu_table *)value;
-               if (!table)
-                       break;
-               if (period == DATA_LATEST) {
-                       utime = table->total_utime;
-                       stime = table->total_stime;
-               } else {
-                       utime = table->utime;
-                       stime = table->stime;
-                       i =  table->cpu_info->len;
-                       if (i < index)
-                               index = i;
-                       for (i = 0; i < index; i++) {
-                               struct heart_cpu_info *ci;
-                               ci = g_array_index(table->cpu_info, struct heart_cpu_info *, i);
-                               if (!ci)
-                                       break;
-                               utime += ci->utime;
-                               stime += ci->stime;
-                       }
-               }
-               ftime = table->fg_time;
-               total = utime + stime;
-               if (total == 0)
-                       continue;
-               appid = table->appid;
-
-               g_variant_builder_add(sub_builder, "(sii)", appid, total, ftime);
-       }
-
-       ret = pthread_mutex_unlock(&heart_cpu_mutex);
-       if (ret) {
-               _E("pthread_mutex_unlock() failed, %d", ret);
-               g_variant_builder_unref(sub_builder);
-               goto failure;
-       }
-
-       g_variant_builder_add_value(&builder, g_variant_new("a(sii)", sub_builder));
-       g_variant_builder_unref(sub_builder);
-
-       g_dbus_method_invocation_return_value(invocation, g_variant_builder_end(&builder));
-       return;
-
-failure:
-       D_BUS_REPLY_ERR(invocation);
-}
-
-static void dbus_heart_reset_cpu_data(GDBusMethodInvocation *invocation, GVariant *params)
-{
-       int ret = -1;
-
-       GHashTableIter iter_table;
-       gpointer key, value;
-
-       g_hash_table_iter_init(&iter_table, heart_cpu_app_list);
-       while (g_hash_table_iter_next(&iter_table, &key, &value))
-               ret = heart_cpu_hashtable_renew(((struct heart_cpu_dat_cache*)value)->list, time(NULL));
-
-
-       g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", ret));
-}
-
-static void dbus_heart_update_cpu_data(GDBusMethodInvocation *invocation, GVariant *params)
-{
-       heart_cpu_update_app_list(NULL);
-
-       g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", 0));
-}
-
-static void dbus_heart_sync_cpu_data(GDBusMethodInvocation *invocation, GVariant *params)
-{
-       int ret = 0;
-
-       heart_cpu_update_app_list(NULL);
-
-       ret = logging_sync(invocation);
-       if (ret)
-               g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", ret));
-}
-
-static void dbus_heart_save_to_file(GDBusMethodInvocation *invocation, GVariant *params)
-{
-       int ret;
-
-       GHashTableIter iter_table;
-       gpointer key, value;
-       struct heart_cpu_dat_cache *cache;
-
-       g_hash_table_iter_init(&iter_table, heart_cpu_app_list);
-       while (g_hash_table_iter_next(&iter_table, &key, &value)) {
-               cache = (struct heart_cpu_dat_cache*)value;
-               ret = heart_cpu_save_to_file(cache);
-               if (ret) {
-                       _E("save to file failed");
-                       D_BUS_REPLY_ERR(invocation);
-                       return;
-               }
-               cache->last_file_commit_time = logging_get_time(CLOCK_BOOTTIME);
-       }
-
-       g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", ret));
-}
-
-static const char dbus_methods_xml[] =
-"              <method name='GetCpuData'>"
-"                      <arg type='i' name='Uid' direction='in'/>"
-"                      <arg type='s' name='Appid' direction='in'/>"
-"                      <arg type='i' name='Period' direction='in'/>"
-"                      <arg type='i' name='Utime' direction='out'/>"
-"                      <arg type='i' name='Stime' direction='out'/>"
-"              </method>"
-"              <method name='GetCpuDataList'>"
-"                      <arg type='i' name='Uid' direction='in'/>"
-"                      <arg type='i' name='Period' direction='in'/>"
-"                      <arg type='a(sii)' name='CpuTimePerApp' direction='out'/>"
-"              </method>"
-"              <method name='ResetCpuData'>"
-"                      <arg type='i' name='ZeroOnSuccess' direction='out'/>"
-"              </method>"
-"              <method name='UpdateCpuData'>"
-"                      <arg type='i' name='Zero' direction='out'/>"
-"              </method>"
-"              <method name='SyncCpuData'>"
-"                      <arg type='i' name='ZeroOnSuccess' direction='out'/>"
-"              </method>"
-"              <method name='SaveCpuData'>"
-"                      <arg type='i' name='ZeroOnSuccess' direction='out'/>"
-"              </method>";
-
-static struct d_bus_method dbus_methods[] = {
-       { "GetCpuData",     dbus_heart_get_cpu_data },
-       { "GetCpuDataList", dbus_heart_get_cpu_data_list },
-       { "ResetCpuData",   dbus_heart_reset_cpu_data },
-       { "UpdateCpuData",  dbus_heart_update_cpu_data },
-       { "SyncCpuData",    dbus_heart_sync_cpu_data },
-       { "SaveCpuData",    dbus_heart_save_to_file },
-};
-
-static int heart_cpu_reset(void *data)
-{
-       GHashTableIter iter_table;
-       gpointer key, value;
-       int ret = RESOURCED_ERROR_FAIL;
-
-       g_hash_table_iter_init(&iter_table, heart_cpu_app_list);
-       while (g_hash_table_iter_next(&iter_table, &key, &value))
-               ret = heart_cpu_hashtable_renew(((struct heart_cpu_dat_cache*)value)->list, time(NULL));
-
-       return ret;
-}
-
-static int heart_cpu_init(void *data)
-{
-       const GArray *user_list = NULL;
-       int ret;
-       uid_t *uid;
-       struct heart_cpu_dat_cache *cache;
-
-       ret = logging_module_init(CPU_NAME, ONE_DAY, TEN_MINUTE, heart_cpu_update, TEN_MINUTE, USER_DEFAULT);
-       if (ret != RESOURCED_ERROR_NONE) {
-               _E("logging module init failed");
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       user_list = userinfo_get_list();
-       if (!user_list) {
-               _E("Fail to get user table");
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       if (!heart_cpu_app_list) {
-               heart_cpu_app_list = g_hash_table_new_full(
-                               g_int_hash,
-                               g_int_equal,
-                               heart_cpu_free_uid,
-                               heart_cpu_free_dat_cache);
-
-               userinfo_for_each(elem, user_list) {
-                       cache = (struct heart_cpu_dat_cache*)malloc(sizeof(struct heart_cpu_dat_cache));
-                       assert(cache);
-
-                       cache->path = strndup(elem->home_dir, strlen(elem->home_dir));
-                       cache->list = g_hash_table_new_full(
-                                       g_str_hash,
-                                       g_str_equal,
-                                       NULL,
-                                       heart_free_value);
-
-                       ret = heart_cpu_read_from_file(cache);
-                       assert(ret == RESOURCED_ERROR_NONE);
-
-                       cache->last_file_commit_time = logging_get_time(CLOCK_BOOTTIME);
-
-                       uid = malloc(sizeof(uid_t));
-                       assert(uid);
-
-                       *uid = elem->uid;
-                       g_hash_table_insert(heart_cpu_app_list, (gpointer)uid, (gpointer)cache);
-               }
-       }
-
-       heart_dbus_declare_methods(dbus_methods_xml, dbus_methods, ARRAY_SIZE(dbus_methods));
-
-       register_notifier(RESOURCED_NOTIFIER_SERVICE_LAUNCH, heart_cpu_service_launch);
-       register_notifier(RESOURCED_NOTIFIER_APP_FOREGRD, heart_cpu_foreground_state);
-       register_notifier(RESOURCED_NOTIFIER_APP_BACKGRD, heart_cpu_background_state);
-       register_notifier(RESOURCED_NOTIFIER_APP_GROUP, heart_cpu_update_appid);
-       register_notifier(RESOURCED_NOTIFIER_DATA_UPDATE, heart_cpu_update_app_list);
-       register_notifier(RESOURCED_NOTIFIER_DATA_RESET, heart_cpu_reset);
-
-       heart_cpu_get_appusage_list_func = heart_cpu_get_appusage_list;
-
-       _D("heart cpu init finished");
-       return RESOURCED_ERROR_NONE;
-}
-
-static int heart_cpu_exit(void *data)
-{
-       GHashTableIter iter;
-       gpointer key, value;
-       struct heart_cpu_dat_cache *cache;
-
-       unregister_notifier(RESOURCED_NOTIFIER_SERVICE_LAUNCH, heart_cpu_service_launch);
-       unregister_notifier(RESOURCED_NOTIFIER_APP_FOREGRD, heart_cpu_foreground_state);
-       unregister_notifier(RESOURCED_NOTIFIER_APP_BACKGRD, heart_cpu_background_state);
-       unregister_notifier(RESOURCED_NOTIFIER_APP_GROUP, heart_cpu_update_appid);
-       unregister_notifier(RESOURCED_NOTIFIER_DATA_UPDATE, heart_cpu_update_app_list);
-       unregister_notifier(RESOURCED_NOTIFIER_DATA_RESET, heart_cpu_reset);
-
-       if (heart_cpu_app_list) {
-               g_hash_table_iter_init(&iter, heart_cpu_app_list);
-               while (g_hash_table_iter_next(&iter, &key, &value)) {
-                       cache = (struct heart_cpu_dat_cache*)value;
-                       heart_cpu_save_to_file(cache);
-               }
-               g_hash_table_destroy(heart_cpu_app_list);
-       }
-
-       logging_module_exit();
-
-       heart_cpu_get_appusage_list_func = NULL;
-
-       _D("heart cpu exit");
-       return RESOURCED_ERROR_NONE;
-}
-
-static int heart_cpu_dump(FILE *fp, int mode, void *data)
-{
-       time_t starttime;
-       char timestr[80];
-       struct tm loc_tm;
-       static GHashTable *cpu_usage_list;
-       gpointer value;
-       gpointer key;
-       GHashTableIter h_iter;
-       struct heart_cpu_table *table;
-
-       starttime = time(NULL);
-
-       starttime -= mode;
-       localtime_r(&starttime, &loc_tm);
-       /* print timestamp */
-       strftime(timestr, sizeof(timestr),
-                       "%Y-%m-%d %H:%M:%S%z", &loc_tm);
-
-       cpu_usage_list = g_hash_table_new_full(
-                       g_str_hash,
-                       g_str_equal,
-                       NULL,
-                       free);
-
-
-       logging_read_foreach(CPU_NAME, NULL, NULL, starttime, 0,
-                       heart_cpu_update, cpu_usage_list);
-
-       if (!g_hash_table_size(cpu_usage_list)) {
-               _E("hash table is empty");
-               return 0;
-       }
-
-       LOG_DUMP(fp, "[CPU USAGE LISTS] since %s\n", timestr);
-       LOG_DUMP(fp, "appid pkgid total fg_count fg_time\n");
-       g_hash_table_iter_init(&h_iter, cpu_usage_list);
-
-       while (g_hash_table_iter_next(&h_iter, &key, &value)) {
-
-               table = (struct heart_cpu_table *)value;
-               if (!table)
-                       break;
-               LOG_DUMP(fp, "%s %s %ld %d %ld\n", table->appid, table->pkgid,
-                               table->total_utime + table->total_stime,
-                               table->fg_count, table->fg_time);
-       }
-       fflush(fp);
-       g_hash_table_destroy(cpu_usage_list);
-
-       return RESOURCED_ERROR_NONE;
-}
-
-static const struct heart_module_ops heart_cpu_ops = {
-       .name           = "CPU",
-       .init           = heart_cpu_init,
-       .dump               = heart_cpu_dump,
-       .exit           = heart_cpu_exit,
-};
-HEART_MODULE_REGISTER(&heart_cpu_ops)
diff --git a/src/resource-monitor/heart-abnormal.c b/src/resource-monitor/heart-abnormal.c
new file mode 100644 (file)
index 0000000..02554a6
--- /dev/null
@@ -0,0 +1,436 @@
+/*
+ * resourced
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @file heart-abnormal.c
+ *
+ * @desc heart abnormal module
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <glib.h>
+#include <sys/time.h>
+
+#include "proc-common.h"
+#include "notifier.h"
+#include "resourced.h"
+#include "dbus-handler.h"
+#include "heart.h"
+#include "logging.h"
+#include "heart-common.h"
+#include "trace.h"
+#include "module.h"
+#include "macro.h"
+
+#define ABNORMAL_NAME                          "abnormal"
+#define ABNORMAL_DATA_MAX                      1024
+#define ABNORMAL_CHECK_NUM                     10
+
+#define TIMESTAMP_LEN                          16
+#define MILLISEC                               1000
+#define TIME_MAX_LEN                           64
+#define SLUG_TYPE_MALFUN                       6
+#define NOPID                                  0
+
+enum abnormal_type {
+       FC = 0,
+       ANR = 1,
+       ABNORMAL_TYPE_MAX,
+};
+
+struct heart_abnormal_table {
+       char appid[MAX_APPID_LENGTH];
+       char pkgid[MAX_PKGNAME_LENGTH];
+       time_t time;
+       int count[ABNORMAL_TYPE_MAX];
+};
+
+static GHashTable *heart_abnormal_list;
+static pthread_mutex_t heart_abnormal_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+void heart_abnormal_fill_array(struct logging_table_form *entry, void *data)
+{
+       int ret, i;
+       unsigned int type;
+       struct heart_abnormal_table *table = NULL;
+       GHashTable *list = (GHashTable *)data;
+
+       if (sscanf((char *)entry->data, "%*s %*s %u ", &type) < 0) {
+               _E("sscanf failed, %m");
+               return;
+       }
+
+       if (type >= ABNORMAL_TYPE_MAX) {
+               _E("wrong abnormal type, %u", type);
+               return;
+       }
+       ret = pthread_mutex_lock(&heart_abnormal_mutex);
+       if (ret) {
+               _E("pthread_mutex_lock() failed, %d", ret);
+               return;
+       }
+       table = g_hash_table_lookup(list, entry->appid);
+       if (!table) {
+               table = malloc(sizeof(struct heart_abnormal_table));
+               if (!table) {
+                       _E("malloc failed");
+                       goto unlock_exit;
+               }
+
+               if (snprintf(table->appid, MAX_APPID_LENGTH, "%s", entry->appid) < 0) {
+                       _E("snprintf failed");
+                       free(table);
+                       goto unlock_exit;
+               }
+
+               if (snprintf(table->pkgid, MAX_PKGNAME_LENGTH, "%s", entry->pkgid) < 0) {
+                       _E("snprintf failed");
+                       free(table);
+                       goto unlock_exit;
+               }
+               table->time = entry->time;
+
+               for (i = 0; i < ABNORMAL_TYPE_MAX; i++)
+                       table->count[i] = 0;
+
+               table->count[type] = 0;
+               g_hash_table_insert(list, (gpointer)table->appid, (gpointer)table);
+       }
+       table->count[type]++;
+
+unlock_exit:
+       ret = pthread_mutex_unlock(&heart_abnormal_mutex);
+       if (ret)
+               _E("pthread_mutex_unlock() failed, %d", ret);
+}
+
+static void heart_abnormal_launch_popup(char *appid, int count)
+{
+       _W("A malfunction popup is supposed to be created here, but system-popup "
+          "doesn't actually expose a MalfunctionNotifierLaunch DBus method and "
+          "this legacy functionality is deprecated.");
+
+#if 0
+       /* Dead code (see above); it has been disabled instead of outright removed
+        * because I've seen too many braindead repository copy-pastes annihilating
+        * git history to trust people to be able to find this code in case their
+        * legacy system suddenly stops working and I don't want to deal with the
+        * flak I could be getting for it. In a year or two (unless somebody patches
+        * system-popup to add MalfurionNotifierLaunch or some other good reason
+        * appears) it would be good to get rid of this code though. */
+
+       int ret;
+       char num[10];
+       char _appid[MAX_APPID_LENGTH];
+       GVariant *param;
+
+       /* Launch malfunction system popup */
+       snprintf(num, 10, "%d", count);
+       snprintf(_appid, MAX_APPID_LENGTH, "%s", appid);
+       _D("appid %s, count %d", appid, count);
+
+       param = g_variant_new("(ssssss)", "_SYSPOPUP_CONTENT_",
+               "malfunction_notifier",
+               "_ERRORS_",
+               num,
+               "_APPID_",
+               _appid)
+
+       ret = d_bus_call_method_async_gvariant("org.tizen.system.popup",
+                       "/Org/Tizen/System/Popup/System",
+                       "org.tizen.system.popup.System",
+                       "MalfunctionNotifierLaunch", param);
+       if (ret < 0)
+               _E("Failed to launch MalfunctionNotifier");
+       else
+               _I("MalfunctionNotifierLaunch Success");
+#endif
+}
+
+static int heart_abnormal_report_malfunction(char *name)
+{
+       int ret = -1;
+       char timestr[TIMESTAMP_LEN] = {0,};
+       int milli;
+       char msgid[TIME_MAX_LEN + sizeof '+' + MAX_DEC_SIZE(milli)] = {0,};
+       char ts[TIME_MAX_LEN] = {0,};
+       struct timeval time_of_day;
+       time_t unix_time = time(NULL);
+       struct tm loc_tm;
+
+       if (gettimeofday(&time_of_day, NULL)) {
+               _E("gettimeofday failed");
+               return ret;
+       }
+       if (!localtime_r(&time_of_day.tv_sec, &loc_tm)) {
+               _E("localtime_r failed");
+               return ret;
+       }
+
+       snprintf(timestr, sizeof(timestr), "%.10ld", unix_time);
+       milli = time_of_day.tv_usec / MILLISEC;
+       strftime(ts, TIME_MAX_LEN, "%Y.%m.%d-%H:%M:%S", &loc_tm);
+       snprintf(msgid, sizeof(msgid), "%s+%d", ts, milli);
+
+       ret = d_bus_call_method_async_gvariant("org.tizen.system.crash", "/Org/Tizen/System/Crash/Crash", "org.tizen.system.crash.Crash",
+                               "sluggish_dump",
+                               g_variant_new("(iisss)", SLUG_TYPE_MALFUN, NOPID, name, timestr, msgid));
+
+       if (ret < 0)
+               _E("Malfunction reporting to sluggish tool failed");
+       return ret;
+}
+
+static void heart_abnormal_process_crashed(GVariant *params)
+{
+       int ret, notify, count;
+       gpointer key, value;
+       time_t curtime, starttime;
+       GHashTableIter hiter;
+       char *process_name = NULL, *exepath = NULL, *appid = NULL, *pkgid = NULL;
+       char info[ABNORMAL_DATA_MAX];
+       struct heart_abnormal_table *table = NULL;
+
+       do_expr_unless_g_variant_get_typechecked(return, params, "(&s&s&s&ssiia{sv})", &process_name, &exepath, &appid, &pkgid,
+                                       NULL, NULL, NULL, NULL);
+       if (!process_name || !exepath || !appid || !pkgid) {
+               _E("Failed: dbus_message_get_args()");
+               return;
+       }
+       curtime = time(NULL);
+       starttime = curtime - 604800;
+       if (starttime < 0)
+               starttime = 0;
+
+       if (g_hash_table_size(heart_abnormal_list))
+               g_hash_table_remove_all(heart_abnormal_list);
+
+       logging_read_foreach(ABNORMAL_NAME, appid, NULL, starttime, curtime,
+                       heart_abnormal_fill_array, heart_abnormal_list);
+
+       g_hash_table_iter_init(&hiter, heart_abnormal_list);
+
+       count = 0;
+       while (g_hash_table_iter_next(&hiter, &key, &value)) {
+               table = (struct heart_abnormal_table *)value;
+               if (!table)
+                       break;
+               count += table->count[FC];
+       }
+
+       notify = 0;
+       if (count > ABNORMAL_CHECK_NUM) {
+               heart_abnormal_launch_popup(appid, count);
+               notify = 1;
+               heart_abnormal_report_malfunction(appid);
+       }
+
+       g_hash_table_remove_all(heart_abnormal_list);
+
+       snprintf(info, sizeof(info), "%s %s %d %d ", process_name, exepath, notify, FC);
+       _D("info : %s %d", info, count);
+       ret = logging_write(PID_FOR_ROOT, ABNORMAL_NAME, appid, pkgid, time(NULL), info);
+       if (ret != RESOURCED_ERROR_NONE)
+               _E("Failed to logging_write %s", info);
+}
+
+static int heart_abnormal_anr(void *data)
+{
+       int ret;
+       char info[ABNORMAL_DATA_MAX];
+       struct proc_status *ps = (struct proc_status *)data;
+       char *appid, *pkgid;
+
+       ret = proc_get_id_info(ps, &appid, &pkgid);
+       if (ret != RESOURCED_ERROR_NONE) {
+               _E("Failed to proc_get_id_info");
+               return ret;
+       }
+       snprintf(info, sizeof(info), "%d ANR %d ", ps->pid, ANR);
+       _D("info : %s", info);
+       ret = logging_write(PID_FOR_ROOT, ABNORMAL_NAME, appid, pkgid, time(NULL), info);
+       if (ret != RESOURCED_ERROR_NONE)
+               _E("Failed to logging_write %s", info);
+       return ret;
+}
+
+static void heart_abnormal_free_value(gpointer value)
+{
+       struct heart_abnormal_table *table =
+               (struct heart_abnormal_table *)value;
+
+       if (!table)
+               return;
+
+       free(table);
+}
+
+static void dbus_heart_get_abnormal_data(GDBusMethodInvocation *invocation, GVariant *params)
+{
+       int type = -1, period = -1;
+       int ret, count, i;
+       time_t starttime;
+       char *appid;
+       gpointer key, value;
+       GHashTableIter hiter;
+       struct heart_abnormal_table *table = NULL;
+       GVariantBuilder builder, *sub_builder;
+
+       do_expr_unless_g_variant_get_typechecked(goto failure, params, "(ii)", &type, &period);
+       if (type < 0 || ABNORMAL_TYPE_MAX  < type || period < 0) {
+               _E("Wrong message arguments! %d", type);
+               goto failure;
+       }
+       starttime = time(NULL);
+       switch (period) {
+       case DATA_LATEST:
+               starttime = 0;
+               break;
+       case DATA_3HOUR:
+               starttime -= 10800;
+               break;
+       case DATA_6HOUR:
+               starttime -= 21600;
+               break;
+       case DATA_12HOUR:
+               starttime -= 43200;
+               break;
+       case DATA_1DAY:
+               starttime -= 86400;
+               break;
+       case DATA_1WEEK:
+               starttime -= 604800;
+               break;
+       default:
+               _E("Wrong message arguments! %d", period);
+               goto failure;
+       }
+
+       if (starttime < 0)
+               starttime = 0;
+
+       if (g_hash_table_size(heart_abnormal_list))
+               g_hash_table_remove_all(heart_abnormal_list);
+
+       logging_read_foreach(ABNORMAL_NAME, NULL, NULL, starttime, time(NULL),
+                       heart_abnormal_fill_array, heart_abnormal_list);
+
+       ret = pthread_mutex_lock(&heart_abnormal_mutex);
+       if (ret) {
+               _E("pthread_mutex_lock() failed, %d", ret);
+               goto failure;
+       }
+
+       g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
+       sub_builder = g_variant_builder_new(G_VARIANT_TYPE("a(si)"));
+
+       g_hash_table_iter_init(&hiter, heart_abnormal_list);
+       while (g_hash_table_iter_next(&hiter, &key, &value)) {
+               table = (struct heart_abnormal_table *)value;
+               if (!table)
+                       break;
+               count = 0;
+               appid = table->appid;
+
+               if (type == ABNORMAL_TYPE_MAX) {
+                       for (i = 0; i < ABNORMAL_TYPE_MAX; i++)
+                               count += table->count[i];
+               } else
+                       count += table->count[type];
+
+               if (!count)
+                       continue;
+
+               g_variant_builder_add(sub_builder, "(si)", appid, count);
+       }
+       g_variant_builder_add_value(&builder, g_variant_new("a(si)", sub_builder));
+       g_variant_builder_unref(sub_builder);
+
+       ret = pthread_mutex_unlock(&heart_abnormal_mutex);
+       if (ret) {
+               _E("pthread_mutex_unlock() failed, %d", ret);
+               goto failure;
+       }
+       g_hash_table_remove_all(heart_abnormal_list);
+
+       g_dbus_method_invocation_return_value(invocation, g_variant_builder_end(&builder));
+       return;
+
+failure:
+       D_BUS_REPLY_ERR(invocation);
+}
+
+static const char dbus_methods_xml[] =
+"              <method name='GetAbnormalData'>"
+"                      <arg type='i' name='Type' direction='in'/>"
+"                      <arg type='i' name='Period' direction='in'/>"
+"                      <arg type='a(si)' name='CountPerApp' direction='out'/>"
+"              </method>";
+
+static struct d_bus_method dbus_methods[] = {
+       { "GetAbnormalData", dbus_heart_get_abnormal_data },
+};
+
+static int heart_abnormal_init(void *data)
+{
+       int ret;
+
+       ret = logging_module_init(ABNORMAL_NAME, ONE_WEEK, HALF_HOUR, NULL, 0, SYSTEM_DEFAULT);
+       if (ret != RESOURCED_ERROR_NONE) {
+               _E("logging module init failed");
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       heart_dbus_declare_methods(dbus_methods_xml, dbus_methods, ARRAY_SIZE(dbus_methods));
+
+       ret = d_bus_register_signal(CRASH_PATH_CRASH,
+                       CRASH_INTERFACE_CRASH, PROCESS_CRASHED,
+                       heart_abnormal_process_crashed, NULL);
+       if (ret < 0)
+               _E("Failed to add a capacity status signal handler");
+       heart_abnormal_list = g_hash_table_new_full(
+                       g_str_hash,
+                       g_str_equal,
+                       NULL,
+                       heart_abnormal_free_value);
+
+       register_notifier(RESOURCED_NOTIFIER_APP_ANR, heart_abnormal_anr);
+       _D("heart abnormal init finished");
+       return RESOURCED_ERROR_NONE;
+}
+
+static int heart_abnormal_exit(void *data)
+{
+       if (heart_abnormal_list)
+               g_hash_table_destroy(heart_abnormal_list);
+       logging_module_exit();
+       unregister_notifier(RESOURCED_NOTIFIER_APP_ANR, heart_abnormal_anr);
+       _D("heart abnormal exit");
+       return RESOURCED_ERROR_NONE;
+}
+
+static const struct heart_module_ops heart_abnormal_ops = {
+       .name           = "ABNORMAL",
+       .init           = heart_abnormal_init,
+       .exit           = heart_abnormal_exit,
+};
+HEART_MODULE_REGISTER(&heart_abnormal_ops)
diff --git a/src/resource-monitor/heart-battery.c b/src/resource-monitor/heart-battery.c
new file mode 100644 (file)
index 0000000..4c5b9b6
--- /dev/null
@@ -0,0 +1,3702 @@
+/*
+ * resourced
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @file heart-battery.c
+ *
+ * @desc heart battery module
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ */
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <glib.h>
+#include <sqlite3.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <math.h>
+#include <device/display.h>
+#include <device/callback.h>
+#include <system_info.h>
+
+#include "proc-common.h"
+#include "notifier.h"
+#include "resourced.h"
+#include "dbus-handler.h"
+#include "heart.h"
+#include "logging.h"
+#include "heart-common.h"
+#include "config-parser.h"
+#include "trace.h"
+#include "vconf.h"
+#include "module.h"
+#include "macro.h"
+#include "util.h"
+#include "file-helper.h"
+
+#define TIZEN_SYSTEM_APPID                     "org.tizen.system"
+#define TIZEN_SYSTEM_BATTERY_APPID             "org.tizen.system.battery.capacity"
+#define BATTERY_NAME                           "battery"
+#define BATTERY_DATA_MAX                       1024
+#define BATTERY_CAPACITY_MAX                   512
+#define BATTERY_LINE_MAX                       128
+#define BATTERY_CLEAN_MAX                      100
+#define BATTERY_HISTORY_DAY_MAX                        7
+#define BATTERY_HISTORY_RESET_MAX              5
+#define BATTERY_HISTORY_RESET_CURRENT          (BATTERY_HISTORY_RESET_MAX - 1)
+#define BATTERY_HISTORY_COUNT_MAX              1000
+#define HEART_BATTERY_UPDATE_INTERVAL          HALF_HOUR
+#define HEART_BATTERY_SAVE_INTERVAL            HALF_HOUR
+#define HEART_BATTERY_CAPACITY_DATA_FILE       HEART_FILE_PATH"/.battery_capacity.dat"
+#define HEART_BATTERY_CONF_SECTION              "BATTERY_POWER_MODE"
+#define GET_CHARGER_STATUS                     "ChargerStatus"
+#define GET_BATTERY_CAPACITY                   "GetPercent"
+#define CALCULATE_DAY_BASE_TIME(x)             ((x / DAY_TO_SEC(1)) * (DAY_TO_SEC(1)))
+#define REMAIN_CAPACITY(x)                     (100 - x)
+#define BATTERY_PREDICTION_DATA_MIN            5
+#define BATTERY_USAGE_LEARNING                 -1
+#define CUMUL_WEIGHT                           (0.8)
+#define TREND_WEIGHT                           (1 - CUMUL_WEIGHT)
+#define DISCHARGE_BASE_RATE                    (0.2)
+
+/*
+ * BATTERY_PREDICTION_LATEST_COUNT must be >= BATTERY_PREDICTION_DATA_MIN
+ */
+#define BATTERY_PREDICTION_LATEST_COUNT                5
+/*
+ * BATTERY_PREDICTION_PERIOD possible values:
+ * DATA_LATEST, DATA_3HOUR, DATA_6HOUR, DATA_12HOUR, DATA_1DAY
+ */
+#define BATTERY_PREDICTION_PERIOD              DATA_3HOUR
+
+#define BATTERY_USED_TIME                       "BATTERY_USED_TIME"
+#define BATTERY_STATUS                          "BATTERY_STATUS"
+#define BATTERY_RESET_USAGE                     "BATTERY_RESET_USAGE"
+#define BATTERY_WEEK_DAY_USAGE                  "BATTERY_WEEK_DAY_USAGE"
+#define BATTERY_LEVEL_USAGE                     "BATTERY_LEVEL_USAGE"
+#define BATTERY_PREDICTION                      "BATTERY_PREDICTION"
+
+#define INDEX_WINDOW_SIZE              10  /*data storing index*/
+#define BATTERY_LEVEL_GAP              5  /*previous 5 battery data*/
+#define LONG_TIME_WEIGHT               (0.7) /*weightage given for longer time discharge*/
+#define SHORT_TIME_WEIGHT              (1-LONG_TIME_WEIGHT) /*weightage given for short time discharge*/
+#define NEW_PIVOT_WEIGHTAGE(x)         (x * 0.10) /* x/10th part */
+#define OLD_PIVOT_WEIGHTAGE(x)         (1.0 - NEW_PIVOT_WEIGHTAGE(x))
+#define MIN_DISCHARGE_PERIOD           40
+#define LOW_CAPACITY                   2
+#define MIN_TIME_FOR_LVL_CHANGE                50
+#define BATT_CHG_FLUSH_DATA            10
+
+/*
+ * Below 6 values are the co-efficient of the polynomial. These are devired from
+ * OCV and  and battery percentage level based on experiment
+ */
+#define OCV_SOC_POLY_COEF_1                    (3402.664)
+#define OCV_SOC_POLY_COEF_2                    (42.031)
+#define OCV_SOC_POLY_COEF_3                    (-1.76745)
+#define OCV_SOC_POLY_COEF_4                    (0.034798)
+#define OCV_SOC_POLY_COEF_5                    (-0.00030516)
+#define OCV_SOC_POLY_COEF_6                    (0.0000010116)
+#define UPS_FACTOR                             (2.88)
+#define DOUBLE_ZERO                            (0.000000)
+#define FULL_CAPACITY                  100
+/* BATTERY_C_RATE is defined as the rate of which battery capacity is changing
+ * If total battery capacity is XmAh, then in one second battery capacity change
+ * will be considered as 90
+ */
+#define BATTERY_C_RATE                 90
+#define SEC_TO_MIN(x) ((x + 30)/60)  /* 30 secs buffer to round off */
+#define CAL_MIN(x, y) ((x < y) ? x : y)
+#define BATTERY_WINDOW_INDEX(x)                (((x) +  INDEX_WINDOW_SIZE) % INDEX_WINDOW_SIZE)
+#define HEART_BATTERY_DATA_FILE                HEART_FILE_PATH"/.battery_data.dat"
+#define HEART_BATTERY_PIVOT_INFO       HEART_FILE_PATH"/.battery_pivot_data.dat"
+#define VCONFKEY_HEART_BATTERY_DEVICE_MODE                     "db/setting/psmode"
+#define VCONFKEY_SETAPPL_MANAGE_BATTERY_TRIGGER_TIME "db/setting/manage_battery_trigger_time"
+
+/*
+ * Remaining Useful Life prediction logic
+ */
+#define RUL_DATA_FILE                  HEART_FILE_PATH"/.rul_data.dat"
+#define RUL_CHARGING_CYCLES_FILE                       HEART_FILE_PATH"/.charging_cycles.dat"
+#define RUL_MIN_CAPACITY_DIFF                  50
+#define RUL_DISPLAY_ON_CUTOFF_RATIO                    0.1f
+#define RUL_DATA_SIZE                  32
+
+enum {
+       TA     = 0,     /* prediction based on total data average */
+       PCB    = 1,     /* prediction with physiological behaviors */
+       WEEK   = 2,     /* prediction based on weekly data */
+       COUNT  = 3,     /* prediction based on last BATTERY_PREDICTION_COUNT number of items */
+       PERIOD = 4,     /* prediction based on data from last BATTERY_PREDICTION_PERIOD time */
+       MAX_STRATEGY = 5,
+};
+
+enum {
+       POWER_NORMAL_MODE  = 0,
+       POWER_SAVING_MODE  = 1,
+       ULTRA_SAVING_MODE  = 2,
+       POWER_MODE_MAX     = 3,
+};
+
+enum {
+       BATTERY_LEVEL_LOW = 0, /* 15 ~ 0 */
+       BATTERY_LEVEL_MID = 1, /* 49 ~ 16 */
+       BATTERY_LEVEL_HIGH = 2, /* 50 ~ 100 */
+       BATTERY_LEVEL_MAX = 3,
+};
+
+enum {
+       DEFAULT_MIN = 0,
+       DEFAULT_AVG = 1,
+       DEFAULT_MAX = 2,
+       DEFAULT_VALUE_MAX = 3,
+};
+
+/* Structure to calculate percentage time LCD on during charging */
+struct rul_lcd_data {
+       display_state_e state;
+       long on_time;
+       long on_start_time;
+       long on_stop_time;
+};
+
+/* Structure to store RUL related charging info  */
+struct rul_info {
+       long charging_start_time;
+       long charging_stop_time;
+       float raw_capacity; /* capacity (mAh) accumulation during charging */
+       int soc_start; /* SoC(%) value when charging starts */
+       int soc_stop; /* SoC(%) value when charging stops */
+       int charging_cycles; /* Number of charging cycles */
+       int curr_soc; /* Current SoC %, compare with prev_soc to determine if charging */
+       int prev_soc; /* Previous value of SoC % */
+       struct rul_lcd_data lcd_data; /* LCD related data */
+};
+
+struct battery_used {
+       time_t used_time_sec; /* seconds on battery */
+       time_t last_update_time;
+       int last_charger_status;
+};
+
+struct battery_usage {
+       time_t start_time; /* timestamp when event started */
+       long sec_per_cap[MAX_CHARGER_STATE]; /* seconds per capacity level change */
+       long cap_counter[MAX_CHARGER_STATE]; /* number of capacity level changes */
+};
+
+struct battery_prediction {
+       long sec_per_cap[MAX_STRATEGY]; /* seconds per capacity level change */
+       long cap_counter[MAX_STRATEGY]; /* number of capacity level changes */
+       long time_pred_min[MAX_STRATEGY]; /* time prediction in minutes */
+};
+
+struct battery_pivot_info {
+       long start_time_dischg; /* store the time from when discharge started */
+       int pvt_data_ind; /* index to keep track of total_dischg_time value */
+       int start_cap_dischg; /* capacity from when discharge started */
+       int total_dischg_time[INDEX_WINDOW_SIZE]; /* total discharge period */
+       time_t last_clock_tick; /* last tick stored */
+};
+
+struct battery_status {
+       /* current battery status */
+       enum charger_status_type curr_charger_status;
+       int curr_capacity;
+
+       enum discharge_rate_level_type discharge_rate_level;
+       /* current runtime statistics */
+       long curr_run_time_sec[MAX_CHARGER_STATE]; /* seconds since reset */
+       long curr_cap_counter[MAX_CHARGER_STATE]; /* capacity level changes */
+
+       long last_wall_time[INDEX_WINDOW_SIZE];  /* previous battery level discharge time */
+       /* previous battery level change time in charging mode */
+       long last_wall_time_chg;
+       /* charging data index*/
+       int index_chg;
+       /* store last 5 battery level change time diff */
+       int last_wall_time_chg_diff[BATTERY_LEVEL_GAP];
+        /* indicates whether do we have enough data to estimate the battery time */
+       int data_available;
+       int curr_index;  /* store current index value */
+       int last_capacity;  /* last battery capacity value */
+       int last_capacity_chg; /* last battery capacity value in charge mode */
+       int remaining_time; /* previous remaining time */
+       int remaining_time_chg; /* previous remaining time in charging mode */
+       int remaining_time_ups; /* previous remaining time in UPS */
+       double last_volt_intg[INDEX_WINDOW_SIZE]; /* store previous calculated voltage integral(energy) value */
+       double last_pwr_bchg;  /* store the battery power available just before charging start */
+
+       /* wall clock time stamp when last event happened in seconds */
+       time_t last_event_wall_time;
+       time_t last_clock_tick;
+
+       /*
+        * reset mark is set when battery is charged in over 90% and
+        * charger was disconnected from the device.
+        * We consider then the device as "charged"
+        *
+        * The possible values are 0 and 1 they're swapped to opposite on change.
+        */
+       int reset_mark;
+       time_t reset_mark_timestamp;
+
+       /* usage time from last reset_mark change*/
+       struct battery_usage batt_reset_usage[BATTERY_HISTORY_RESET_MAX];
+
+       /* usage time by week day */
+       struct battery_usage week_day_usage[BATTERY_HISTORY_DAY_MAX];
+
+       /* usage time by user behavior & battery level */
+       struct battery_usage batt_lvl_usage[BATTERY_LEVEL_MAX];
+
+       /* calculated battery prediction */
+       struct battery_prediction prediction[MAX_CHARGER_STATE];
+
+       /* battery pivot information */
+       struct battery_pivot_info pvt;
+};
+
+static int default_sec_per_cap[MAX_CHARGER_STATE][DEFAULT_VALUE_MAX] = {
+       { 70, 670, 3600 }, /* DISCHARGING MIN: 70s, AVG: 670s, MAX: 1 hour */
+       { 30, 80, 3600 }    /* CHARGING MIN: 30s, AVG: 80s,  MAX: 1 hour */
+};
+
+static double default_mode_spc[POWER_MODE_MAX] = {
+       670,    /* POWER_NORMAL_MODE */
+       750,    /* POWER_SAVING_MODE */
+       1947    /* ULTRA_SAVING_MODE */
+};
+
+static double default_mode_factor[POWER_MODE_MAX] = {
+       1,      /* POWER_NORMAL_MODE */
+       1.1,    /* POWER_SAVING_MODE */
+       2.88    /* ULTRA_SAVING_MODE */
+};
+
+struct heart_power_profile {
+       float wifi_on;
+       float wifi_active;
+       float wifi_scan;
+};
+
+static struct heart_power_profile power_profile;
+#ifdef NETWORK_SUPPORT
+static struct heart_calc_time calc_time;
+#endif
+static struct battery_used batt_used;
+static struct battery_status batt_stat;
+static GSList *capacity_history_list = NULL;
+static pthread_mutex_t heart_battery_mutex = PTHREAD_MUTEX_INITIALIZER;
+static time_t last_file_commit_time;
+static int battery_learning_mode;
+
+static int ocv_degree; /* Degree of the OCV and SOC polynomial */
+static double *intg;   /* Co-efficients of the OCV and SOC polynomial */
+static double pivot_nor;  /* time pivot for normal mode */
+static double pivot_ups; /* time pivot for UPS mode */
+static double volt_intg_full; /* 100% battery voltage integral(engery) value */
+static bool data_avail_chg = false; /* 5 readings in charging mode */
+ /*
+ * variable to hold the current device mode(NORMAL, PS & UPS)
+ */
+static int device_mode = POWER_NORMAL_MODE;
+
+static int heart_battery_direct_get_capacity(void);
+
+/*
+ * Given the 'SOC', remaining energy of the cell can be predicted. New battery
+ * remaining time estimation logic will calculating the remaining energy as
+ * 'curr_volt_intg'.
+ *
+ * Based on estimated average power(P), a time estimate can be calcluated.
+ * Power can be estimated based on constant SOC interval Ps and constant
+ * time interval Pt.
+ *
+ * At high usage Ps will be short term average power and Pt will be long term
+ * average power.
+ *
+ * At low usage Ps will be long term average power and Pt will be short term
+ * average power.
+ *
+ * The new logic will calculate the average power 'batt_pwr' from Ps and Pt.
+ *
+ * Under-relaxation is a popular and effective technique of stabilizing prediction.
+ * The predicted time is stabilized around a pivot, which is calculated from the
+ * high-usage time and low-usage time
+ *
+ * The new logic will calculated 'pivot_nor' and 'pivot_ups' for normal and UPS
+ * mode respectively
+ *
+ * Finally, using current available energy(curr_volt_intg), average power(batt_pwr)
+ * and pivot time (pivot_nor or pivot_ups) this new logic will estimate the Battery
+ * Remaining Time for normal mode and UPS mode
+ */
+/*
+ * new battery remaining time estimation logic
+ */
+static int logic_v2;
+/*
+ * Total time taken in minutes when device is discharging at fastest rate
+ */
+static int discharge_fast;
+/*
+ * Total time taken in minutes when device is discharging at slowest rate
+ */
+static int discharge_slow;
+/*
+ * Avarage power consumed in UPS mode
+ */
+static double average_pwr;
+/*
+ * Total battery capacity in minutes(mAM)
+ */
+static int total_battery_capacity;
+/*
+ * This variable indicates first battery level update after charger insert
+ */
+static bool first_level_change = FALSE;
+/*
+ * This variable indicates the battery header used in heart.conf file
+ */
+static char battery_header[BATTERY_LINE_MAX] = "BATTERY";
+
+/*
+ * Remaining Useful Life (RUL) prediction logic
+ */
+static int logic_rul;
+struct rul_info rul;
+
+static int get_battery_remaining_time(int mode, enum charger_status_type status);
+
+int heart_battery_get_capacity(void)
+{
+       return batt_stat.curr_capacity;
+}
+
+enum charger_status_type heart_battery_get_charger_status(void)
+{
+       return batt_stat.curr_charger_status;
+}
+
+static inline void heart_battery_set_usage_reset_stime(int history, time_t start_time)
+{
+       batt_stat.batt_reset_usage[history].start_time = start_time;
+}
+
+static inline void heart_battery_set_usage_reset(int history, enum charger_status_type status, long sec_per_cap, long cap_counter)
+{
+       batt_stat.batt_reset_usage[history].sec_per_cap[status] = sec_per_cap;
+       batt_stat.batt_reset_usage[history].cap_counter[status] = cap_counter;
+}
+
+static inline long heart_battery_get_usage_reset_total_time(int history, enum charger_status_type status)
+{
+       return batt_stat.batt_reset_usage[history].sec_per_cap[status] * batt_stat.batt_reset_usage[history].cap_counter[status];
+}
+
+static inline long heart_battery_get_usage_reset_count(int history, enum charger_status_type status)
+{
+       return batt_stat.batt_reset_usage[history].cap_counter[status];
+}
+
+static inline void heart_battery_set_usage_level_stime(int level, time_t start_time)
+{
+       batt_stat.batt_lvl_usage[level].start_time = start_time;
+}
+
+static inline void heart_battery_set_usage_level(int level, enum charger_status_type status, long sec_per_cap, long cap_counter)
+{
+       batt_stat.batt_lvl_usage[level].sec_per_cap[status] = sec_per_cap;
+       batt_stat.batt_lvl_usage[level].cap_counter[status] = cap_counter;
+}
+
+static inline long heart_battery_get_usage_level_total_time(int level, enum charger_status_type status)
+{
+       return batt_stat.batt_lvl_usage[level].sec_per_cap[status] * batt_stat.batt_lvl_usage[level].cap_counter[status];
+}
+
+static inline long heart_battery_get_usage_level_spc(int level, enum charger_status_type status)
+{
+       return batt_stat.batt_lvl_usage[level].sec_per_cap[status];
+}
+
+static inline long heart_battery_get_usage_level_count(int level, enum charger_status_type status)
+{
+       return batt_stat.batt_lvl_usage[level].cap_counter[status];
+}
+
+static inline long heart_battery_get_usage_week_total_time(int day, enum charger_status_type status)
+{
+       return batt_stat.week_day_usage[day].sec_per_cap[status] * batt_stat.week_day_usage[day].cap_counter[status];
+}
+
+static inline long heart_battery_get_usage_week_count(int day, enum charger_status_type status)
+{
+       return batt_stat.week_day_usage[day].cap_counter[status];
+}
+
+static inline void heart_battery_set_usage_week_stime(int day, time_t start_time)
+{
+       batt_stat.week_day_usage[day].start_time = start_time;
+}
+
+static inline time_t heart_battery_get_usage_week_stime(int day)
+{
+       return batt_stat.week_day_usage[day].start_time;
+}
+
+static inline int heart_battery_get_learning_mode(void)
+{
+       int i, count = 0;
+
+       if (logic_v2) { /* new logic */
+               /*wait till enough data gets collected to estimated battery remaining time */
+               if (batt_stat.data_available == TRUE)
+                       return 1;
+               return 0;
+       }
+        /* old logic */
+       for (i = 0; i < BATTERY_HISTORY_DAY_MAX; i++) {
+               if (heart_battery_get_usage_week_stime(i))
+                       count++;
+               if (count > 1)
+                       return 1;
+       }
+       return 0;
+}
+
+static inline void heart_battery_set_usage_week(int day, enum charger_status_type status, long sec_per_cap, long cap_counter)
+{
+       batt_stat.week_day_usage[day].sec_per_cap[status] = sec_per_cap;
+       batt_stat.week_day_usage[day].cap_counter[status] = cap_counter;
+}
+
+static inline void heart_battery_set_prediction(int strategy, enum charger_status_type status, long sec_per_cap, long cap_counter, long pred_min)
+{
+       batt_stat.prediction[status].sec_per_cap[strategy] = sec_per_cap;
+       batt_stat.prediction[status].cap_counter[strategy] = cap_counter;
+       batt_stat.prediction[status].time_pred_min[strategy] = pred_min;
+}
+
+static inline long heart_battery_get_prediction_time(int strategy, enum charger_status_type status)
+{
+       return batt_stat.prediction[status].time_pred_min[strategy];
+}
+
+static inline time_t heart_battery_get_file_commit_timestamp()
+{
+       return last_file_commit_time;
+}
+
+static inline void heart_battery_set_file_commit_timestamp(time_t timestamp)
+{
+       last_file_commit_time = timestamp;
+}
+
+static int heart_battery_calculate_discharge_rate_level(long spc)
+{
+       long gap, total_spc;
+
+       total_spc = batt_stat.prediction[DISCHARGING].sec_per_cap[TA];
+       if (!total_spc)
+               return BATTERY_DISCHARGE_NONE;
+       gap = (total_spc * DISCHARGE_BASE_RATE);
+
+       _I("total: %ld, spc: %ld, gap: %ld", total_spc, spc, gap);
+
+       if (total_spc + gap < spc)
+               return BATTERY_DISCHARGE_LOW;
+       else if (total_spc - gap > spc)
+               return BATTERY_DISCHARGE_HIGH;
+
+       return BATTERY_DISCHARGE_AVG;
+}
+
+static void heart_battery_save_used_time(char *key, struct battery_used *used)
+{
+       assert(key);
+       assert(used);
+
+       logging_leveldb_putv(key, strlen(key), "%d %d ",
+                       used->used_time_sec, used->last_update_time);
+};
+
+static void heart_battery_save_status(char *key, struct battery_status *status)
+{
+       assert(key);
+       assert(status);
+
+       logging_leveldb_putv(key, strlen(key), "%d %ld %ld %ld %ld %d %d ",
+                       status->curr_capacity,
+                       status->curr_run_time_sec[DISCHARGING],
+                       status->curr_cap_counter[DISCHARGING],
+                       status->curr_run_time_sec[CHARGING],
+                       status->curr_cap_counter[CHARGING],
+                       status->curr_charger_status,
+                       status->reset_mark);
+};
+
+static void heart_battery_save_usage(char *key, struct battery_usage *usage, int total_size)
+{
+       int i, len, num;
+       char buf[BATTERY_DATA_MAX] = {0, };
+
+       assert(key);
+       assert(usage);
+
+       len = 0;
+       num = total_size/sizeof(struct battery_usage);
+       for (i = 0; i < num; i++) {
+               len += snprintf(buf + len, BATTERY_DATA_MAX - len, "%ld %ld %ld %ld %ld ",
+                               usage[i].start_time,
+                               usage[i].sec_per_cap[DISCHARGING],
+                               usage[i].cap_counter[DISCHARGING],
+                               usage[i].sec_per_cap[CHARGING],
+                               usage[i].cap_counter[CHARGING]);
+       }
+       logging_leveldb_put(key, strlen(key), buf, len);
+};
+
+static void heart_battery_save_prediction(char *key, struct battery_prediction *prediction)
+{
+       int i, len;
+       char buf[BATTERY_DATA_MAX] = {0, };
+
+       assert(key);
+       assert(prediction);
+
+       len = 0;
+       for (i = 0; i < MAX_STRATEGY; i++) {
+               len += snprintf(buf + len, BATTERY_DATA_MAX - len, "%ld %ld %ld %ld %ld %ld ",
+                               prediction[DISCHARGING].sec_per_cap[i],
+                               prediction[DISCHARGING].cap_counter[i],
+                               prediction[DISCHARGING].time_pred_min[i],
+                               prediction[CHARGING].sec_per_cap[i],
+                               prediction[CHARGING].cap_counter[i],
+                               prediction[CHARGING].time_pred_min[i]);
+       }
+       logging_leveldb_put(key, strlen(key), buf, len);
+};
+
+
+static int heart_battery_load_used_time(char *key, struct battery_used *used)
+{
+       int ret;
+       char *token;
+       char buf[BATTERY_DATA_MAX] = {0, };
+       char *saveptr;
+
+       if (!key || !used)
+               return RESOURCED_ERROR_FAIL;
+
+       ret = logging_leveldb_read(key, strlen(key), buf, sizeof(buf));
+       if (ret != RESOURCED_ERROR_NONE) {
+               _E("Failed to read leveldb key: %s", key);
+               return RESOURCED_ERROR_FAIL;
+       }
+       token = strtok_r(buf, " ", &saveptr);
+       if (!token) {
+               _E("Failed to token value");
+               return RESOURCED_ERROR_FAIL;
+       }
+       used->used_time_sec = atoi(token);
+       token = strtok_r(NULL, " ", &saveptr);
+       if (!token) {
+               _E("Failed to token value");
+               return RESOURCED_ERROR_FAIL;
+       }
+       used->last_update_time = atoi(token);
+       return RESOURCED_ERROR_NONE;
+};
+
+static int heart_battery_load_status(char *key, struct battery_status *status)
+{
+       int ret;
+       char *token;
+       char buf[BATTERY_DATA_MAX] = {0, };
+       char *saveptr;
+
+       if (!key || !status)
+               return RESOURCED_ERROR_FAIL;
+
+       ret = logging_leveldb_read(key, strlen(key), buf, sizeof(buf));
+       if (ret != RESOURCED_ERROR_NONE) {
+               _E("Failed to read leveldb key: %s", key);
+               return RESOURCED_ERROR_FAIL;
+       }
+       token = strtok_r(buf, " ", &saveptr);
+       if (!token) {
+               _E("Failed to token value");
+               return RESOURCED_ERROR_FAIL;
+       }
+       status->curr_capacity = atoi(token);
+       token = strtok_r(NULL, " ", &saveptr);
+       if (!token) {
+               _E("Failed to token value");
+               return RESOURCED_ERROR_FAIL;
+       }
+       status->curr_run_time_sec[DISCHARGING] = atol(token);
+       token = strtok_r(NULL, " ", &saveptr);
+       if (!token) {
+               _E("Failed to token value");
+               return RESOURCED_ERROR_FAIL;
+       }
+       status->curr_cap_counter[DISCHARGING] = atol(token);
+       token = strtok_r(NULL, " ", &saveptr);
+       if (!token) {
+               _E("Failed to token value");
+               return RESOURCED_ERROR_FAIL;
+       }
+       status->curr_run_time_sec[CHARGING] = atol(token);
+       token = strtok_r(NULL, " ", &saveptr);
+       if (!token) {
+               _E("Failed to token value");
+               return RESOURCED_ERROR_FAIL;
+       }
+       status->curr_cap_counter[CHARGING] = atol(token);
+       token = strtok_r(NULL, " ", &saveptr);
+       if (!token) {
+               _E("Failed to token value");
+               return RESOURCED_ERROR_FAIL;
+       }
+       status->curr_charger_status = atoi(token);
+       token = strtok_r(NULL, " ", &saveptr);
+       if (!token) {
+               _E("Failed to token value");
+               return RESOURCED_ERROR_FAIL;
+       }
+       status->reset_mark = atoi(token);
+       return RESOURCED_ERROR_NONE;
+};
+
+static int heart_battery_load_usage(char *key, struct battery_usage *usage, int total_size)
+{
+       int i, num, ret;
+       char *token;
+       char buf[BATTERY_DATA_MAX] = {0, };
+       char *saveptr;
+
+       if (!key || !usage)
+               return RESOURCED_ERROR_FAIL;
+
+       ret = logging_leveldb_read(key, strlen(key), buf, sizeof(buf));
+       if (ret != RESOURCED_ERROR_NONE) {
+               _E("Failed to read leveldb key");
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       if (buf[0] == '\0') {
+               _D("There is no history about %s", key);
+               return RESOURCED_ERROR_NONE;
+       }
+
+       i = 0;
+       num = total_size/sizeof(struct battery_usage);
+       token = strtok_r(buf, " ", &saveptr);
+       if (!token) {
+               _E("Failed to token value");
+               return RESOURCED_ERROR_FAIL;
+       }
+       while (token && i++ < num) {
+               usage[i].start_time = atol(token);
+               token = strtok_r(NULL, " ", &saveptr);
+               if (!token) {
+                       _E("Failed to token value");
+                       return RESOURCED_ERROR_FAIL;
+               }
+               usage[i].sec_per_cap[DISCHARGING] = atol(token);
+               token = strtok_r(NULL, " ", &saveptr);
+               if (!token) {
+                       _E("Failed to token value");
+                       return RESOURCED_ERROR_FAIL;
+               }
+               usage[i].cap_counter[DISCHARGING] = atol(token);
+               token = strtok_r(NULL, " ", &saveptr);
+               if (!token) {
+                       _E("Failed to token value");
+                       return RESOURCED_ERROR_FAIL;
+               }
+               usage[i].sec_per_cap[CHARGING] = atol(token);
+               token = strtok_r(NULL, " ", &saveptr);
+               if (!token) {
+                       _E("Failed to token value");
+                       return RESOURCED_ERROR_FAIL;
+               }
+               usage[i].cap_counter[CHARGING] = atol(token);
+               token = strtok_r(NULL, " ", &saveptr);
+               _D("load [%d] stime: %ld, spc: %ld, count: %ld, spc: %ld, count: %ld",
+                               i, usage[i].start_time, usage[i].sec_per_cap[DISCHARGING],
+                               usage[i].cap_counter[DISCHARGING], usage[i].sec_per_cap[CHARGING],
+                               usage[i].cap_counter[CHARGING]);
+       }
+       return RESOURCED_ERROR_NONE;
+};
+
+static int heart_battery_load_prediction(char *key, struct battery_prediction *prediction)
+{
+       int ret, i;
+       char *token;
+       char buf[BATTERY_DATA_MAX] = {0, };
+       char *saveptr;
+
+       if (!key || !prediction)
+               return RESOURCED_ERROR_FAIL;
+
+       ret = logging_leveldb_read(key, strlen(key), buf, sizeof(buf));
+       if (ret != RESOURCED_ERROR_NONE) {
+               _E("Failed to read leveldb key: %s", key);
+               return RESOURCED_ERROR_FAIL;
+       }
+       token = strtok_r(buf, " ", &saveptr);
+       if (!token) {
+               _E("Failed to token value");
+               return RESOURCED_ERROR_FAIL;
+       }
+       for (i = 0; i < MAX_STRATEGY && token; i++) {
+               prediction[DISCHARGING].sec_per_cap[i] = atol(token);
+               token = strtok_r(NULL, " ", &saveptr);
+               if (!token) {
+                       _E("Failed to token value");
+                       return RESOURCED_ERROR_FAIL;
+               }
+               prediction[DISCHARGING].cap_counter[i] = atol(token);
+               token = strtok_r(NULL, " ", &saveptr);
+               if (!token) {
+                       _E("Failed to token value");
+                       return RESOURCED_ERROR_FAIL;
+               }
+               prediction[DISCHARGING].time_pred_min[i] = atol(token);
+               token = strtok_r(NULL, " ", &saveptr);
+               if (!token) {
+                       _E("Failed to token value");
+                       return RESOURCED_ERROR_FAIL;
+               }
+               prediction[CHARGING].sec_per_cap[i] = atol(token);
+               token = strtok_r(NULL, " ", &saveptr);
+               if (!token) {
+                       _E("Failed to token value");
+                       return RESOURCED_ERROR_FAIL;
+               }
+               prediction[CHARGING].cap_counter[i] = atol(token);
+               token = strtok_r(NULL, " ", &saveptr);
+               if (!token) {
+                       _E("Failed to token value");
+                       return RESOURCED_ERROR_FAIL;
+               }
+               prediction[CHARGING].time_pred_min[i] = atol(token);
+               token = strtok_r(NULL, " ", &saveptr);
+       }
+       return RESOURCED_ERROR_NONE;
+};
+
+static void heart_battery_update_used_time(time_t now, enum charger_status_type status)
+{
+       if (batt_used.last_charger_status == DISCHARGING)
+               batt_used.used_time_sec +=
+                       now - batt_used.last_update_time;
+       batt_used.last_charger_status = status;
+       batt_used.last_update_time = now;
+       heart_battery_save_used_time(BATTERY_USED_TIME, &batt_used);
+}
+
+static int heart_battery_get_capacity_history_size(void)
+{
+       int size, ret;
+
+       ret = pthread_mutex_lock(&heart_battery_mutex);
+       if (ret) {
+               _E("pthread_mutex_lock() failed, %d", ret);
+               return RESOURCED_ERROR_FAIL;
+       }
+       size = g_slist_length(capacity_history_list);
+       if (!size) {
+               _I("capacity history is empty");
+               ret = pthread_mutex_unlock(&heart_battery_mutex);
+               if (ret) {
+                       _E("pthread_mutex_unlock() failed, %d", ret);
+                       return RESOURCED_ERROR_FAIL;
+               }
+               return RESOURCED_ERROR_NONE;
+       }
+       ret = pthread_mutex_unlock(&heart_battery_mutex);
+       if (ret) {
+               _E("pthread_mutex_unlock() failed, %d", ret);
+               return RESOURCED_ERROR_FAIL;
+       }
+       return size;
+}
+
+static void heart_battery_insert_capacity(GSList **history_list, int capacity,
+               int diff_capacity, time_t timestamp, long used_time, long charging_time,
+               enum charger_status_type charger_status, int reset_mark, int clear)
+{
+       static int old_reset_mark = 0;
+       GSList *iter, *next;
+       int ret, count;
+       struct heart_battery_capacity *lbc, *tlbc;
+
+       lbc = malloc(sizeof(struct heart_battery_capacity));
+       if (!lbc) {
+               _E("malloc failed");
+               return;
+       }
+       lbc->capacity = capacity;
+       lbc->diff_capacity = diff_capacity;
+       lbc->used_time = used_time;
+       lbc->charging_time = charging_time;
+       lbc->charger_status = charger_status;
+       lbc->reset_mark = reset_mark;
+       lbc->timestamp = timestamp;
+
+       ret = pthread_mutex_lock(&heart_battery_mutex);
+       if (ret) {
+               _E("pthread_mutex_lock() failed, %d", ret);
+               free(lbc);
+               return;
+       }
+       /* clean all history when reset event */
+       if (clear && *history_list && lbc->reset_mark != old_reset_mark) {
+               g_slist_free_full(*history_list, free);
+               *history_list = NULL;
+       }
+
+       /* history reached maximum limitation number */
+       if (*history_list && g_slist_length(*history_list) > BATTERY_CAPACITY_MAX) {
+               count = 0;
+               gslist_for_each_safe(*history_list, iter, next, tlbc) {
+                       *history_list = g_slist_remove(*history_list, (gpointer)tlbc);
+                       free(tlbc);
+                       if (BATTERY_CLEAN_MAX < count++)
+                               break;
+               }
+       }
+       old_reset_mark = lbc->reset_mark;
+       *history_list = g_slist_append(*history_list, (gpointer)lbc);
+       ret = pthread_mutex_unlock(&heart_battery_mutex);
+       if (ret)
+               _E("pthread_mutex_unlock() failed, %d", ret);
+}
+
+/* ======================== Serialization/Deserialization ==================== */
+
+static void heart_battery_status_save_to_db(void)
+{
+       heart_battery_save_used_time(BATTERY_USED_TIME, &batt_used);
+       heart_battery_save_status(BATTERY_STATUS, &batt_stat);
+
+       heart_battery_save_usage(BATTERY_RESET_USAGE, batt_stat.batt_reset_usage, sizeof(batt_stat.batt_reset_usage));
+       heart_battery_save_usage(BATTERY_WEEK_DAY_USAGE, batt_stat.week_day_usage, sizeof(batt_stat.week_day_usage));
+       heart_battery_save_usage(BATTERY_LEVEL_USAGE, batt_stat.batt_lvl_usage, sizeof(batt_stat.batt_lvl_usage));
+
+       heart_battery_save_prediction(BATTERY_PREDICTION, batt_stat.prediction);
+}
+
+static int heart_battery_status_read_from_db(void)
+{
+       bool ok = true;
+
+       ok &= (RESOURCED_ERROR_NONE == heart_battery_load_used_time(BATTERY_USED_TIME, &batt_used));
+       ok &= (RESOURCED_ERROR_NONE == heart_battery_load_status(BATTERY_STATUS, &batt_stat));
+
+       ok &= (RESOURCED_ERROR_NONE == heart_battery_load_usage(BATTERY_RESET_USAGE, batt_stat.batt_reset_usage, sizeof(batt_stat.batt_reset_usage)));
+       ok &= (RESOURCED_ERROR_NONE == heart_battery_load_usage(BATTERY_WEEK_DAY_USAGE, batt_stat.week_day_usage, sizeof(batt_stat.week_day_usage)));
+       ok &= (RESOURCED_ERROR_NONE == heart_battery_load_usage(BATTERY_LEVEL_USAGE, batt_stat.batt_lvl_usage, sizeof(batt_stat.batt_lvl_usage)));
+
+       ok &= (RESOURCED_ERROR_NONE == heart_battery_load_prediction(BATTERY_PREDICTION, batt_stat.prediction));
+
+       return ok ? RESOURCED_ERROR_NONE : RESOURCED_ERROR_FAIL;
+}
+
+static int heart_battery_capacity_save_to_file(char *filename)
+{
+       int size, ret, count, len = 0;
+       struct heart_battery_capacity *lbc;
+       GSList *iter, *next;
+       FILE *fp;
+       char buf[BATTERY_DATA_MAX] = {0, };
+
+       if (!capacity_history_list) {
+               _E("capacity history is NULL!");
+               return RESOURCED_ERROR_NONE;
+       }
+       ret = pthread_mutex_lock(&heart_battery_mutex);
+       if (ret) {
+               _E("pthread_mutex_lock() failed, %d", ret);
+               return RESOURCED_ERROR_FAIL;
+       }
+       size = g_slist_length(capacity_history_list);
+       if (!size) {
+               _I("capacity history is empty");
+               ret = pthread_mutex_unlock(&heart_battery_mutex);
+               if (ret) {
+                       _E("pthread_mutex_unlock() failed, %d", ret);
+                       return RESOURCED_ERROR_FAIL;
+               }
+               return RESOURCED_ERROR_NONE;
+       }
+       fp = fopen(filename, "w");
+       if (!fp) {
+               _E("%s fopen failed %d", filename, errno);
+               ret = pthread_mutex_unlock(&heart_battery_mutex);
+               if (ret) {
+                       _E("pthread_mutex_unlock() failed, %d", ret);
+                       return RESOURCED_ERROR_FAIL;
+               }
+               return RESOURCED_ERROR_FAIL;
+       }
+       gslist_for_each_item(iter, capacity_history_list) {
+               lbc = (struct heart_battery_capacity *)iter->data;
+               if (!lbc)
+                       break;
+               len += snprintf(buf + len, BATTERY_DATA_MAX - len, "%d %d %ld %ld %ld %d %d\n",
+                               lbc->capacity, lbc->diff_capacity, lbc->timestamp, lbc->used_time,
+                               lbc->charging_time, lbc->charger_status,
+                               lbc->reset_mark);
+               if (BATTERY_DATA_MAX < len + BATTERY_LINE_MAX) {
+                       fputs(buf, fp);
+                       len = 0;
+               }
+       }
+       fputs(buf, fp);
+       fclose(fp);
+       if (BATTERY_CAPACITY_MAX < size) {
+               count = 0;
+               gslist_for_each_safe(capacity_history_list, iter, next, lbc) {
+                       capacity_history_list = g_slist_remove(capacity_history_list, (gpointer)lbc);
+                       free(lbc);
+                       if (BATTERY_CLEAN_MAX < count++)
+                               break;
+               }
+       }
+       ret = pthread_mutex_unlock(&heart_battery_mutex);
+       if (ret) {
+               _E("pthread_mutex_unlock() failed, %d", ret);
+               return RESOURCED_ERROR_FAIL;
+       }
+       return RESOURCED_ERROR_NONE;
+}
+
+static int heart_battery_capacity_read_from_file(char *filename)
+{
+       int len;
+       int capacity, diff_capacity, charger_status, reset_mark;
+       long used_time, charging_time;
+       time_t timestamp;
+       FILE *fp;
+       char buf[BATTERY_DATA_MAX] = {0, };
+       int ret;
+
+       fp = fopen(filename, "r");
+       if (!fp) {
+               if (errno != ENOENT) {
+                       _E("Fail to open %s (%d)", buf, errno);
+                       return RESOURCED_ERROR_FAIL;
+               }
+
+               _D("%s doesn't exist. Make new one.", buf);
+               ret = mkdir(HEART_FILE_PATH, S_IRWXU | S_IRWXG | S_IROTH);
+               if (ret != 0 && errno != EEXIST) {
+                       _E("Fail to create %s (%d)", buf, errno);
+                       return RESOURCED_ERROR_FAIL;
+               }
+
+               fp = fopen(filename, "w+");
+               if (!fp) {
+                       _E("Fail to create %s (%d)", buf, errno);
+                       return RESOURCED_ERROR_FAIL;
+               }
+               fclose(fp);
+               return RESOURCED_ERROR_NONE;
+       }
+
+       while (fgets(buf, BATTERY_DATA_MAX, fp)) {
+               len = sscanf(buf, "%d %d %ld %ld %ld %d %d", &capacity, &diff_capacity,
+                               &timestamp, &used_time, &charging_time,
+                               &charger_status, &reset_mark);
+               if (len < 0) {
+                       _E("sscanf failed");
+                       fclose(fp);
+                       return RESOURCED_ERROR_FAIL;
+               }
+               heart_battery_insert_capacity(&capacity_history_list, capacity, diff_capacity,
+                               timestamp, used_time, charging_time,
+                               charger_status, reset_mark, true);
+       }
+       fclose(fp);
+       return RESOURCED_ERROR_NONE;
+}
+
+/* ==================== Serialization/Deserialization END ==================== */
+
+static void heart_battery_save_to_file(bool force)
+{
+       int ret;
+       time_t now = logging_get_time(CLOCK_BOOTTIME);
+
+       heart_battery_update_used_time(now, batt_stat.curr_charger_status);
+
+       if (!force &&
+           heart_battery_get_file_commit_timestamp() + HEART_BATTERY_SAVE_INTERVAL >= now)
+               return;
+
+       heart_battery_status_save_to_db();
+
+       ret = heart_battery_capacity_save_to_file(HEART_BATTERY_CAPACITY_DATA_FILE);
+       if (ret)
+               _E("failed to save capacity file");
+       heart_battery_set_file_commit_timestamp(now);
+}
+
+/*
+ * This function will open the '.battery_data.dat' file and write all battery
+ * related data into it.
+ */
+static void heart_battery_write_data_to_file(void)
+{
+       int i;
+       int len = 0;
+       char buff[BATTERY_DATA_MAX] = {0, 0};
+       _cleanup_fclose_ FILE *fp = NULL;
+
+       fp = fopen(HEART_BATTERY_DATA_FILE, "w");
+       if (fp == NULL) {
+               _E("Could not open file battery_data file\n");
+               return;
+       }
+
+       for (i = 0; i < INDEX_WINDOW_SIZE; i++) {
+               len += snprintf(buff + len, BATTERY_DATA_MAX - len, "%ld %lf\n", \
+                       batt_stat.last_wall_time[i], batt_stat.last_volt_intg[i]);
+
+               if (BATTERY_DATA_MAX < len + BATTERY_LINE_MAX) {
+                       fputs(buff, fp);
+                       len = 0;
+               }
+       }
+       len += snprintf(buff + len, BATTERY_DATA_MAX - len, "%d %d %d %d %lf %d", \
+               batt_stat.curr_index, batt_stat.last_capacity, batt_stat.remaining_time, \
+               batt_stat.remaining_time_ups, batt_stat.last_pwr_bchg, batt_stat.data_available);
+
+       fputs(buff, fp);
+}
+
+/*
+ * This function will open the '.battery_data.dat' file and read all battery
+ * related data from it and store in variable 'batt_stat'
+ */
+static void heart_battery_read_data_from_file(void)
+{
+       int i;
+       int len = 0;
+       char buff[BATTERY_DATA_MAX] = {0, 0};
+       char *ch;
+       _cleanup_fclose_ FILE *fp = NULL;
+
+       fp = fopen(HEART_BATTERY_DATA_FILE, "r");
+       if (fp == NULL) {
+               _E("Could not open battery_data file\n");
+               return;
+       }
+
+       for (i = 0; i < INDEX_WINDOW_SIZE; i++) {
+               ch = fgets(buff, BATTERY_DATA_MAX, fp);
+               if (ch == NULL)
+                       /*if file is empty then return from here */
+                       return;
+
+               len += sscanf(buff, "%ld %lf", \
+                               &batt_stat.last_wall_time[i], &batt_stat.last_volt_intg[i]);
+       }
+
+       ch = fgets(buff, BATTERY_DATA_MAX, fp);
+       if (ch != NULL)
+               len += sscanf(buff, "%d %d %d %d %lf %d", \
+                       &batt_stat.curr_index, &batt_stat.last_capacity, &batt_stat.remaining_time, \
+                       &batt_stat.remaining_time_ups, &batt_stat.last_pwr_bchg, &batt_stat.data_available);
+}
+
+/*
+ * This function will reject all the battery related data which were stored earlier
+ */
+static void heart_battery_reject_data(void)
+{
+       int i;
+
+       for (i = 0; i < INDEX_WINDOW_SIZE; i++) {
+               batt_stat.last_wall_time[i] = 0;
+               batt_stat.last_volt_intg[i] = 0.0;
+       }
+
+       /* Do not reject this, once data available, do not change untill next binary flash */
+       /*batt_stat.data_available = 0;   */
+       batt_stat.last_capacity = 0;
+       batt_stat.curr_index = 0;
+       batt_stat.remaining_time = 0;
+       batt_stat.remaining_time_ups = 0;
+       /* do not flush this value. When proper power value is not present, previously
+       calculated power only will be used. */
+       /*batt_stat.last_pwr_bchg = 0.0;  */
+
+       heart_battery_write_data_to_file();
+}
+
+/*
+ * This function will calculate the voltage integral(energy) at battery level 100.
+ * We will calculate Pivot using fast discharge and slow discharge rate for
+ * estimating the battery time in normal mode
+ */
+static void heart_battery_calculate_pivot(void)
+{
+       int i;
+
+       for (i = 0; i < ocv_degree; i++)
+               volt_intg_full += (intg[i] /(i+1)) * pow(100 , i+1);
+       volt_intg_full = volt_intg_full/100000.0;
+
+       pivot_nor = ((sqrt(discharge_fast) + sqrt(discharge_slow))/2);
+       pivot_nor = pivot_nor * pivot_nor; // taking square of Tpivot
+
+       pivot_ups = ((sqrt(discharge_fast*UPS_FACTOR) + sqrt(discharge_slow*UPS_FACTOR))/2);
+       pivot_ups = pivot_ups * pivot_ups; // taking square of Tpivot
+}
+
+/* function to return the time(in seconds) since the  Epoch*/
+static long heart_battery_logging_get_time_sec_new(void)
+{
+       struct timeval tv;
+
+       gettimeofday(&tv, NULL);
+
+       return (tv.tv_sec + tv.tv_usec / 1000000);
+}
+
+/*
+ * This function will read the current time and will compare with previously stored time.
+ * If time difference is more then it is assumed that device was powered off and it will
+ * adjust all stored time values
+ */
+static void heart_battery_power_off_time_adjustment(void)
+{
+       int i;
+       int index;
+       int clock_tick_diff = 0;
+       long int curr_time;
+       long int time_diff = 0;
+
+       curr_time = heart_battery_logging_get_time_sec_new();
+
+       index = BATTERY_WINDOW_INDEX(batt_stat.curr_index - 1);
+       if (batt_stat.last_wall_time[index] == 0)
+               index = 0;
+
+       clock_tick_diff = logging_get_time(CLOCK_BOOTTIME) - batt_stat.last_clock_tick;
+
+       /* check if we have store last time value or not */
+       if (batt_stat.last_wall_time[index] != 0) {
+               time_diff = curr_time - batt_stat.last_wall_time[index];
+               time_diff -= clock_tick_diff;
+       }
+
+       _I("All store time value will be scaled up by %ld secs\n", time_diff);
+
+       /*scale up all stored time value */
+       for (i = 0; i < INDEX_WINDOW_SIZE; i++) {
+               if (batt_stat.last_wall_time[i] == 0) {
+                       /* we do not have stored time value from this point onwards, stop updating*/
+                       break;
+               } else
+                       batt_stat.last_wall_time[i] += time_diff;
+       }
+
+       /* update same value in battery data file*/
+       heart_battery_write_data_to_file();
+
+       /*
+        * during charge time
+        */
+       time_diff = curr_time - batt_stat.last_wall_time_chg;
+       time_diff -= clock_tick_diff;
+       /*
+         * update last_wall_time_chg as per previous and new time diff
+         * it will take care of positive of negative difference
+         */
+       batt_stat.last_wall_time_chg += time_diff;
+       _I("last_wall_time_chg got updated by %ld\n", time_diff);
+       /*
+         * make first_level_change as TRUE so that charge remaining time
+         * should not vary much
+         */
+       first_level_change = TRUE;
+
+       /* for pivot data */
+       if (batt_stat.pvt.start_time_dischg != 0) {
+               time_diff = curr_time - batt_stat.pvt.start_time_dischg;
+               clock_tick_diff = logging_get_time(CLOCK_BOOTTIME) - batt_stat.pvt.last_clock_tick;
+               time_diff -= clock_tick_diff;
+               batt_stat.pvt.start_time_dischg += time_diff;
+       }
+}
+
+/*
+ * In case of any time change in the device, this callback get called and it
+ * will do the time adjustment
+ */
+static void time_change_notify_cb(keynode_t *key, void *data)
+{
+       heart_battery_power_off_time_adjustment();
+}
+
+static int get_battery_remaining_time_new(void)
+{
+       return batt_stat.remaining_time;
+}
+
+static int get_battery_remaining_time_ups()
+{
+       return batt_stat.remaining_time_ups;
+}
+
+/*
+ * This function will return the average of stored time diff values
+ */
+static int heart_battery_get_time_diff_avg(int time_diff_avg)
+{
+       int temp_index;
+       int i;
+
+       if (data_avail_chg == true) {
+               /*
+                * calculate the average of last 5(including current) time diff values
+                */
+               temp_index = ((batt_stat.index_chg-1) + BATTERY_LEVEL_GAP) % BATTERY_LEVEL_GAP;
+               for (i = 1; i < BATTERY_LEVEL_GAP; i++) {
+                       time_diff_avg += batt_stat.last_wall_time_chg_diff[temp_index];
+                       temp_index = ((temp_index-1) + BATTERY_LEVEL_GAP) % BATTERY_LEVEL_GAP;
+               }
+               time_diff_avg = time_diff_avg/BATTERY_LEVEL_GAP;
+       } else {
+               /*
+                * take average of only available data. Do not include 1st value so
+                * i stared from 1.
+                */
+               for (i = 1; i < batt_stat.index_chg; i++)
+                       time_diff_avg += batt_stat.last_wall_time_chg_diff[i];
+
+               time_diff_avg = time_diff_avg/i;
+       }
+       /*
+        * to minimize the time diff fluctuation
+        */
+       time_diff_avg = (time_diff_avg+BATTERY_C_RATE)/2;
+       _I("time_diff after averaging= %d seconds\n", time_diff_avg);
+
+       return time_diff_avg;
+}
+
+/*
+ * This function will return the time diff between last and current battery
+ * level change
+ */
+int heart_battery_get_time_diff(long curr_wall_time)
+{
+       if (batt_stat.last_wall_time_chg == 0)
+               /*
+                * First time estimation
+                * In this case charge rate will be considered as time diff
+                */
+               return BATTERY_C_RATE;
+
+       return (curr_wall_time - batt_stat.last_wall_time_chg);
+}
+
+static void heart_battery_print_prev_charge_data(void)
+{
+       int i;
+
+       _I("Charging stored data, current index = %d", batt_stat.index_chg);
+
+       for (i = 0; i < BATTERY_LEVEL_GAP; i++)
+               _I("Index = %d, time_diff = %d", i, batt_stat.last_wall_time_chg_diff[i]);
+}
+
+/*
+ * This function will flush the stored charge data
+ */
+static void heart_battery_flush_charge_data(void)
+{
+       int i;
+
+        _I("Prev and curr battery lvl gap = %d, flush charge data",
+               batt_stat.last_capacity_chg - batt_stat.curr_capacity);
+
+        for (i = 0; i < BATTERY_LEVEL_GAP; i++)
+               batt_stat.last_wall_time_chg_diff[i] = 0;
+
+        batt_stat.last_wall_time_chg = 0;
+        batt_stat.index_chg = 0;
+        data_avail_chg = false;
+}
+
+/*
+ * store the discharge start time and capacity to calculte the
+ * time taken for the discharge period
+ */
+static void heart_battery_collect_discharge_data(void)
+{
+       batt_stat.pvt.start_cap_dischg = batt_stat.curr_capacity;
+       batt_stat.pvt.start_time_dischg = heart_battery_logging_get_time_sec_new();
+       batt_stat.pvt.last_clock_tick = logging_get_time(CLOCK_BOOTTIME);
+}
+
+/*
+ * Read all the stored pivot data from file and keep it in
+ * local variable batt_stat.pvt
+ */
+static void heart_battery_read_pivot_info_from_file(void)
+{
+       int i;
+       char buf[BATTERY_DATA_MAX] = {0, };
+       char *p;
+       _cleanup_fclose_ FILE *fp = NULL;
+
+       fp = fopen(HEART_BATTERY_PIVOT_INFO, "r");
+       if (fp == NULL) {
+               _E("Could not open pivot info file");
+               return;
+       }
+
+       for (i = 0; i < INDEX_WINDOW_SIZE; i++) {
+               p = fgets(buf, BATTERY_DATA_MAX, fp);
+               if (p == NULL)
+                       return;
+
+               if (sscanf(buf, "%d", &batt_stat.pvt.total_dischg_time[i]) == -1)
+                       return;
+       }
+
+       p = fgets(buf, BATTERY_DATA_MAX, fp);
+       if (!p)
+               return;
+       if (sscanf(buf, "%d", &batt_stat.pvt.pvt_data_ind) == -1)
+               return;
+
+}
+
+/*
+ * Store all the local  pivot data to a file
+ */
+static void heart_battery_save_pivot_info(void)
+{
+       int len = 0;
+       int i;
+       char buf[BATTERY_DATA_MAX] = {0, };
+       _cleanup_fclose_ FILE *fp = NULL;
+
+       fp = fopen(HEART_BATTERY_PIVOT_INFO, "w");
+       if (fp == NULL) {
+               _E("Could not open pivot info file");
+               return;
+       }
+
+       for (i = 0; i < INDEX_WINDOW_SIZE; i++) {
+               len += snprintf(buf + len, BATTERY_DATA_MAX - len, "%d\n",
+                               batt_stat.pvt.total_dischg_time[i]);
+
+               if (BATTERY_DATA_MAX < len + BATTERY_LINE_MAX) {
+                       fputs(buf, fp);
+                       len = 0;
+               }
+       }
+       len += snprintf(buf + len, BATTERY_DATA_MAX - len, "%d",
+                       batt_stat.pvt.pvt_data_ind);
+
+       fputs(buf, fp);
+}
+
+/*
+ * Calculate the remaining enery in battery based on current capacity
+ */
+static double heart_battery_get_energy(int capacity)
+{
+       int i;
+       double volt_intg = 0;
+
+       for (i = 0; i < ocv_degree; i++)
+               volt_intg += (intg[i] /(i+1)) * pow(capacity , i+1);
+
+       return (volt_intg /100000.0);
+}
+
+/*
+ * Update the pivot based on device learning data
+ */
+static void heart_battery_update_pivot(void)
+{
+       int i;
+       int avg = 0;
+
+       static int count = 1;
+
+       for (i = 0; i < INDEX_WINDOW_SIZE; i++) {
+               if(batt_stat.pvt.total_dischg_time[i] == 0)
+                       break;
+               avg += batt_stat.pvt.total_dischg_time[i];
+       }
+
+       if (avg == 0)
+               return;
+       if (i != 0)
+               avg = (avg  / i);
+
+       /*
+        * Total 10 discharge cycle data will be stored and based on those values
+        * new pivot will be calculted. Untill 10 cycles data are not available, take
+        * count/10 % from new pivot and 1-count/10 % from existing pivot. By
+        * doing this, sudden jump in pivot can be avoided
+        */
+       if (count <= 10) {
+               avg = NEW_PIVOT_WEIGHTAGE(count) * avg + OLD_PIVOT_WEIGHTAGE(count) * pivot_nor;
+               count++;
+       }
+
+       _I("Old pivot = %lf, New pivot =%d, count = %d", pivot_nor, avg, count);
+
+       pivot_nor = avg;
+       pivot_ups = pivot_nor * UPS_FACTOR;
+}
+
+/*
+ * This function will take the average of last 10 discharge time period and
+ * update the pivot
+ */
+static void heart_battery_collect_pivot_info(void)
+{
+       long curr_time;
+       int time_diff;
+       int cap_diff;
+       int total_time;
+
+       double energy_dis;
+       double energy_chg;
+       double energy_total;
+
+       if (batt_stat.pvt.start_time_dischg == 0)
+               return;
+
+       curr_time = heart_battery_logging_get_time_sec_new();
+       time_diff = curr_time - batt_stat.pvt.start_time_dischg;
+       cap_diff = batt_stat.pvt.start_cap_dischg - batt_stat.curr_capacity;
+
+       /* discharge period is too less so do not consider this period */
+       if (cap_diff < MIN_DISCHARGE_PERIOD)
+               return;
+
+       energy_dis = heart_battery_get_energy(batt_stat.pvt.start_cap_dischg);
+       energy_chg = heart_battery_get_energy(batt_stat.curr_capacity);
+       energy_total = heart_battery_get_energy(FULL_CAPACITY);
+
+       total_time = (energy_total * time_diff) /(energy_dis - energy_chg);
+
+       _I("Energy discharge = %lf, Energy charge = %lf, Energy Total = %lf, Total time = %d",
+                               energy_dis, energy_chg, energy_total, total_time);
+
+       batt_stat.pvt.total_dischg_time[batt_stat.pvt.pvt_data_ind] = SEC_TO_MIN(total_time);
+       batt_stat.pvt.pvt_data_ind = (batt_stat.pvt.pvt_data_ind + 1) % INDEX_WINDOW_SIZE;
+
+       /* update the pivot */
+       heart_battery_update_pivot();
+       /* save pivot info into file */
+       heart_battery_save_pivot_info();
+}
+
+/*
+ * This function will calculate the battery charging remaining time
+ */
+static void heart_battery_cal_charging_rem_time(void)
+{
+       long curr_wall_time = 0;
+       int rem_time;
+       int time_diff;
+       int time_diff_avg;
+       double temp_cv;
+
+       if (batt_stat.last_capacity_chg == batt_stat.curr_capacity) {
+               _I("Last capacity %d is same as current capacity %d\n",
+                       batt_stat.last_capacity_chg, batt_stat.curr_capacity);
+               return;
+       }
+
+       curr_wall_time = heart_battery_logging_get_time_sec_new();
+
+       time_diff = heart_battery_get_time_diff(curr_wall_time);
+
+       /*
+        * just after inserting the charger, if time diff between two level
+        * is less than MIN_TIME_FOR_LVL_CHANGE value then consider time diff
+        * as BATTERY_C_RATE so that there will not be sudden fall in charge
+        * remaining time
+        */
+       if (time_diff < MIN_TIME_FOR_LVL_CHANGE && first_level_change == TRUE) {
+               /*
+                * first_level_change will be set to TRUE in function
+                * heart_battery_charger_status() and set to FALSE in function
+                * heart_battery_capacity_status()
+                */
+               _I("time diff %d is less than min value of lvl change %d\n",
+                       time_diff, MIN_TIME_FOR_LVL_CHANGE);
+               time_diff = BATTERY_C_RATE;
+       }
+
+       _I("data_avail_chg = %d, index_chg = %d\n",
+               data_avail_chg, batt_stat.index_chg);
+       _I("last_wall_time_chg = %ld, curr_wall_time = %ld\n",
+               batt_stat.last_wall_time_chg, curr_wall_time);
+       _I("time diff before averaging = %d seconds\n", time_diff);
+
+       /*
+        * get the average of all time diff values stored including current
+        */
+       time_diff_avg = heart_battery_get_time_diff_avg(time_diff);
+
+       if (time_diff_avg > BATTERY_C_RATE && batt_stat.curr_capacity <= 30)
+               time_diff_avg = BATTERY_C_RATE;
+
+       if (batt_stat.curr_capacity == FULL_CAPACITY) {
+               batt_stat.remaining_time_chg = 0;
+       } else {
+               /*
+                * calculate the remaining charge time based on constant current
+                * and constant votlage(CCCV) logic. 'time_diff_avg' is for CC and
+                * 'temp_cv' is for CV part.
+                */
+               temp_cv = ((double)time_diff_avg)/((double)BATTERY_C_RATE);
+               temp_cv = temp_cv * temp_cv;
+               rem_time = (time_diff_avg + temp_cv)*(FULL_CAPACITY - batt_stat.curr_capacity);
+               batt_stat.remaining_time_chg = SEC_TO_MIN(rem_time);
+       }
+
+       batt_stat.last_wall_time_chg = curr_wall_time;
+       batt_stat.last_wall_time_chg_diff[batt_stat.index_chg] = time_diff;
+       batt_stat.index_chg = (batt_stat.index_chg+1)%BATTERY_LEVEL_GAP;
+       batt_stat.last_capacity_chg = batt_stat.curr_capacity;
+       batt_stat.last_clock_tick =  logging_get_time(CLOCK_BOOTTIME);
+
+       _I("Capacity = %d, charging remaining time = %d minutes\n",
+               batt_stat.curr_capacity, batt_stat.remaining_time_chg);
+
+       if (batt_stat.index_chg+1 == BATTERY_LEVEL_GAP)
+               data_avail_chg = true;
+}
+
+/*
+ * This function will calculate the battery estimation time for every battery
+ * level change
+ */
+static void heart_battery_cal_discharge_rem_time(void)
+{
+       double curr_volt_intg = 0;
+       double volt_intg_diff = 0;
+       double ps, pt;
+       double batt_pwr;
+       int rem_time = 0;
+       int index = 0;
+       int temp_index = 0;
+       int index_count;
+       int i;
+       int update_time;
+       long curr_wall_time = 0;
+       long time_diff1, time_diff2;
+
+       _I("last capacity = %d, current capacity = %d\n", batt_stat.last_capacity, batt_stat.curr_capacity);
+
+       /* if battery level change happen then only calculate the new time*/
+       if (batt_stat.last_capacity != batt_stat.curr_capacity) {
+               /* calculate the voltage integral(energy) for current capacity */
+               for (i = 0; i < ocv_degree; i++)
+                       curr_volt_intg += (intg[i] /(i+1)) * pow(batt_stat.curr_capacity , i+1);
+               curr_volt_intg = curr_volt_intg /100000.0;
+
+               /*current time*/
+               curr_wall_time = heart_battery_logging_get_time_sec_new();
+
+               _I("curr_volt_intg = %lf, curr_wall_time = %ld\n", curr_volt_intg, curr_wall_time);
+
+               if (batt_stat.last_capacity < batt_stat.curr_capacity) {
+                       /*
+                        *this indicates that device was put for charging so need to reject
+                        *all the previous data except 'batt_stat.data_available' and
+                        *'batt_stat.last_pwr_bchg'. Use last available battery power
+                        *before connecting the charger as current average power.
+                        */
+                       batt_pwr = batt_stat.last_pwr_bchg;
+                       heart_battery_reject_data();
+               } else {
+                       index = BATTERY_WINDOW_INDEX(batt_stat.curr_index - BATTERY_LEVEL_GAP);
+                       if (batt_stat.last_wall_time[index] == 0 &&
+                               batt_stat.last_volt_intg[index] == 0) {
+                               /*
+                                *do not have enough previous data so take 1st stored data
+                                *as reference
+                                */
+                               time_diff1 = curr_wall_time - batt_stat.last_wall_time[0];
+                               volt_intg_diff = batt_stat.last_volt_intg[0] - curr_volt_intg;
+                               if (volt_intg_diff < DOUBLE_ZERO)
+                                       volt_intg_diff = volt_intg_full - curr_volt_intg;
+                       } else {
+                               /* time differenc since last battery level change*/
+                               time_diff1 = curr_wall_time - batt_stat.last_wall_time[index];
+                               /* voltage integral(energy) change since last battery level change */
+                               volt_intg_diff = batt_stat.last_volt_intg[index] - curr_volt_intg;
+                       }
+                       _I("time_diff1 = %ld, volt_intg_diff = %lf\n", time_diff1, volt_intg_diff);
+
+                       time_diff1 = SEC_TO_MIN(time_diff1); /*convert second to minute */
+
+                       /* calculate short term average power component*/
+                       if (time_diff1 != 0)
+                               ps = (total_battery_capacity *volt_intg_diff) / time_diff1;
+                       else
+                               ps = 0;
+
+                       _I("ps = %lf\n", ps);
+
+                       /* find the voltage integral(energy) of 1 hr back battery level.
+                       1. Place the index at proper location
+                       2. get the time stored at that index
+                       3. if difference between last time and current time is >= 60 then take that voltage integral
+                       */
+                       index_count = INDEX_WINDOW_SIZE;
+                       time_diff2 = 0;
+                       temp_index = BATTERY_WINDOW_INDEX(batt_stat.curr_index - 1);
+                       while ((index_count > 0) && (time_diff2 < 60)) {
+                               if  (batt_stat.last_wall_time[temp_index] == 0)
+                                       /* data not available so break the loop */
+                                       break;
+
+                               time_diff2 = SEC_TO_MIN(curr_wall_time - batt_stat.last_wall_time[temp_index]);
+                               temp_index = BATTERY_WINDOW_INDEX(temp_index - 1);
+                               index_count--;
+                       }
+
+                       /* calculate long term average power component*/
+                       if (time_diff2 < 60) {
+                               pt = 0;
+                       } else {
+                               temp_index = BATTERY_WINDOW_INDEX(temp_index + 1);
+                               volt_intg_diff = batt_stat.last_volt_intg[temp_index] - curr_volt_intg ;
+                               if (volt_intg_diff < DOUBLE_ZERO)
+                                       pt = 0;
+                               else
+                                       pt = (total_battery_capacity  * volt_intg_diff) / time_diff2;
+                       }
+
+                       _I("time_diff2 = %ld, volt_intg_diff = %lf, pt = %lf\n", time_diff2, volt_intg_diff, pt);
+
+                       /* calculate the average power from the short component and long component*/
+                       if ((pt + ps) != 0)
+                               batt_pwr = (((pt  * pt) + (ps * ps)) / (pt + ps));
+                       else
+                               batt_pwr = batt_stat.last_pwr_bchg;
+               }
+
+               /* total remaining time based on current battery level*/
+               rem_time = (total_battery_capacity * curr_volt_intg) / batt_pwr;
+
+               _I("pivot_nor = %lf, curr_volt_intg = %lf , volt_intg_full %lf, batt_pwr = %lf", pivot_nor, curr_volt_intg, volt_intg_full, batt_pwr);
+
+               /* calculate remaining time for normal mode */
+               update_time = (pivot_nor * curr_volt_intg) / volt_intg_full;
+               batt_stat.remaining_time = (LONG_TIME_WEIGHT * update_time + SHORT_TIME_WEIGHT * CAL_MIN(update_time, rem_time));
+
+                /* calculate remaining time for UPS mode */
+               update_time = (pivot_ups * curr_volt_intg) / volt_intg_full;
+               batt_stat.remaining_time_ups = (LONG_TIME_WEIGHT * update_time + SHORT_TIME_WEIGHT * CAL_MIN(update_time, rem_time));
+
+               _I("normal mode remaining time = %d minutes, ups remaining time = %d minutes\n",
+                       batt_stat.remaining_time, batt_stat.remaining_time_ups);
+
+               batt_stat.last_volt_intg[batt_stat.curr_index] = curr_volt_intg;
+               batt_stat.last_wall_time[batt_stat.curr_index] = curr_wall_time;
+               batt_stat.last_capacity = batt_stat.curr_capacity;
+               batt_stat.curr_index = (batt_stat.curr_index + 1) % INDEX_WINDOW_SIZE;
+               batt_stat.last_clock_tick =  logging_get_time(CLOCK_BOOTTIME);
+
+               if (batt_pwr > DOUBLE_ZERO) {
+                       /*
+                        *when battery percentage is 0 then available power will be 0 so
+                        *do not store this value. keep previous value only.
+                        */
+                       batt_stat.last_pwr_bchg = batt_pwr;
+               }
+
+               if (batt_stat.curr_index > BATTERY_LEVEL_GAP) {
+                       /*
+                        *When enough data to estimate the available battery time are
+                        *stored, no need to update the status of batt_stat. data_available
+                        *untill we are flashing new binary.
+                        */
+                       batt_stat.data_available = TRUE;
+               }
+
+               /* save all calculated battery data to file*/
+               heart_battery_write_data_to_file();
+       }
+}
+
+void heart_battery_update(struct logging_table_form *data, void *user_data)
+{
+       heart_battery_save_to_file(false);
+}
+
+static int heart_battery_get_level_usage_index(int capacity)
+{
+       return (capacity > 49) ? BATTERY_LEVEL_HIGH :
+               (capacity < 16) ? BATTERY_LEVEL_LOW : BATTERY_LEVEL_MID;
+}
+
+static int heart_battery_get_week_day_usage_index(time_t timestamp)
+{
+       int i;
+
+       for (i = 0; i < BATTERY_HISTORY_DAY_MAX; i++) {
+               if (!heart_battery_get_usage_week_stime(i))
+                       return i;
+               else if (abs(timestamp - heart_battery_get_usage_week_stime(i)) < DAY_TO_SEC(1))
+                       return i;
+       }
+       for (i = 0; i < BATTERY_HISTORY_DAY_MAX - 1; i++) {
+               batt_stat.week_day_usage[i].start_time =
+                       batt_stat.week_day_usage[i + 1].start_time;
+               batt_stat.week_day_usage[i].sec_per_cap[DISCHARGING] =
+                       batt_stat.week_day_usage[i + 1].sec_per_cap[DISCHARGING];
+               batt_stat.week_day_usage[i].sec_per_cap[CHARGING] =
+                       batt_stat.week_day_usage[i + 1].sec_per_cap[CHARGING];
+               batt_stat.week_day_usage[i].cap_counter[DISCHARGING] =
+                       batt_stat.week_day_usage[i + 1].cap_counter[DISCHARGING];
+               batt_stat.week_day_usage[i].cap_counter[CHARGING] =
+                       batt_stat.week_day_usage[i + 1].cap_counter[CHARGING];
+       }
+       return BATTERY_HISTORY_DAY_MAX - 1;
+}
+
+static int heart_battery_get_batt_reset_usage_index(void)
+{
+       int i;
+
+       for (i = 0; i < BATTERY_HISTORY_RESET_MAX; i++) {
+               if (heart_battery_get_usage_reset_count(i, DISCHARGING) < BATTERY_HISTORY_COUNT_MAX
+                       && heart_battery_get_usage_reset_count(i, CHARGING) < BATTERY_HISTORY_COUNT_MAX)
+                       return i;
+       }
+       for (i = 0; i < BATTERY_HISTORY_RESET_MAX - 1; i++) {
+               batt_stat.batt_reset_usage[i].start_time =
+                       batt_stat.batt_reset_usage[i + 1].start_time;
+               batt_stat.batt_reset_usage[i].sec_per_cap[DISCHARGING] =
+                       batt_stat.batt_reset_usage[i + 1].sec_per_cap[DISCHARGING];
+               batt_stat.batt_reset_usage[i].sec_per_cap[CHARGING] =
+                       batt_stat.batt_reset_usage[i + 1].sec_per_cap[CHARGING];
+               batt_stat.batt_reset_usage[i].cap_counter[DISCHARGING] =
+                       batt_stat.batt_reset_usage[i + 1].cap_counter[DISCHARGING];
+               batt_stat.batt_reset_usage[i].cap_counter[CHARGING] =
+                       batt_stat.batt_reset_usage[i + 1].cap_counter[CHARGING];
+       }
+       return BATTERY_HISTORY_RESET_CURRENT;
+}
+
+static int heart_battery_reset(void *data)
+{
+       int idx;
+       long total_time, total_count, sec_per_cap;
+
+       idx = heart_battery_get_batt_reset_usage_index();
+
+       /* DISCHARGING */
+       total_time = 0; total_count = 0;
+       total_time = heart_battery_get_usage_reset_total_time(idx, DISCHARGING) + batt_stat.curr_run_time_sec[DISCHARGING];
+       total_count = heart_battery_get_usage_reset_count(idx, DISCHARGING) + batt_stat.curr_cap_counter[DISCHARGING];
+
+       if (total_time && total_count) {
+               sec_per_cap = total_time / total_count;
+               if (sec_per_cap < default_sec_per_cap[DISCHARGING][DEFAULT_MIN])
+                       sec_per_cap = default_sec_per_cap[DISCHARGING][DEFAULT_MIN];
+               else if (sec_per_cap > default_sec_per_cap[DISCHARGING][DEFAULT_MAX])
+                       sec_per_cap = default_sec_per_cap[DISCHARGING][DEFAULT_MAX];
+               heart_battery_set_usage_reset(idx, DISCHARGING, sec_per_cap, total_count);
+       }
+       /* CHARGING */
+       total_time = 0; total_count = 0;
+       total_time = heart_battery_get_usage_reset_total_time(idx, CHARGING)
+               + batt_stat.curr_run_time_sec[CHARGING];
+       total_count = heart_battery_get_usage_reset_count(idx, CHARGING) + batt_stat.curr_cap_counter[CHARGING];
+
+       if (total_time && total_count) {
+               sec_per_cap = total_time / total_count;
+               if (sec_per_cap < default_sec_per_cap[CHARGING][DEFAULT_MIN])
+                       sec_per_cap = default_sec_per_cap[CHARGING][DEFAULT_MIN];
+               else if (sec_per_cap > default_sec_per_cap[CHARGING][DEFAULT_MAX])
+                       sec_per_cap = default_sec_per_cap[CHARGING][DEFAULT_MAX];
+               heart_battery_set_usage_reset(idx, CHARGING, sec_per_cap, total_count);
+       }
+
+       batt_stat.reset_mark = batt_stat.reset_mark ? 0 : 1; /* Swap reset_mark */
+       batt_stat.reset_mark_timestamp = time(NULL);
+       batt_stat.curr_run_time_sec[DISCHARGING] = 0;
+       batt_stat.curr_run_time_sec[CHARGING] = 0;
+       batt_stat.curr_cap_counter[DISCHARGING] = 0;
+       batt_stat.curr_cap_counter[CHARGING] = 0;
+       batt_used.used_time_sec = 0;
+       batt_used.last_update_time = logging_get_time(CLOCK_BOOTTIME);
+
+       return RESOURCED_ERROR_NONE;
+}
+
+static long heart_battery_compute_remaining_time_in_min(int capacity_count, long sec_per_cap)
+{
+       /*
+        * Calculates and returns remaining time in minutes based on number
+        * of capacity changes and time needed for one change.
+        */
+       long time;
+
+       time = (capacity_count * sec_per_cap); /* seconds */
+       time = time + 30; /* add 30s margin */
+       time = time / 60; /* change to minutes */
+       return time;
+}
+
+static void heart_battery_calculate_prediction(enum charger_status_type goal)
+{
+       int i, capacity, level;
+       long total_time, total_count, sec_per_cap, pred_min;
+       long low_count, mid_count, high_count;
+       struct heart_battery_capacity *lbc = NULL;
+       GArray *arrays = NULL;
+
+       if (goal == CHARGING)
+               capacity = REMAIN_CAPACITY(batt_stat.curr_capacity);
+       else {
+               capacity = batt_stat.curr_capacity;
+
+               if (goal != DISCHARGING) {
+                       _E("Wrong charging status is written. Suppose discharging");
+                       goal = DISCHARGING;
+               }
+       }
+
+       /* PREDICTION METHOD: total average */
+       total_time = 0;
+       total_count = 0;
+       for (i = 0; i < BATTERY_HISTORY_RESET_MAX; i++) {
+               total_time += heart_battery_get_usage_reset_total_time(i, goal);
+               total_count += heart_battery_get_usage_reset_count(i, goal);
+       }
+       total_time += batt_stat.curr_run_time_sec[goal];
+       total_count += batt_stat.curr_cap_counter[goal];
+
+       if (total_time && total_count >= BATTERY_PREDICTION_DATA_MIN) {
+               sec_per_cap = total_time / total_count;
+               if (sec_per_cap < default_sec_per_cap[goal][DEFAULT_MIN])
+                       sec_per_cap = default_sec_per_cap[goal][DEFAULT_MIN];
+               else if (sec_per_cap > default_sec_per_cap[goal][DEFAULT_MAX])
+                       sec_per_cap = default_sec_per_cap[goal][DEFAULT_MAX];
+               pred_min = heart_battery_compute_remaining_time_in_min(capacity, sec_per_cap);
+               heart_battery_set_prediction(TA, goal,
+                               sec_per_cap, total_count,
+                               pred_min);
+       } else {
+               heart_battery_set_prediction(TA, goal, 0, 0, 0);
+       }
+
+
+       /* PREDICTION METHOD:
+        * Prediction of battery remaining usage time
+        * considering users' psychological usage patterns
+        * by batt_lvl_usage of battery charge
+        * */
+       pred_min = 0;
+       sec_per_cap = 0;
+       level = heart_battery_get_level_usage_index(capacity);
+       low_count = heart_battery_get_usage_level_count(BATTERY_LEVEL_LOW, goal);
+       mid_count = heart_battery_get_usage_level_count(BATTERY_LEVEL_MID, goal);
+       high_count = heart_battery_get_usage_level_count(BATTERY_LEVEL_HIGH, goal);
+
+       if (level == BATTERY_LEVEL_LOW && low_count) {
+               sec_per_cap = heart_battery_get_usage_level_spc(BATTERY_LEVEL_LOW, goal);
+               pred_min = heart_battery_compute_remaining_time_in_min(capacity, sec_per_cap);
+       } else if (level == BATTERY_LEVEL_MID && low_count && mid_count) {
+               sec_per_cap = heart_battery_get_usage_level_spc(BATTERY_LEVEL_LOW, goal);
+               pred_min = heart_battery_compute_remaining_time_in_min(15, sec_per_cap);
+               sec_per_cap = heart_battery_get_usage_level_spc(BATTERY_LEVEL_MID, goal);
+               pred_min +=
+               heart_battery_compute_remaining_time_in_min(capacity - 15, sec_per_cap);
+       } else if (level == BATTERY_LEVEL_HIGH && low_count && mid_count && high_count) {
+               sec_per_cap = heart_battery_get_usage_level_spc(BATTERY_LEVEL_LOW, goal);
+               pred_min = heart_battery_compute_remaining_time_in_min(15, sec_per_cap);
+               sec_per_cap = heart_battery_get_usage_level_spc(BATTERY_LEVEL_MID, goal);
+               pred_min +=
+                       heart_battery_compute_remaining_time_in_min(35, sec_per_cap);
+               sec_per_cap = heart_battery_get_usage_level_spc(BATTERY_LEVEL_HIGH, goal);
+               pred_min +=
+                       heart_battery_compute_remaining_time_in_min(capacity - 50, sec_per_cap);
+       }
+       heart_battery_set_prediction(PCB, goal, 0, 0, pred_min);
+
+
+       /* PREDICTION METHOD: week average */
+       total_time = 0;
+       total_count = 0;
+       for (i = 0; i < BATTERY_HISTORY_DAY_MAX; i++) {
+               total_time += heart_battery_get_usage_week_total_time(i, goal);
+               total_count += heart_battery_get_usage_week_count(i, goal);
+       }
+       if (total_time && total_count >= BATTERY_PREDICTION_DATA_MIN) {
+               sec_per_cap = total_time / total_count;
+               if (sec_per_cap < default_sec_per_cap[goal][DEFAULT_MIN])
+                       sec_per_cap = default_sec_per_cap[goal][DEFAULT_MIN];
+               else if (sec_per_cap > default_sec_per_cap[goal][DEFAULT_MAX])
+                       sec_per_cap = default_sec_per_cap[goal][DEFAULT_MAX];
+               pred_min =
+                       heart_battery_compute_remaining_time_in_min(capacity, sec_per_cap);
+               heart_battery_set_prediction(WEEK, goal, sec_per_cap, total_count, pred_min);
+       } else
+               heart_battery_set_prediction(WEEK, goal, 0, 0, 0);
+
+
+       /* PREDICTION METHOD:  last BATTERY_PREDICTION_COUNT data average */
+       arrays = g_array_new(FALSE, FALSE, sizeof(struct heart_battery_capacity *));
+       if (!arrays) {
+               _E("Failed to alloc array");
+               return;
+       }
+       if (heart_battery_get_capacity_history_latest(arrays, goal, BATTERY_PREDICTION_LATEST_COUNT)
+                       != RESOURCED_ERROR_NONE) {
+               _E("Failed to get battery capacity history");
+               g_array_free(arrays, TRUE);
+               arrays = NULL;
+               return;
+       }
+       total_time = 0;
+       total_count = 0;
+       for (i = 0; i < arrays->len; i++) {
+               lbc = g_array_index(arrays, struct heart_battery_capacity *, i);
+               if (!lbc)
+                       break;
+               total_count += lbc->diff_capacity;
+               if (goal == CHARGING)
+                       total_time += lbc->charging_time;
+               else
+                       total_time += lbc->used_time;
+               free(lbc);
+       }
+       if (total_time && total_count >= BATTERY_PREDICTION_DATA_MIN) {
+               sec_per_cap = total_time / total_count;
+               if (sec_per_cap < default_sec_per_cap[goal][DEFAULT_MIN])
+                       sec_per_cap = default_sec_per_cap[goal][DEFAULT_MIN];
+               else if (sec_per_cap > default_sec_per_cap[goal][DEFAULT_MAX])
+                       sec_per_cap = default_sec_per_cap[goal][DEFAULT_MAX];
+
+               pred_min =
+                       heart_battery_compute_remaining_time_in_min(capacity, sec_per_cap);
+               heart_battery_set_prediction(COUNT, goal, sec_per_cap, total_count, pred_min);
+               /* check current discharge rate */
+               if (sec_per_cap && goal == DISCHARGING) {
+                       batt_stat.discharge_rate_level =
+                               heart_battery_calculate_discharge_rate_level(sec_per_cap);
+                       _I("discharge rate level : %d", batt_stat.discharge_rate_level);
+               }
+       } else
+               heart_battery_set_prediction(COUNT, goal, 0, 0, 0);
+       g_array_free(arrays, TRUE);
+       arrays = NULL;
+
+
+       /* PREDICTION METHOD: last BATTERY_PREDICTION_PERIOD hours average */
+       arrays = g_array_new(FALSE, FALSE, sizeof(struct heart_battery_capacity *));
+       if (!arrays) {
+               _E("Failed to alloc array");
+               return;
+       }
+       if (heart_battery_get_capacity_history(arrays, BATTERY_PREDICTION_PERIOD) != RESOURCED_ERROR_NONE) {
+               _E("Failed to get battery capacity history");
+               g_array_free(arrays, TRUE);
+               arrays =  NULL;
+               return;
+       }
+       total_time = 0;
+       total_count = 0;
+       for (i = 0; i < arrays->len; i++) {
+               lbc = g_array_index(arrays, struct heart_battery_capacity *, i);
+               if (!lbc)
+                       break;
+               if (goal == CHARGING) {
+                       if (lbc->charger_status != CHARGING) {
+                               free(lbc);
+                               continue;
+                       }
+                       total_time += lbc->charging_time;
+                       total_count += lbc->diff_capacity;
+               } else {
+                       if (lbc->charger_status != DISCHARGING) {
+                               free(lbc);
+                               continue;
+                       }
+                       total_time += lbc->used_time;
+                       total_count += lbc->diff_capacity;
+               }
+               free(lbc);
+       }
+       g_array_free(arrays, TRUE);
+       arrays = NULL;
+       if (total_time && total_count >= BATTERY_PREDICTION_DATA_MIN) {
+               sec_per_cap = total_time / total_count;
+               if (sec_per_cap < default_sec_per_cap[goal][DEFAULT_MIN])
+                       sec_per_cap = default_sec_per_cap[goal][DEFAULT_MIN];
+               else if (sec_per_cap > default_sec_per_cap[goal][DEFAULT_MAX])
+                       sec_per_cap = default_sec_per_cap[goal][DEFAULT_MAX];
+               pred_min =
+                       heart_battery_compute_remaining_time_in_min(capacity, sec_per_cap);
+               heart_battery_set_prediction(PERIOD, goal, sec_per_cap, total_count, pred_min);
+
+       } else
+               heart_battery_set_prediction(PERIOD, goal, 0, 0, 0);
+
+       /* Log values of all predictions calculated */
+       for (i = 0; i < MAX_STRATEGY; i++) {
+               _I("%s %d %ld %ld %ld",
+                               (goal == DISCHARGING) ? "TimeToEmpty:" : "TimeToFull:",
+                               batt_stat.curr_capacity,
+                               batt_stat.prediction[goal].sec_per_cap[i],
+                               batt_stat.prediction[goal].cap_counter[i],
+                               batt_stat.prediction[goal].time_pred_min[i]);
+       }
+}
+
+static int heart_battery_add_capacity(int capacity)
+{
+       char info[BATTERY_DATA_MAX];
+       int ret, idx, status;
+       long time_diff_capacity_lvl[MAX_CHARGER_STATE];
+       int diff_capacity_lvl;
+       long total_time, total_count, sec_per_cap;
+       time_t timestamp = time(NULL);
+       time_t curr_wall_time = logging_get_time(CLOCK_BOOTTIME);
+
+       status = batt_stat.curr_charger_status;
+       /* calculate diff */
+       time_diff_capacity_lvl[status] = curr_wall_time - batt_stat.last_event_wall_time;
+
+       if (time_diff_capacity_lvl[status] < 0) {
+               batt_stat.last_event_wall_time = curr_wall_time;
+               return 0;
+       }
+
+       time_diff_capacity_lvl[!status] = 0;
+
+       if (!batt_stat.curr_capacity)
+               diff_capacity_lvl = 1;
+       else
+               diff_capacity_lvl = abs(batt_stat.curr_capacity - capacity);
+
+       _I("%d -> %d %ld %ld", batt_stat.curr_capacity, capacity,
+                       timestamp, time_diff_capacity_lvl[status]);
+
+       /* update battery current status */
+       batt_stat.last_event_wall_time = curr_wall_time;
+       batt_stat.curr_capacity = capacity;
+
+       /* Full Charging status */
+       if (status == CHARGING && !REMAIN_CAPACITY(capacity) && !diff_capacity_lvl)
+               return 0;
+
+       /* update run usage */
+       batt_stat.curr_run_time_sec[status] += time_diff_capacity_lvl[status];
+       batt_stat.curr_cap_counter[status] += diff_capacity_lvl;
+
+       /* update batt_lvl_usage usage */
+       total_time = 0;
+       total_count = 0;
+
+       if (status == CHARGING)
+               idx = heart_battery_get_level_usage_index(REMAIN_CAPACITY(capacity));
+       else
+               idx = heart_battery_get_level_usage_index(capacity);
+
+       total_time = heart_battery_get_usage_level_total_time(idx, status) + time_diff_capacity_lvl[status];
+       if (total_time)
+               total_count = heart_battery_get_usage_level_count(idx, status) + diff_capacity_lvl;
+
+       if (total_count) {
+               sec_per_cap = total_time / total_count;
+               if (sec_per_cap == 0)
+                       sec_per_cap = default_sec_per_cap[status][DEFAULT_AVG];
+               else if (sec_per_cap < default_sec_per_cap[status][DEFAULT_MIN])
+                       sec_per_cap = default_sec_per_cap[status][DEFAULT_MIN];
+               else if (sec_per_cap > default_sec_per_cap[status][DEFAULT_MAX])
+                       sec_per_cap = default_sec_per_cap[status][DEFAULT_MAX];
+               /*
+                * If counts reached MAXIMUM number,
+                * counts is divided by 2 to reduce previous data's effect to equation
+                */
+               if (total_count >= BATTERY_HISTORY_COUNT_MAX)
+                       total_count = total_count >> 1;
+
+               heart_battery_set_usage_level(idx, status, sec_per_cap, total_count);
+               heart_battery_set_usage_level_stime(idx, timestamp);
+       }
+
+       /* update day usage */
+       total_time = 0;
+       total_count = 0;
+
+       idx = heart_battery_get_week_day_usage_index(timestamp);
+       total_time = heart_battery_get_usage_week_total_time(idx, status) + time_diff_capacity_lvl[status];
+       if (total_time)
+               total_count = heart_battery_get_usage_week_count(idx, status) + diff_capacity_lvl;
+
+       if (total_count) {
+               sec_per_cap = total_time / total_count;
+               if (sec_per_cap == 0)
+                       sec_per_cap = default_sec_per_cap[status][DEFAULT_AVG];
+               else if (sec_per_cap < default_sec_per_cap[status][DEFAULT_MIN])
+                       sec_per_cap = default_sec_per_cap[status][DEFAULT_MIN];
+               else if (sec_per_cap > default_sec_per_cap[status][DEFAULT_MAX])
+                       sec_per_cap = default_sec_per_cap[status][DEFAULT_MAX];
+               heart_battery_set_usage_week(idx, status, sec_per_cap, total_count);
+               heart_battery_set_usage_week_stime(idx, CALCULATE_DAY_BASE_TIME(timestamp));
+       }
+
+       heart_battery_calculate_prediction(batt_stat.curr_charger_status);
+
+       /* db backup */
+       snprintf(info, sizeof(info), "%d %d %ld %ld %d %d ",
+                       capacity, diff_capacity_lvl,
+                       time_diff_capacity_lvl[DISCHARGING], time_diff_capacity_lvl[CHARGING],
+                       batt_stat.curr_charger_status, batt_stat.reset_mark);
+       ret = logging_write(PID_FOR_ROOT, BATTERY_NAME, TIZEN_SYSTEM_BATTERY_APPID,
+                       TIZEN_SYSTEM_APPID, timestamp, info);
+       if (ret != RESOURCED_ERROR_NONE)
+               return ret;
+
+       /* insert capacity history list */
+       heart_battery_insert_capacity(&capacity_history_list, capacity, diff_capacity_lvl,
+                       timestamp, time_diff_capacity_lvl[DISCHARGING],
+                       time_diff_capacity_lvl[CHARGING], batt_stat.curr_charger_status,
+                       batt_stat.reset_mark, true);
+
+       _D("battery_heart_capacity_write %d diff_capacity %d, used time %ld, charging time %ld, charger status %d, reset_mark %d",
+                       capacity, diff_capacity_lvl,
+                       time_diff_capacity_lvl[DISCHARGING], time_diff_capacity_lvl[CHARGING],
+                       batt_stat.curr_charger_status, batt_stat.reset_mark);
+
+       resourced_notify(RESOURCED_NOTIFIER_LOGGING_START, NULL);
+       return RESOURCED_ERROR_NONE;
+}
+
+static void rul_display_state_changed_cb(device_callback_e type, void *value, void *user_data)
+{
+       int display_state = (int) ((intptr_t) value), charger_status;
+       /* 0 : on, 1 : dim, 2: off */
+
+       /*
+        * If charger_status==CHARGING and raw capacity calculation ongoing,
+        * then, handle display_on time for RUL
+        */
+
+       charger_status = heart_battery_get_charger_status();
+       if ((charger_status == CHARGING) && (rul.charging_start_time != 0)) {
+               if (type != DEVICE_CALLBACK_DISPLAY_STATE)
+                       return;
+
+               if (display_state == DISPLAY_STATE_NORMAL) {
+                       _I("DISPLAY: NORMAL/DIM");
+                       rul.lcd_data.state = DISPLAY_STATE_NORMAL;
+                       if (rul.lcd_data.on_start_time == 0) {
+                               rul.lcd_data.on_start_time = logging_get_time(CLOCK_BOOTTIME);
+                       }
+               } else if (display_state == DISPLAY_STATE_SCREEN_OFF) {
+                       _I("DISPLAY: OFF");
+                       rul.lcd_data.state = DISPLAY_STATE_SCREEN_OFF;
+                       if (rul.lcd_data.on_start_time > 0) {
+                               rul.lcd_data.on_stop_time = logging_get_time(CLOCK_BOOTTIME);
+                               rul.lcd_data.on_time += rul.lcd_data.on_stop_time - rul.lcd_data.on_start_time;
+                               rul.lcd_data.on_start_time = 0;
+                               rul.lcd_data.on_stop_time = 0;
+                       }
+               }
+       }
+}
+
+static void rul_write_data_to_file(void)
+{
+       int len = 0;
+       char buff[RUL_DATA_SIZE] = {0};
+       _cleanup_fclose_ FILE *fp = NULL, *fp1 = NULL;
+       float fullcapnom = 0, fullcapnom_mAh = 0;
+
+       /* Update count of Charging cycles*/
+       rul.charging_cycles += 1;
+
+       /* Calculate normalized capacity, i.e., extrapolate for 0% to 100% */
+       fullcapnom = rul.raw_capacity / ((rul.soc_stop/100.0f) - (rul.soc_start/100.0f));
+       fullcapnom_mAh = fullcapnom / 3.6f;
+       _I("rul : raw_capacity = %.4f As, fullcapnom = %.4f As = %.4f mAh", rul.raw_capacity, fullcapnom, fullcapnom_mAh);
+
+       /* Update RUL data file */
+       fp = fopen(RUL_DATA_FILE, "a");
+       if (fp == NULL) {
+               _E("Could not open file - RUL_DATA_FILE");
+               return;
+       }
+
+       len = snprintf(buff, RUL_DATA_SIZE, "%d %.4f\n", rul.charging_cycles, fullcapnom_mAh);
+
+       if (len < RUL_DATA_SIZE)
+               fputs(buff, fp);
+
+       /* Write Charging cycles count to file */
+       fp1 = fopen(RUL_CHARGING_CYCLES_FILE, "w");
+       if (fp1 == NULL) {
+               _E("Could not open file for write - RUL_CHARGING_CYCLES_FILE");
+               return;
+       }
+       fprintf(fp1, "%d", rul.charging_cycles);
+
+}
+
+static void rul_charging_cycle_end_work(void)
+{
+       int capacity;
+       long total_charging_time;
+       bool lcd_on_time_check;
+       float lcd_on_ratio = 1.0f;
+
+       capacity = heart_battery_get_capacity();
+
+       rul.soc_stop = capacity;
+       rul.charging_stop_time = logging_get_time(CLOCK_BOOTTIME);
+
+       /* If LCD was on before disconnecting charger, update display_on time */
+       if (rul.lcd_data.on_start_time != 0) {
+               rul.lcd_data.on_stop_time = logging_get_time(CLOCK_BOOTTIME);
+               rul.lcd_data.on_time += rul.lcd_data.on_stop_time - rul.lcd_data.on_start_time;
+       }
+
+       /* Max LCD ON Time ratio criteria met ? */
+       total_charging_time = rul.charging_stop_time - rul.charging_start_time;
+       if (total_charging_time != 0)
+               lcd_on_ratio = (rul.lcd_data.on_time / (total_charging_time * 1.0f));
+       lcd_on_time_check = lcd_on_ratio <= RUL_DISPLAY_ON_CUTOFF_RATIO;
+
+       /* write data to file if condititons met*/
+       if ((rul.charging_start_time != 0) && (lcd_on_time_check == true) &&
+           (rul.soc_stop - rul.soc_start >= RUL_MIN_CAPACITY_DIFF))
+               rul_write_data_to_file();
+
+       /* init for next charging cycle */
+       rul.soc_start = 0;
+       rul.soc_stop = 0;
+       rul.charging_start_time = 0;
+       rul.charging_stop_time = 0;
+       rul.lcd_data.on_start_time = 0;
+       rul.lcd_data.on_stop_time = 0;
+       rul.lcd_data.on_time = 0;
+}
+
+static void rul_calculate_raw_capacity(void)
+{
+       /*
+        * This function updates Raw Capacity every 1% SoC change.
+        *
+        * Upon first time 1% SoC change, initialize rul_info variables.
+        *
+        * Subsequently, Update Raw Capacity using time interval and
+        * current_now sys node values.
+        *
+        * If capacity = 100%, dump collected data
+        */
+
+       long rul_curr_time, rul_time_interval;
+       static long prev_charging_time;
+       int fg_curr_inst, capacity, ret;
+       float fg_curr_inst_f;
+       static float prev_fg_curr_inst_f = 0.0f;
+
+       capacity = heart_battery_get_capacity();
+
+       if (rul.charging_start_time == 0) {
+               rul.charging_start_time = logging_get_time(CLOCK_BOOTTIME);
+               rul.soc_start = capacity;
+               rul.raw_capacity = 0.0f;
+               prev_charging_time = rul.charging_start_time;
+               prev_fg_curr_inst_f = 0.0f;
+               rul.lcd_data.on_start_time = 0;
+               rul.lcd_data.on_stop_time = 0;
+               rul.lcd_data.on_time = 0;
+
+               /* Get display status at time of initiating RUL calculations */
+               ret = device_display_get_state(&rul.lcd_data.state);
+               if (ret != DEVICE_ERROR_NONE) {
+                       _E("Failed to get device display state with err = %d", ret);
+                       return;
+               }
+               if ((rul.lcd_data.state == DISPLAY_STATE_NORMAL) || (rul.lcd_data.state == DISPLAY_STATE_SCREEN_DIM))
+                       rul.lcd_data.on_start_time = logging_get_time(CLOCK_BOOTTIME);
+       } else {
+               rul_curr_time = logging_get_time(CLOCK_BOOTTIME);
+               rul_time_interval = rul_curr_time - prev_charging_time;
+               prev_charging_time = rul_curr_time;
+
+               ret = fread_int("/sys/class/power_supply/battery/current_now", &fg_curr_inst);
+               if (ret != RESOURCED_ERROR_NONE) {
+                       _E("This device doesn't support FG CURRENT_NOW information. Disable LOGIC_RUL");
+                       return;
+               }
+
+               fg_curr_inst_f = fg_curr_inst / 1000.0f;
+               rul.raw_capacity += ((fg_curr_inst_f + prev_fg_curr_inst_f) / 2.0f)*rul_time_interval;
+               prev_fg_curr_inst_f = fg_curr_inst_f;
+       }
+
+       if (capacity == 100) {
+               rul_charging_cycle_end_work();
+       }
+}
+
+/* ============================ DBUS -> DEVICED on demand ==================== */
+
+static int heart_battery_direct_get_capacity(void)
+{
+       int capacity;
+
+       capacity = d_bus_call_method_sync_gvariant(DEVICED_BUS_NAME, DEVICED_PATH_BATTERY,
+                       DEVICED_INTERFACE_BATTERY,
+                       GET_BATTERY_CAPACITY,
+                       NULL);
+       if (capacity < 0) {
+               _E("Failed to sync DBUS message.");
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       return capacity;
+}
+
+static enum charger_status_type heart_battery_direct_get_charger_status(void)
+{
+       int status;
+
+       status = d_bus_call_method_sync_gvariant(DEVICED_BUS_NAME, DEVICED_PATH_BATTERY,
+                       DEVICED_INTERFACE_BATTERY,
+                       GET_CHARGER_STATUS,
+                       NULL);
+       if (status < 0) {
+               _E("Failed to sync DBUS message.");
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       if (status > 0)
+               return CHARGING;
+       return DISCHARGING;
+}
+
+/* =========================  DBUS -> DEVICED  on demand END ================= */
+
+/* ============================ DBUS -> DEVICED handler ====================== */
+static void heart_battery_capacity_status(GVariant *params)
+{
+       /*
+        * This handler is called when battery capacity value change in 1%
+        *
+        * The message have current percent value of capacity
+        *
+        * (This requires deviced with commit at least:
+        * "f1ae1d1f270e9 battery: add battery capacity dbus signal broadcast")
+        */
+
+       int capacity = -1;
+       int bat_trigger = -1;
+       int bat_ups_est = -1;
+       int bat_normal_est = -1;
+
+       do_expr_unless_g_variant_get_typechecked(return, params, "(i)", &capacity);
+       if (capacity < 0) {
+               _E("Failed: dbus_message_get_args()");
+               return;
+       }
+       heart_battery_add_capacity(capacity);
+       heart_battery_update_used_time(logging_get_time(CLOCK_BOOTTIME),
+                       batt_stat.curr_charger_status);
+
+       if (logic_v2) {
+               /* get the device mode */
+               if (vconf_get_int(VCONFKEY_HEART_BATTERY_DEVICE_MODE, &device_mode))
+                       _E("failed to get VCONFKEY_HEART_BATTERY_DEVICE_MODE\n");
+
+               /* for every battery level change, calculate the battery estimation time using new logic*/
+               heart_battery_cal_discharge_rem_time();
+
+               if (batt_stat.curr_charger_status == CHARGING &&
+                       batt_stat.last_capacity_chg < batt_stat.curr_capacity) {
+                       heart_battery_cal_charging_rem_time();
+                       first_level_change = FALSE;
+               } else {
+                       /*
+                        * if battery is very very low then update the pivot before power off
+                        */
+                       if (batt_stat.curr_capacity == LOW_CAPACITY)
+                               heart_battery_collect_pivot_info();
+               }
+       }
+       if (logic_rul) {
+               /* Update prev_soc, curr_soc */
+               rul.prev_soc = rul.curr_soc;
+               rul.curr_soc = capacity;
+
+               /*
+                * If charger_status==CHARGING and SOC_INCREASING, start/continue raw capacity calculation.
+                * Else, if raw capacity calculation was ongoing, then dump collected data.
+                */
+               if ((batt_stat.curr_charger_status == CHARGING) && (rul.curr_soc >= rul.prev_soc))
+                       rul_calculate_raw_capacity();
+               else if (rul.charging_start_time != 0)
+                       rul_charging_cycle_end_work();
+       }
+
+       /* Get the UPSM trigger value and remaining estimate */
+       if (vconf_get_int(VCONFKEY_SETAPPL_MANAGE_BATTERY_TRIGGER_TIME, &bat_trigger)) {
+               _E("failed to get VCONFKEY_SETAPPL_MANAGE_BATTERY_TRIGGER_TIME\n");
+               return;
+       }
+       if (bat_trigger > 0) { /* Battery planner is enabled*/
+               bat_ups_est = get_battery_remaining_time(ULTRA_SAVING_MODE, DISCHARGING);
+               bat_normal_est = get_battery_remaining_time(POWER_NORMAL_MODE, DISCHARGING);
+               _I(" trigger time: %d,  ups est:%d, normal est:%d", bat_trigger, bat_ups_est, bat_normal_est);
+               if (bat_ups_est > 0 && bat_trigger >= bat_ups_est) {
+                       char *args[4] = { "_SYSPOPUP_CONTENT_", "manage_battery",
+                                               "_BAT_POPUP_TYPE_", "enable_mbp"};
+
+                       d_bus_call_method_sync(SYSTEM_POPUP_BUS_NAME,
+                                       SYSTEM_POPUP_PATH_SYSTEM, SYSTEM_POPUP_IFACE_SYSTEM,
+                                       "PopupLaunch", "ssss", args);
+               }
+               if (bat_normal_est > 0 && bat_normal_est >= bat_trigger) {
+                       char *args[4] = { "_SYSPOPUP_CONTENT_", "manage_battery",\
+                                               "_BAT_POPUP_TYPE_", "disable_mbp"};
+
+                       d_bus_call_method_sync(SYSTEM_POPUP_BUS_NAME,
+                                       SYSTEM_POPUP_PATH_SYSTEM, SYSTEM_POPUP_IFACE_SYSTEM,
+                                       "PopupLaunch", "ssss", args);
+               }
+       }
+}
+
+static void heart_battery_charger_status(GVariant *params)
+{
+       /*
+        * This handler is called when USB cable with charging capabilities
+        * is connected or disconnected from the device.
+        *
+        * The message have current status of charger connection.
+        * STATUSES:
+        * 0 - charger was disconnected
+        * 1 - charger was connected
+        */
+       int charger_status = -1, cap_history_size;
+
+       do_expr_unless_g_variant_get_typechecked(return, params, "(i)", &charger_status);
+       if (charger_status < 0) {
+               _E("Failed: dbus_message_get_args()");
+               return;
+       }
+
+       /* Update the statistics with capacity when charger state was changed */
+       heart_battery_add_capacity(batt_stat.curr_capacity);
+
+       cap_history_size = heart_battery_get_capacity_history_size();
+
+       if (charger_status == DISCHARGING && batt_stat.curr_capacity >= 90) {
+               /*
+                * If battery is charged over 90 and charger was disconnected.
+                * So most probably the phone was "charged".
+                * Let's reset the statistics.
+                */
+               resourced_notify(RESOURCED_NOTIFIER_DATA_RESET, NULL);
+       } else if (charger_status == DISCHARGING && cap_history_size >= BATTERY_CAPACITY_MAX) {
+               /*
+                * Charger is not connected and the battery history is over limit.
+                * Let's reset the statistics.
+                */
+               resourced_notify(RESOURCED_NOTIFIER_DATA_RESET, NULL);
+       }
+       /* Update current charger connection status */
+       batt_stat.curr_charger_status = charger_status;
+       heart_battery_update_used_time(logging_get_time(CLOCK_BOOTTIME),
+                       batt_stat.curr_charger_status);
+       heart_battery_calculate_prediction(batt_stat.curr_charger_status);
+
+       if (logic_v2) {
+               /*
+                * If charger removed/inserted then update the battery estimation time
+                */
+               heart_battery_cal_discharge_rem_time();
+
+               if (charger_status == CHARGING) {
+                       /*
+                        * if diff is more than 10% then flush the previous charge data
+                        */
+                       if ((batt_stat.last_capacity_chg > 0) &&
+                           (batt_stat.last_capacity_chg - batt_stat.curr_capacity > BATT_CHG_FLUSH_DATA))
+                               heart_battery_flush_charge_data();
+
+                       /* collect the data for pivot update */
+                       heart_battery_collect_pivot_info();
+
+                       batt_stat.last_wall_time_chg = 0;
+                       first_level_change = TRUE;
+                       heart_battery_print_prev_charge_data();
+                       heart_battery_cal_charging_rem_time();
+               } else {
+                       heart_battery_collect_discharge_data();
+               }
+       }
+       if (logic_rul) {
+               /*
+                * If charger disconnected and raw capacity calculation was ongoing,
+                * then dump collected data.
+                */
+               if ((charger_status == DISCHARGING) && (rul.charging_start_time != 0))
+                       rul_charging_cycle_end_work();
+       }
+}
+
+/* =========================  DBUS -> DEVICED handler END ==================== */
+
+int heart_battery_get_capacity_history_latest(GArray *arrays, int charge, int max_size)
+{
+       int ret, size, count;
+       struct heart_battery_capacity *lbc, *lbci;
+       GSList *iter, *rlist;
+
+       if (!capacity_history_list) {
+               _E("empty capacity history list");
+               return RESOURCED_ERROR_FAIL;
+       }
+       size = g_slist_length(capacity_history_list);
+       if (!size) {
+               _I("capacity history is empty");
+               return RESOURCED_ERROR_NONE;
+       }
+       ret = pthread_mutex_lock(&heart_battery_mutex);
+       if (ret) {
+               _E("pthread_mutex_lock() failed, %d", ret);
+               return RESOURCED_ERROR_FAIL;
+       }
+       count = 0;
+
+       rlist = g_slist_copy(capacity_history_list);
+
+       rlist = g_slist_reverse(rlist);
+
+       gslist_for_each_item(iter, rlist) {
+               lbc = (struct heart_battery_capacity *)iter->data;
+               if (!lbc)
+                       break;
+               if (charge < MAX_CHARGER_STATE && charge != lbc->charger_status)
+                       continue;
+               count++;
+               if (max_size < count)
+                       break;
+               lbci = malloc(sizeof(struct heart_battery_capacity));
+               if (!lbci) {
+                       _E("malloc failed");
+                       goto unlock_exit;
+               }
+               lbci->capacity = lbc->capacity;
+               lbci->diff_capacity = lbc->diff_capacity;
+               if (!lbc->diff_capacity)
+                       count--;
+               lbci->used_time = lbc->used_time;
+               lbci->charging_time = lbc->charging_time;
+               lbci->charger_status = lbc->charger_status;
+               g_array_prepend_val(arrays, lbci);
+       }
+unlock_exit:
+       g_slist_free(rlist);
+       ret = pthread_mutex_unlock(&heart_battery_mutex);
+       if (ret) {
+               _E("pthread_mutex_unlock() failed, %d", ret);
+               return RESOURCED_ERROR_FAIL;
+       }
+       return RESOURCED_ERROR_NONE;
+}
+
+int heart_battery_get_capacity_history(GArray *arrays, enum heart_data_period period)
+{
+       int ret, index, size;
+       struct heart_battery_capacity *lbc, *lbci;
+       GSList *iter;
+       time_t curr = time(NULL);
+
+       switch (period) {
+       case DATA_LATEST:
+               index = 0;
+               break;
+       case DATA_3HOUR:
+               index = 3;
+               break;
+       case DATA_6HOUR:
+               index = 6;
+               break;
+       case DATA_12HOUR:
+               index = 12;
+               break;
+       case DATA_1DAY:
+               index = 24;
+               break;
+       default:
+               _E("Wrong message arguments! %d", period);
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       if (!capacity_history_list) {
+               _E("empty capacity history list");
+               return RESOURCED_ERROR_FAIL;
+       }
+       size = g_slist_length(capacity_history_list);
+       if (!size) {
+               _I("capacity history is empty");
+               return RESOURCED_ERROR_NONE;
+       }
+       ret = pthread_mutex_lock(&heart_battery_mutex);
+       if (ret) {
+               _E("pthread_mutex_lock() failed, %d", ret);
+               return RESOURCED_ERROR_FAIL;
+       }
+       gslist_for_each_item(iter, capacity_history_list) {
+               lbc = (struct heart_battery_capacity *)iter->data;
+               if (!lbc)
+                       break;
+               if (index && (lbc->timestamp < curr - (index * 3600)))
+                       continue;
+               lbci = malloc(sizeof(struct heart_battery_capacity));
+               if (!lbci) {
+                       _E("malloc failed");
+                       ret = pthread_mutex_unlock(&heart_battery_mutex);
+                       if (ret) {
+                               _E("pthread_mutex_unlock() failed, %d", ret);
+                               return RESOURCED_ERROR_FAIL;
+                       }
+                       return RESOURCED_ERROR_OUT_OF_MEMORY;
+               }
+               lbci->capacity = lbc->capacity;
+               lbci->diff_capacity = lbc->diff_capacity;
+               lbci->used_time = lbc->used_time;
+               lbci->charging_time = lbc->charging_time;
+               lbci->charger_status = lbc->charger_status;
+               g_array_append_val(arrays, lbci);
+       }
+       ret = pthread_mutex_unlock(&heart_battery_mutex);
+       if (ret) {
+               _E("pthread_mutex_unlock() failed, %d", ret);
+               return RESOURCED_ERROR_FAIL;
+       }
+       return RESOURCED_ERROR_NONE;
+}
+
+/* ============================ DBUS interface ====================== */
+
+static void dbus_get_battery_capacity_history_latest(GDBusMethodInvocation *invocation, GVariant *params)
+{
+       int i, size, charge, max_size;
+       GArray *arrays = NULL;
+       GVariantBuilder builder, *sub_builder;
+
+       do_expr_unless_g_variant_get_typechecked(goto failure, params, "(ii)", &charge, &max_size);
+       if (charge < 0 || max_size < 0) {
+               _E("Wrong message arguments!");
+               goto failure;
+       }
+
+       size = g_slist_length(capacity_history_list);
+       if (!size) {
+               _I("capacity history is empty");
+               goto failure;
+       }
+       arrays = g_array_new(FALSE, FALSE, sizeof(struct heart_battery_capacity *));
+       if (!arrays) {
+               _E("Failed to alloc array");
+               goto failure;
+       }
+       if (heart_battery_get_capacity_history_latest(arrays, charge, max_size) != RESOURCED_ERROR_NONE) {
+               _E("Failed to get capacity history latest");
+               D_BUS_REPLY_ERR(invocation);
+               return;
+       }
+
+       g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
+       sub_builder = g_variant_builder_new(G_VARIANT_TYPE("a(iii)"));
+       if (!arrays->len) {
+               _E("No battery capacity history data");
+               goto exit;
+       }
+
+       for (i = 0; i < arrays->len; i++) {
+               struct heart_battery_capacity *lbc;
+               lbc = g_array_index(arrays, struct heart_battery_capacity *, i);
+               if (!lbc)
+                       break;
+
+               g_variant_builder_add(sub_builder, "(iii)", lbc->capacity,
+                                                       lbc->used_time, lbc->charging_time);
+               free(lbc);
+       }
+exit:
+       g_variant_builder_add_value(&builder, g_variant_new("a(iii)", sub_builder));
+       g_variant_builder_unref(sub_builder);
+       g_array_free(arrays, TRUE);
+       g_dbus_method_invocation_return_value(invocation, g_variant_builder_end(&builder));
+       return;
+
+failure:
+       D_BUS_REPLY_ERR(invocation);
+}
+
+static void dbus_get_battery_capacity_history(GDBusMethodInvocation *invocation, GVariant *params)
+{
+       int ret, size, period = -1, index;
+       struct heart_battery_capacity *lbc;
+       GSList *iter;
+       time_t curr = time(NULL);
+       GVariantBuilder builder, *sub_builder;
+
+       do_expr_unless_g_variant_get_typechecked(goto failure, params, "(i)", &period);
+       if (period < 0) {
+               _E("Wrong message arguments!");
+               goto failure;
+       }
+       switch (period) {
+       case DATA_LATEST:
+               index = 0;
+               break;
+       case DATA_3HOUR:
+               index = 3;
+               break;
+       case DATA_6HOUR:
+               index = 6;
+               break;
+       case DATA_12HOUR:
+               index = 12;
+               break;
+       case DATA_1DAY:
+               index = 24;
+               break;
+       default:
+               _E("Wrong message arguments! %d", period);
+               goto failure;
+       }
+       size = g_slist_length(capacity_history_list);
+       if (!size) {
+               _I("capacity history is empty");
+               goto failure;
+       }
+       ret = pthread_mutex_lock(&heart_battery_mutex);
+       if (ret) {
+               _E("pthread_mutex_lock() failed, %d", ret);
+               goto failure;
+       }
+
+       g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
+       sub_builder = g_variant_builder_new(G_VARIANT_TYPE("a(su)"));
+
+       gslist_for_each_item(iter, capacity_history_list) {
+               lbc = (struct heart_battery_capacity *)iter->data;
+               if (!lbc)
+                       break;
+               if (index && (lbc->timestamp < curr - (index * 3600)))
+                       continue;
+
+               g_variant_builder_add(sub_builder, "(iii)", lbc->capacity,
+                                                       lbc->used_time, lbc->charging_time);
+       }
+
+       ret = pthread_mutex_unlock(&heart_battery_mutex);
+       if (ret) {
+               _E("pthread_mutex_unlock() failed, %d", ret);
+               g_variant_builder_unref(sub_builder);
+               goto failure;
+       }
+
+       g_variant_builder_add_value(&builder, g_variant_new("a(iii)", sub_builder));
+       g_variant_builder_unref(sub_builder);
+
+       g_dbus_method_invocation_return_value(invocation, g_variant_builder_end(&builder));
+       return;
+
+failure:
+       D_BUS_REPLY_ERR(invocation);
+}
+
+static void dbus_get_battery_used_time(GDBusMethodInvocation *invocation, GVariant *params)
+{
+       heart_battery_update_used_time(logging_get_time(CLOCK_BOOTTIME),
+                       batt_stat.curr_charger_status);
+
+       g_dbus_method_invocation_return_value(invocation,
+                       g_variant_new("(i)", batt_used.used_time_sec));
+}
+
+static int get_battery_remaining_time(int mode, enum charger_status_type status)
+{
+       int i, ret, count;
+       long sum, time, cumul_average, trend_average;
+       double result;
+
+       ret = count = 0;
+       sum = time = 0;
+       cumul_average = trend_average = 0;
+       /* get prediction time of cumulative value */
+       for (i = 0; i <= WEEK; i++) {
+               time = heart_battery_get_prediction_time(i, status);
+               if (time) {
+                       sum += time;
+                       count++;
+               }
+       }
+       if (count)
+               cumul_average = sum / count;
+
+       count = 0;
+       sum = 0;
+       /* get prediction time of trend value */
+       for (i = COUNT; i < MAX_STRATEGY; i++) {
+               time = heart_battery_get_prediction_time(i, status);
+               if (time) {
+                       sum += time;
+                       count++;
+               }
+       }
+       if (count)
+               trend_average = sum / count;
+
+       /* failed to get prediction so return learning mode */
+       if (!cumul_average && !trend_average) {
+               if (batt_stat.curr_capacity != 100 && batt_stat.curr_capacity != 0)
+                       ret = BATTERY_USAGE_LEARNING;
+       } else if (cumul_average && !trend_average) {
+               /* failed to get prediction of trend average */
+               ret = cumul_average;
+       } else if (!cumul_average && trend_average) {
+               /* failed to get prediction of cumulative average */
+               ret = trend_average;
+       } else
+               ret = ((cumul_average * CUMUL_WEIGHT) + (trend_average * TREND_WEIGHT));
+
+       if (status == CHARGING) {
+               if (logic_v2)  /* new logic */
+                       return batt_stat.remaining_time_chg;
+               return ret; /* old logic */
+       }
+
+       if (logic_v2) { /* new logic */
+               switch (mode) {
+               case POWER_SAVING_MODE:
+                       /* Fall through */
+               case ULTRA_SAVING_MODE:
+                       ret = get_battery_remaining_time_ups();
+                       break;
+               case POWER_NORMAL_MODE:
+                       ret = get_battery_remaining_time_new();
+                       break;
+               default:
+                       break;
+               }
+               return ret;
+       }
+
+       if (ret <= 0)
+               return BATTERY_USAGE_LEARNING;
+
+        /* old logic */
+       switch (mode) {
+       case ULTRA_SAVING_MODE:
+               /* Fall through */
+       case POWER_SAVING_MODE:
+               result = (double)ret * default_mode_factor[mode];
+               return (int)result;
+       case POWER_NORMAL_MODE:
+               /* Fall through */
+       default:
+               return ret;
+       }
+}
+
+static void dbus_get_battery_remaining_time(GDBusMethodInvocation *invocation, GVariant *params)
+{
+       int ret, mode = -1;
+
+       do_expr_unless_g_variant_get_typechecked(goto failure, params, "(i)", &mode);
+       if (mode < 0) {
+               _E("Wrong message arguments!");
+               goto failure;
+       }
+
+       if (!battery_learning_mode)
+               battery_learning_mode = heart_battery_get_learning_mode();
+
+       if (!battery_learning_mode) {
+               _E("data is not enough to calculate prediction");
+               ret = BATTERY_USAGE_LEARNING;
+       } else {
+               if (batt_stat.curr_capacity <= 0) {
+                       _I("Last capacity read may not be proper so read again");
+                       batt_stat.curr_capacity = heart_battery_direct_get_capacity();
+                       if (batt_stat.curr_capacity <= 0) {
+                               /*
+                                * still not proper ? return learning mode
+                                */
+                               ret = BATTERY_USAGE_LEARNING;
+                       } else {
+                               heart_battery_cal_discharge_rem_time();
+                               ret = get_battery_remaining_time(mode, DISCHARGING);
+                       }
+               } else {
+                       ret = get_battery_remaining_time(mode, DISCHARGING);
+               }
+       }
+
+       _I("Remaining_time %d (mode: %d)", ret, mode);
+       g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", ret));
+       return;
+
+failure:
+       D_BUS_REPLY_ERR(invocation);
+}
+
+static void dbus_get_battery_charging_time(GDBusMethodInvocation *invocation, GVariant *params)
+{
+       int ret = get_battery_remaining_time(POWER_NORMAL_MODE, CHARGING);
+       _I("Remaining_charging_time %d", ret);
+       g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", ret));
+}
+
+static void dbus_get_battery_discharge_rate_level(GDBusMethodInvocation *invocation, GVariant *params)
+{
+       int ret = batt_stat.discharge_rate_level;
+       _I("discharge_rate_level %d", ret);
+       g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", ret));
+}
+
+static void dbus_battery_save_to_file(GDBusMethodInvocation *invocation, GVariant *params)
+{
+       heart_battery_status_save_to_db();
+
+       int ret = heart_battery_capacity_save_to_file(HEART_BATTERY_CAPACITY_DATA_FILE);
+       if (ret) {
+               _E("save to file failed");
+               D_BUS_REPLY_ERR(invocation)
+               return;
+       }
+
+       g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", ret));
+}
+
+static const char dbus_methods_xml[] =
+"              <method name='GetBatteryCapacityHistory'>"
+"                      <arg type='i' name='Period' direction='in'/>"
+"                      <arg type='a(iii)' name='CapacityHistory' direction='out'/>"
+"              </method>"
+"              <method name='GetBatteryCapacityHistoryLatest'>"
+"                      <arg type='i' name='Charge' direction='in'/>"
+"                      <arg type='i' name='MaxSize' direction='in'/>"
+"                      <arg type='a(iii)' name='CapacityHistory' direction='out'/>"
+"              </method>"
+"              <method name='GetBatteryUsedTime'>"
+"                      <arg type='i' name='UsedTime' direction='out'/>"
+"              </method>"
+"              <method name='GetBatteryRemainingTime'>"
+"                      <arg type='i' name='Mode' direction='in'/>"
+"                      <arg type='i' name='RemainingTime' direction='out'/>"
+"              </method>"
+"              <method name='GetBatteryChargingTime'>"
+"                      <arg type='i' name='ChargingTime' direction='out'/>"
+"              </method>"
+"              <method name='GetBatteryDischargeRateLevel'>"
+"                      <arg type='i' name='DischargeRateLevel' direction='out'/>"
+"              </method>"
+"              <method name='SaveBatteryData'>"
+"                      <arg type='i' name='ZeroOnSuccess' direction='out'/>"
+"              </method>";
+
+static struct d_bus_method dbus_methods[] = {
+       { "GetBatteryCapacityHistory",       dbus_get_battery_capacity_history },
+       { "GetBatteryCapacityHistoryLatest", dbus_get_battery_capacity_history_latest },
+       { "GetBatteryUsedTime",              dbus_get_battery_used_time },
+       { "GetBatteryRemainingTime",         dbus_get_battery_remaining_time },
+       { "GetBatteryChargingTime",          dbus_get_battery_charging_time },
+       { "GetBatteryDischargeRateLevel",    dbus_get_battery_discharge_rate_level },
+       { "SaveBatteryData",                 dbus_battery_save_to_file },
+};
+
+/* =========================  DBUS interface END ==================== */
+static void heart_battery_used_time_init(enum charger_status_type status)
+{
+       batt_used.last_charger_status = status;
+       batt_used.last_update_time = logging_get_time(CLOCK_BOOTTIME);
+}
+
+static void heart_battery_status_init(void)
+{
+       int i, ret, status, capacity;
+
+       batt_stat.curr_capacity = 0;
+       batt_stat.curr_run_time_sec[DISCHARGING] = 0;
+       batt_stat.curr_run_time_sec[CHARGING] = 0;
+       batt_stat.curr_cap_counter[DISCHARGING] = 0;
+       batt_stat.curr_cap_counter[CHARGING] = 0;
+       batt_stat.curr_charger_status = 0;
+       batt_stat.reset_mark = 0;
+
+       for (i = 0; i < BATTERY_HISTORY_RESET_MAX; i++) {
+               heart_battery_set_usage_reset_stime(i, 0);
+               heart_battery_set_usage_reset(i, DISCHARGING, 0, 0);
+               heart_battery_set_usage_reset(i, CHARGING, 0, 0);
+       }
+
+
+       for (i = 0; i < BATTERY_LEVEL_MAX; i++) {
+               heart_battery_set_usage_level_stime(i, 0);
+               heart_battery_set_usage_level(i, DISCHARGING, default_sec_per_cap[DISCHARGING][DEFAULT_AVG], 0);
+               heart_battery_set_usage_level(i, CHARGING, default_sec_per_cap[CHARGING][DEFAULT_AVG], 0);
+       }
+
+       for (i = 0; i < BATTERY_HISTORY_DAY_MAX; i++) {
+               heart_battery_set_usage_week_stime(i, 0);
+               heart_battery_set_usage_week(i, DISCHARGING, 0, 0);
+               heart_battery_set_usage_week(i, CHARGING, 0, 0);
+       }
+
+       for (i = 0; i < MAX_STRATEGY; i++) {
+               heart_battery_set_prediction(i, DISCHARGING, 0, 0, 0);
+               heart_battery_set_prediction(i, CHARGING, 0, 0, 0);
+       }
+
+       ret = heart_battery_status_read_from_db();
+       if (ret < 0)
+               _E("Failed to read battery status data");
+
+       if (logic_v2) {
+               for (i = 0; i < INDEX_WINDOW_SIZE; i++) {
+                       batt_stat.last_wall_time[i] = 0;
+                       batt_stat.last_volt_intg[i] = 0.0;
+               }
+               for (i = 0; i < BATTERY_LEVEL_GAP; i++)
+                       batt_stat.last_wall_time_chg_diff[i] = 0;
+
+               batt_stat.data_available = 0;
+               batt_stat.last_capacity = 0;
+               batt_stat.last_capacity_chg = 0;
+               first_level_change = FALSE;
+               batt_stat.curr_index = 0;
+               batt_stat.remaining_time = 0;
+               batt_stat.remaining_time_ups = 0;
+               batt_stat.last_pwr_bchg = average_pwr;
+               batt_stat.last_wall_time_chg = 0;
+               batt_stat.index_chg = 0;
+               batt_stat.remaining_time_chg = 0;
+               batt_stat.last_clock_tick =  logging_get_time(CLOCK_BOOTTIME);
+               for (i = 0; i < INDEX_WINDOW_SIZE; i++)
+                       batt_stat.pvt.total_dischg_time[i] = 0;
+               batt_stat.pvt.pvt_data_ind = 0;
+               batt_stat.pvt.start_cap_dischg = 0;
+               batt_stat.pvt.start_time_dischg = 0;
+               batt_stat.pvt.last_clock_tick = 0;
+
+               /* During the device boot-up, calculate energy for 100% battery and calcuate
+               pivot(norma and UPS mode) for time remaining time estimation*/
+               heart_battery_calculate_pivot();
+               /*get all the previousely stored data from file to program variable*/
+               heart_battery_read_data_from_file();
+               /* get all the previosly stored pivot info */
+               heart_battery_read_pivot_info_from_file();
+               /* if enough pivot data present then update the pivot */
+               heart_battery_update_pivot();
+               /*
+               * check whether was device power off for long time. If yes then adjust
+               * our stored time values
+               */
+               heart_battery_power_off_time_adjustment();
+               /*
+               * register callback for any time change from user side.
+               * If any time change happen then adjust whole data as per new time
+               */
+               vconf_notify_key_changed(VCONFKEY_SETAPPL_TIMEZONE_INT, time_change_notify_cb, NULL);
+               vconf_notify_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED, time_change_notify_cb, NULL);
+               vconf_notify_key_changed(VCONFKEY_REGIONFORMAT, time_change_notify_cb, NULL);
+       }
+
+       battery_learning_mode = heart_battery_get_learning_mode();
+
+       ret = heart_battery_capacity_read_from_file(HEART_BATTERY_CAPACITY_DATA_FILE);
+       if (ret < 0)
+               _E("Failed to read battery capacity data");
+
+       capacity = heart_battery_direct_get_capacity();
+       status = heart_battery_direct_get_charger_status();
+
+       /*
+        * Consider power off charing mode
+        * If new capacity is higher than old capacity and it is full, reset heart data
+        */
+       if (capacity > batt_stat.curr_capacity && status == DISCHARGING && capacity >= 90)
+               heart_battery_reset(NULL);
+       else
+               heart_battery_used_time_init(batt_stat.curr_charger_status);
+
+       if (capacity > 0)
+               batt_stat.curr_capacity = capacity;
+       if (status >= 0)
+               batt_stat.curr_charger_status = status;
+
+       heart_battery_calculate_prediction(batt_stat.curr_charger_status);
+       batt_stat.last_event_wall_time = logging_get_time(CLOCK_BOOTTIME);
+       batt_stat.discharge_rate_level = BATTERY_DISCHARGE_NONE;
+
+       if (logic_v2) {
+               heart_battery_cal_discharge_rem_time();
+
+               if (batt_stat.curr_charger_status == CHARGING) {
+                       heart_battery_cal_charging_rem_time();
+                       first_level_change = TRUE;
+               } else {
+                       heart_battery_collect_discharge_data();
+               }
+       }
+}
+
+static int low_battery_handler(void *data)
+{
+       heart_battery_save_to_file(false);
+       return RESOURCED_ERROR_NONE;
+}
+
+static int heart_battery_config(struct parse_result *result, void *user_data)
+{
+       int val;
+       int battery_capacity = 0;
+
+       if (!result)
+               return -EINVAL;
+
+       if (!strncmp(result->section, HEART_BATTERY_CONF_SECTION, sizeof(HEART_BATTERY_CONF_SECTION) + 1)) {
+               if (!strncmp(result->name, "POWER_NORMAL_MODE", sizeof("POWER_NORMAL_MODE") + 1)) {
+                       val = atoi(result->value);
+                       if (val > 0)
+                               default_mode_spc[POWER_NORMAL_MODE] = val;
+                       _D("POWER_NORMAL_MODE SPC: %d", val);
+               } else if (!strncmp(result->name, "POWER_SAVING_MODE", sizeof("POWER_SAVING_MODE") + 1)) {
+                       val = atoi(result->value);
+                       if (val > 0)
+                               default_mode_spc[POWER_SAVING_MODE] = val;
+                       _D("POWER_SAVING_MODE SPC: %d", val);
+               } else if (!strncmp(result->name, "ULTRA_SAVING_MODE", sizeof("ULTRA_SAVING_MODE") + 1)) {
+                       val = atoi(result->value);
+                       if (val > 0)
+                               default_mode_spc[ULTRA_SAVING_MODE] = val;
+                       _D("ULTRA_POWER_SAVING_MODE SPC: %d", val);
+               }
+       } else if (!strncmp(result->section, battery_header, sizeof(battery_header) + 1)) {
+               if (!strncmp(result->name, "LOGIC_V2", sizeof("LOGIC_V2") + 1)) {
+                       logic_v2 = atoi(result->value);
+                       _I("logic_v2 : %d", logic_v2);
+               } else if (!strncmp(result->name, "LOGIC_RUL", sizeof("LOGIC_RUL") + 1)) {
+                       logic_rul = atoi(result->value);
+                       _I("logic_rul : %d", logic_rul);
+               } else if (!strncmp(result->name, "BATTERY_CAPACITY", sizeof("BATTERY_CAPACITY") + 1)) {
+                       battery_capacity = atoi(result->value);
+                       _I("total battery capacity: %d", battery_capacity);
+
+                       if(total_battery_capacity == 0 && !battery_capacity) {
+                               /* sys interface battery capacity path not found, read from conf file */
+                               total_battery_capacity = battery_capacity * 60; /* mAm */
+                       }
+               } else if (!strncmp(result->name, "DISCHARGE_FAST", sizeof("DISCHARGE_FAST") + 1)) {
+                       discharge_fast = atoi(result->value);
+                       _I("discharge_fast: %d", discharge_fast);
+               } else if (!strncmp(result->name, "DISCHARGE_SLOW", sizeof("DISCHARGE_SLOW") + 1)) {
+                       discharge_slow = atoi(result->value);
+                       _I("discharge_slow: %d", discharge_slow);
+               } else if (!strncmp(result->name, "AVERAGE_PWR", sizeof("AVERAGE_PWR") + 1)) {
+                       average_pwr = atof(result->value);
+                       _I("average_power: %lf", average_pwr);
+               } else if (!strncmp(result->name, "OCV_SOC_POLY_COEF", sizeof("OCV_SOC_POLY_COEF") + 1)) {
+                       char *token, *saveptr = NULL;
+                       int i;
+                       token = strtok_r(result->value, " ", &saveptr);
+                       if (token) {
+                               ocv_degree = atoi(token);
+                               if (ocv_degree <= 0) {
+                                       _E("ocv_degree should be positive if you decide to use logic_v2");
+                                       return -EINVAL;
+                               }
+                               intg = calloc(ocv_degree, sizeof(double));
+                               if (!intg) {
+                                       _E("Out of memory");
+                                       return -ENOMEM;
+                               }
+                               _I("Degree of OCV_SOC_POLY = %d", ocv_degree);
+
+                               for (i = 0; i < ocv_degree; i++) {
+                                       token = strtok_r(NULL, " ", &saveptr);
+                                       if (!token) {
+                                               _E("There is no OCV_SOC_POLY_COEF_%d", i + 1);
+                                               return -EINVAL;
+                                       }
+                                       intg[i] = atof(token);
+                                       _I("OCV_SOC_POLY_COEF_%d = %.9g", i + 1, intg[i]);
+                               }
+                       }
+               }
+       }  else if (!strncmp(result->section, "POWER_PROFILE", sizeof("POWER_PROFILE") + 1)) {
+               if (!strncmp(result->name, "WIFI_ACTIVE", sizeof("WIFI_ACTIVE") + 1)) {
+                       power_profile.wifi_active = atof(result->value);
+                       _D("HEART WIFI_ACTIVE: %f", power_profile.wifi_active);
+               } else if (!strncmp(result->name, "WIFI_ON", sizeof("WIFI_ON") + 1)) {
+                       power_profile.wifi_on = atof(result->value);
+                       _D("HEART WIFI_ON: %f", power_profile.wifi_on);
+               }
+       }
+       return RESOURCED_ERROR_NONE;
+}
+
+static void heart_battery_mode_factor_init(void)
+{
+       double val;
+
+       val = default_mode_spc[POWER_SAVING_MODE]/default_mode_spc[POWER_NORMAL_MODE];
+
+       if (1.0 < val)
+               default_mode_factor[POWER_SAVING_MODE] = val;
+       _I("POWER_SAVING_MODE factor: %f", val);
+
+       val = default_mode_spc[ULTRA_SAVING_MODE]/default_mode_spc[POWER_NORMAL_MODE];
+
+       if (1.0 < val)
+               default_mode_factor[ULTRA_SAVING_MODE] = val;
+       _I("ULTRA_POWER_SAVING_MODE factor: %f", val);
+}
+
+/*
+ * This function will read total battery capacity from sys interface
+ * example - 1500mAh or 2600mAh
+ */
+static void heart_read_battery_total_capacity(void)
+{
+       u_int32_t batt_capacity;
+
+       /*
+        * read the battery total capacity from sys interface path
+        * "/sys/class/power_supply/battery/batt_capacity"
+        * which is provided by kernel
+        */
+       if (fread_uint("/sys/class/power_supply/battery/batt_capacity",
+                                       &batt_capacity) != RESOURCED_ERROR_NONE) {
+               _D("This device doesn't support battery capacity information. Disable LOGIC_V2");
+               return;
+       }
+
+       snprintf(battery_header, sizeof(battery_header), "BATTERY_%d",
+                       batt_capacity);
+
+       /*
+        * convert battery capacity from mAh to mAm
+        */
+       total_battery_capacity = batt_capacity * 60;
+       _I("battery capacity = %d, battery header = %s",
+                       batt_capacity, battery_header);
+}
+
+/* Database related operations for heart-battery tables */
+
+static int heart_battery_stats_init_db(void)
+{
+       sqlite3 *battery_stats_db;
+       char *err_msg = NULL;
+       char buf[HEART_BATTERY_STATS_MAX] = {0, };
+       int ret;
+
+       ret = sqlite3_open(BATTERY_STATS_DB_FILE_NAME, &battery_stats_db);
+       if (ret != SQLITE_OK) {
+               _E("Can't open database %s: %s", BATTERY_STATS_DB_FILE_NAME,
+                  sqlite3_errmsg(battery_stats_db));
+               goto error_db_open;
+       }
+
+       snprintf(buf, HEART_BATTERY_STATS_MAX, "%s", QUERY_CREATE_BATTERY_STATS);
+       ret = sqlite3_exec(battery_stats_db, buf, NULL, NULL, &err_msg);
+       if (ret != SQLITE_OK) {
+               _E("create failed: %s", err_msg);
+               sqlite3_free(err_msg);
+               goto error_db_open;
+       }
+       _I("Create db Success");
+
+error_db_open:
+       sqlite3_close(battery_stats_db);
+       return ret;
+}
+
+static int heart_battery_stats_db_open_transaction(sqlite3 *db)
+{
+       char *err_msg = NULL;
+
+       if (sqlite3_exec(db, "PRAGMA journal_mode = PERSIST", NULL, NULL, &err_msg) != SQLITE_OK) {
+               _E("sqlite3_exec(\"PRAGMA journal_mode = PERSIST\") failed! -> %s", err_msg);
+               sqlite3_free(err_msg);
+               return RESOURCED_ERROR_DB_FAILED;
+       }
+
+       if (sqlite3_exec(db, "BEGIN EXCLUSIVE", NULL, NULL, &err_msg) != SQLITE_OK) {
+               _E("sqlite3_exec(\"BEGIN EXCLUSIVE\") failed! -> %s", err_msg);
+               sqlite3_free(err_msg);
+               return RESOURCED_ERROR_DB_FAILED;
+       }
+
+       return RESOURCED_ERROR_NONE;
+}
+
+int heart_battery_stats_execute_insert_db(char buf[])
+{
+       sqlite3 *battery_stats_db;
+       char *err_msg = NULL;
+       int ret;
+
+       if (sqlite3_open(BATTERY_STATS_DB_FILE_NAME, &battery_stats_db) != SQLITE_OK) {
+               _E("Can't open database %s: %s", BATTERY_STATS_DB_FILE_NAME,
+                  sqlite3_errmsg(battery_stats_db));
+               return RESOURCED_ERROR_DB_FAILED;
+       }
+       ret = heart_battery_stats_db_open_transaction(battery_stats_db);
+       if (ret != RESOURCED_ERROR_NONE)
+               goto error_close;
+
+       if (sqlite3_exec(battery_stats_db, buf, NULL, NULL, &err_msg) != SQLITE_OK) {
+               _E("sqlite3_exec(\"%s\") failed! -> %s", buf, err_msg);
+               sqlite3_free(err_msg);
+               goto error_db;
+       }
+
+       if (sqlite3_exec(battery_stats_db, "COMMIT", NULL, NULL, NULL) != SQLITE_OK) {
+               _E("sqlite3_exec(\"COMMIT\") failed!");
+               goto error_db;
+       }
+       _I("QUERY: %s SUCCESS", buf);
+
+       sqlite3_close(battery_stats_db);
+       return RESOURCED_ERROR_NONE;
+
+error_db:
+       if (sqlite3_exec(battery_stats_db, "ROLLBACK", NULL, NULL, NULL) != SQLITE_OK)
+               _E("sqlite3_exec(\"ROLLBACK\") failed!");
+       _I("QUERY: %s FAILED", buf);
+error_close:
+       sqlite3_close(battery_stats_db);
+       return RESOURCED_ERROR_DB_FAILED;
+}
+
+long heart_battery_stats_execute_select_total_db(char buf[])
+{
+       sqlite3 *battery_stats_db;
+       sqlite3_stmt *stmt;
+       long totaltime = 0;
+       int ret;
+
+       if (sqlite3_open(BATTERY_STATS_DB_FILE_NAME, &battery_stats_db) != SQLITE_OK) {
+               _E("Can't open database %s: %s", BATTERY_STATS_DB_FILE_NAME,
+                  sqlite3_errmsg(battery_stats_db));
+               return 0;
+       }
+
+       ret = sqlite3_prepare_v2(battery_stats_db, buf, -1, &stmt, NULL);
+       if (ret != SQLITE_OK) {
+               _E("Failed to prepare query %s", sqlite3_errmsg(battery_stats_db));
+               goto error_db;
+       }
+
+       ret = sqlite3_step(stmt);
+       switch (ret) {
+       case SQLITE_ROW:
+               _I("QUERY: %s SUCCESS", buf);
+               totaltime = (long)sqlite3_column_int(stmt, 0);
+               _D("totaltime: (%ld)", totaltime);
+               break;
+       case SQLITE_DONE:
+               _D("SQLITE_DONE");
+               break;
+       case SQLITE_ERROR:
+               /* FALLTHROUGH */
+               _E("sqlite3_step failed %s", sqlite3_errmsg(battery_stats_db));
+       default:
+               _E("RESOURCED_ERROR_DB_FAILED");
+               break;
+       }
+       sqlite3_finalize(stmt);
+error_db:
+       sqlite3_close(battery_stats_db);
+       return totaltime;
+}
+
+static void rul_data_init(void)
+{
+       _cleanup_fclose_ FILE *fp = NULL;
+       int ret, check;
+
+       rul.charging_start_time = 0;
+       rul.charging_stop_time = 0;
+       rul.raw_capacity = 0;
+       rul.soc_start = 0;
+       rul.soc_stop = 0;
+       rul.curr_soc = heart_battery_direct_get_capacity();
+       rul.prev_soc = rul.curr_soc;
+
+       /* Init LCD related data */
+       rul.lcd_data.on_start_time = 0;
+       rul.lcd_data.on_stop_time = 0;
+       rul.lcd_data.on_time = 0;
+       ret = device_display_get_state(&rul.lcd_data.state);
+       if (ret != DEVICE_ERROR_NONE) {
+               _E("Failed to get device display state with err = %d", ret);
+               return;
+       }
+
+       /* Register callback for LCD state change */
+       check = device_add_callback(DEVICE_CALLBACK_DISPLAY_STATE, rul_display_state_changed_cb, NULL);
+       if (check != DEVICE_ERROR_NONE) {
+               _E("Failed to add calback with err = %d", check);
+               //TODO: consider "rul.charging_cycles = 0;"
+               return;
+       }
+
+       /* Read Charging cycles count from file */
+       fp = fopen(RUL_CHARGING_CYCLES_FILE, "r");
+       if (fp == NULL) {
+               _E("Can't open RUL_CHARGING_CYCLES_FILE");
+               rul.charging_cycles = 0;
+               return;
+       }
+
+       if (fscanf(fp, "%d", &rul.charging_cycles) != 1) {
+               _E("Unable to assign charging cycles from file");
+               rul.charging_cycles = 0;
+               return;
+       }
+}
+
+static int heart_battery_init(void *data)
+{
+       int ret;
+       bool supported;
+
+       ret = system_info_get_platform_bool("tizen.org/feature/battery", &supported);
+       if (ret != SYSTEM_INFO_ERROR_NONE || !supported) {
+               return RESOURCED_ERROR_NOTIMPL;
+       }
+
+       ret = heart_battery_stats_init_db();
+       if (ret != RESOURCED_ERROR_NONE) {
+               _E("heart module init failed at db creation");
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       heart_dbus_declare_methods(dbus_methods_xml, dbus_methods, ARRAY_SIZE(dbus_methods));
+
+       ret = d_bus_register_signal(DEVICED_PATH_BATTERY,
+                       DEVICED_INTERFACE_BATTERY, GET_BATTERY_CAPACITY,
+                       heart_battery_capacity_status, NULL);
+       if (ret < 0)
+               _E("heart module failed to add a capacity status signal handler");
+
+       ret = d_bus_register_signal(DEVICED_PATH_BATTERY,
+                       DEVICED_INTERFACE_BATTERY, GET_CHARGER_STATUS,
+                       heart_battery_charger_status, NULL);
+       if (ret < 0)
+               _E("heart module failed to add a charger status signal handler");
+
+       heart_read_battery_total_capacity();
+
+       config_parse(HEART_CONF_FILE_PATH, heart_battery_config, NULL);
+       _I("heart config init");
+
+
+       heart_battery_mode_factor_init();
+
+       heart_battery_status_init();
+
+       if (logic_rul)
+               rul_data_init();
+
+       register_notifier(RESOURCED_NOTIFIER_LOW_BATTERY, low_battery_handler);
+       register_notifier(RESOURCED_NOTIFIER_DATA_RESET, heart_battery_reset);
+
+       heart_battery_set_file_commit_timestamp(logging_get_time(CLOCK_BOOTTIME));
+
+       ret = logging_module_init(BATTERY_NAME, ONE_DAY, TEN_MINUTE, heart_battery_update,
+                                                       HEART_BATTERY_UPDATE_INTERVAL, SYSTEM_DEFAULT);
+       if (ret != RESOURCED_ERROR_NONE) {
+               _E("logging module init failed");
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       _D("heart battery init finished");
+       return RESOURCED_ERROR_NONE;
+}
+
+void heart_capacity_history_update(struct logging_table_form *data, void *user_data)
+{
+       int status, reset, capacity, diff;
+       unsigned long discharging = 0, charging = 0;
+       GSList **history_list = NULL;
+
+       if (user_data)
+               history_list = (GSList **)user_data;
+       else
+               history_list = &capacity_history_list;
+
+       _D("%s %s %ld %s", data->appid, data->pkgid, data->time, data->data);
+       if (sscanf(data->data, "%d %d %ld %ld %d %d ",
+                               &capacity, &diff,
+                               &discharging, &charging,
+                               &status, &reset) < 0) {
+               _E("sscanf failed");
+               return;
+       }
+       heart_battery_insert_capacity(history_list, capacity,
+                       diff, data->time, discharging, charging, status,
+                       reset, false);
+}
+
+static int heart_battery_dump(FILE *fp, int mode, void *data)
+{
+       struct heart_battery_capacity *lbc;
+       GSList *iter;
+       char buf[BATTERY_DATA_MAX] = {0, };
+       int ret, size, len = 0;
+       time_t starttime;
+       char timestr[80];
+       struct tm loc_tm;
+       GSList *history_list = NULL;
+
+       starttime = time(NULL);
+       starttime -= mode;
+       localtime_r(&starttime, &loc_tm);
+       /* print timestamp */
+       strftime(timestr, sizeof(timestr),
+                       "%Y-%m-%d %H:%M:%S%z", &loc_tm);
+
+       logging_read_foreach(BATTERY_NAME, NULL, NULL, starttime, 0,
+                       heart_capacity_history_update, &history_list);
+
+       if (!history_list) {
+               _E("capacity history is NULL!");
+               return RESOURCED_ERROR_NONE;
+       }
+       LOG_DUMP(fp, "[BATTERY CAPACITY HISTORY] since %s\n", timestr);
+       LOG_DUMP(fp, "capacity diff timestamp used_time charging_time charger_status, reset_mark\n");
+       ret = pthread_mutex_lock(&heart_battery_mutex);
+       if (ret) {
+               _E("pthread_mutex_lock() failed, %d", ret);
+               return RESOURCED_ERROR_FAIL;
+       }
+       size = g_slist_length(history_list);
+       if (!size) {
+               _I("capacity history is empty");
+               ret = pthread_mutex_unlock(&heart_battery_mutex);
+               if (ret) {
+                       _E("pthread_mutex_unlock() failed, %d", ret);
+                       return RESOURCED_ERROR_FAIL;
+               }
+               return RESOURCED_ERROR_NONE;
+       }
+       gslist_for_each_item(iter, history_list) {
+               lbc = (struct heart_battery_capacity *)iter->data;
+               if (!lbc)
+                       break;
+               len += snprintf(buf + len, BATTERY_DATA_MAX - len, "%d %d %ld %ld %ld %d %d\n",
+                               lbc->capacity, lbc->diff_capacity, lbc->timestamp, lbc->used_time,
+                               lbc->charging_time, lbc->charger_status,
+                               lbc->reset_mark);
+               if (BATTERY_DATA_MAX < len + BATTERY_LINE_MAX) {
+                       LOG_DUMP(fp, "%s\n", buf);
+                       len = 0;
+               }
+       }
+       LOG_DUMP(fp, "%s\n", buf);
+       ret = pthread_mutex_unlock(&heart_battery_mutex);
+       if (ret) {
+               _E("pthread_mutex_unlock() failed, %d", ret);
+               return RESOURCED_ERROR_FAIL;
+       }
+       fflush(fp);
+       if (history_list) {
+               g_slist_free_full(history_list, free);
+               history_list = NULL;
+       }
+
+       return RESOURCED_ERROR_NONE;
+}
+
+static int heart_battery_exit(void *data)
+{
+       int ret;
+       GSList *iter, *next;
+       struct heart_battery_capacity *lbc;
+
+       heart_battery_save_to_file(true);
+       ret = pthread_mutex_lock(&heart_battery_mutex);
+       if (ret)
+               _E("pthread_mutex_lock() failed, %d", ret);
+
+       gslist_for_each_safe(capacity_history_list, iter, next, lbc) {
+               capacity_history_list = g_slist_remove(capacity_history_list, lbc);
+               free(lbc);
+       }
+       capacity_history_list = NULL;
+
+       ret = pthread_mutex_unlock(&heart_battery_mutex);
+       if (ret)
+               _E("pthread_mutex_unlock() failed, %d", ret);
+
+       unregister_notifier(RESOURCED_NOTIFIER_LOW_BATTERY, low_battery_handler);
+       unregister_notifier(RESOURCED_NOTIFIER_DATA_RESET, heart_battery_reset);
+
+       logging_module_exit();
+
+       _D("heart battery exit");
+       return RESOURCED_ERROR_NONE;
+}
+
+static const struct heart_module_ops heart_battery_ops = {
+       .name           = "BATTERY",
+       .init           = heart_battery_init,
+       .dump           = heart_battery_dump,
+       .exit           = heart_battery_exit,
+};
+HEART_MODULE_REGISTER(&heart_battery_ops)
diff --git a/src/resource-monitor/heart-cpu.c b/src/resource-monitor/heart-cpu.c
new file mode 100644 (file)
index 0000000..39bed76
--- /dev/null
@@ -0,0 +1,1495 @@
+/*
+ * resourced
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @file heart-cpu.c
+ *
+ * @desc heart cpu module
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <glib.h>
+#include <math.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "proc-common.h"
+#include "notifier.h"
+#include "resourced.h"
+#include "dbus-handler.h"
+#include "heart.h"
+#include "logging.h"
+#include "heart-common.h"
+#include "trace.h"
+#include "module.h"
+#include "macro.h"
+#include "userinfo-list.h"
+#include "proc-main.h"
+
+#define PROC_PATH                              "/proc/%d"
+#define PROC_STAT_PATH                         "/proc/%d/stat"
+#define CPU_NAME                               "cpu"
+#define CPU_DATA_MAX                           1024
+#define CPU_ARRAY_MAX                          24
+#define HEART_CPU_SAVE_INTERVAL                        3600
+#define HEART_CPU_DATA_FILE                    HEART_USER_FILE_PATH"/.cpu.dat"
+
+enum {
+       SERVICE = 0,
+       FOREG = 1,
+       BACKG = 2
+};
+
+struct heart_cpu_info {
+       unsigned long utime;
+       unsigned long stime;
+       int state;
+       pid_t pid;
+};
+
+struct heart_cpu_table {
+       char appid[MAX_APPID_LENGTH];
+       char pkgid[MAX_PKGNAME_LENGTH];
+       unsigned long total_utime;
+       unsigned long total_stime;
+       unsigned long utime;
+       unsigned long stime;
+       int fg_count;
+       unsigned long fg_time;
+       unsigned long bg_time;
+       GSList *last_pid_info;
+       pid_t last_pid;
+       time_t last_renew_time;
+       GArray *cpu_info;
+};
+
+struct heart_cpu_dat_cache {
+       char *path;
+       GHashTable *list;
+       time_t last_file_commit_time;
+};
+
+static GHashTable *heart_cpu_app_list;
+static pthread_mutex_t heart_cpu_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static void heart_cpu_remove_last_pid_info_exited(struct heart_cpu_table *table)
+{
+       char proc_path[sizeof(PROC_PATH) + MAX_DEC_SIZE(int)];
+       GSList *iter, *next;
+       struct heart_cpu_info *ci = NULL;
+
+       if (!table || !table->last_pid_info)
+               return;
+
+       gslist_for_each_safe(table->last_pid_info, iter, next, ci) {
+               snprintf(proc_path, sizeof(proc_path), PROC_PATH, ci->pid);
+               if (!access(proc_path, F_OK))
+                       continue;
+               table->last_pid_info = g_slist_remove(table->last_pid_info, ci);
+               free(ci);
+       }
+}
+
+static struct heart_cpu_info *find_pid_info(struct heart_cpu_table *table, pid_t pid)
+{
+       GSList *iter = NULL;
+       struct heart_cpu_info *ci = NULL;
+
+       if (!table || !table->last_pid_info)
+               return NULL;
+
+       gslist_for_each_item(iter, table->last_pid_info) {
+               ci = (struct heart_cpu_info *)iter->data;
+               if (ci && ci->pid == pid)
+                       return ci;
+       }
+       return NULL;
+}
+
+static int heart_cpu_get_cpu_time(pid_t pid, unsigned long *utime,
+               unsigned long *stime)
+{
+       char proc_path[sizeof(PROC_STAT_PATH) + MAX_DEC_SIZE(int)];
+       FILE *fp;
+
+       assert(utime != NULL);
+       assert(stime != NULL);
+
+       snprintf(proc_path, sizeof(proc_path), PROC_STAT_PATH, pid);
+       fp = fopen(proc_path, "r");
+       if (fp == NULL)
+               return RESOURCED_ERROR_FAIL;
+
+       if (fscanf(fp, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s") < 0) {
+               fclose(fp);
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       if (fscanf(fp, "%lu %lu", utime, stime) < 1) {
+               fclose(fp);
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       fclose(fp);
+
+       return RESOURCED_ERROR_NONE;
+}
+
+static GHashTable* heart_cpu_get_user_app_list(int uid)
+{
+       struct heart_cpu_dat_cache *cache;
+
+       cache = (struct heart_cpu_dat_cache*)g_hash_table_lookup(heart_cpu_app_list, (gconstpointer)&uid);
+       if (!cache) {
+               _E("There is no table of uid %d", uid);
+               return NULL;
+       }
+
+       return cache->list;
+}
+
+static int heart_cpu_write_data(struct proc_status *ps, pid_t pid, int type)
+{
+       int ret;
+       unsigned long utime, stime;
+       char info[CPU_DATA_MAX];
+       char *appid, *pkgid;
+
+       ret = heart_cpu_get_cpu_time(pid, &utime, &stime);
+       if (ret != RESOURCED_ERROR_NONE)
+               return ret;
+
+       snprintf(info, sizeof(info), "%lu %lu %d %d ", utime, stime, pid, type);
+
+       ret = proc_get_id_info(ps, &appid, &pkgid);
+       if (ret != RESOURCED_ERROR_NONE) {
+               _E("Failed to proc_get_id_info");
+               return ret;
+       }
+       ret = logging_write(pid, CPU_NAME, appid, pkgid, time(NULL), info);
+       _D("heart_cpu_write_data : pid = %d, appname = %s, pkgname = %s, type=%d",
+                       pid, appid, pkgid, type);
+       return ret;
+}
+
+static int heart_cpu_service_launch(void *data)
+{
+       int ret;
+       struct proc_status *ps = (struct proc_status *)data;
+
+       ret = heart_cpu_write_data(ps, ps->pid, SERVICE);
+       if (ret != RESOURCED_ERROR_NONE) {
+               _E("Failed to write cpu info %d", ps->pid);
+               return ret;
+       }
+       resourced_notify(RESOURCED_NOTIFIER_LOGGING_START, NULL);
+       return RESOURCED_ERROR_NONE;
+}
+
+static int heart_cpu_foreground_state(void *data)
+{
+       int ret;
+       struct proc_status *ps = (struct proc_status *)data;
+
+       ret = heart_cpu_write_data(ps, ps->pid, FOREG);
+       if (ret != RESOURCED_ERROR_NONE) {
+               _E("Failed to write cpu info %d", ps->pid);
+               return ret;
+       }
+       resourced_notify(RESOURCED_NOTIFIER_LOGGING_START, NULL);
+       return RESOURCED_ERROR_NONE;
+}
+
+static int heart_cpu_background_state(void *data)
+{
+       int ret;
+       GSList *giter = NULL;
+       struct proc_status *ps = (struct proc_status *)data;
+
+       ret = heart_cpu_write_data(ps, ps->pid, BACKG);
+       if (ret != RESOURCED_ERROR_NONE) {
+               _E("Failed to write cpu info %d", ps->pid);
+               return ret;
+       }
+       if (!ps->pai->childs)
+               return RESOURCED_ERROR_NONE;
+       gslist_for_each_item(giter, ps->pai->childs) {
+               pid_t child = GPOINTER_TO_PID(giter->data);
+               ret = heart_cpu_write_data(ps, child, BACKG);
+               if (ret != RESOURCED_ERROR_NONE) {
+                       _E("Failed to write child cpu info %d", child);
+                       return ret;
+               }
+       }
+       resourced_notify(RESOURCED_NOTIFIER_LOGGING_START, NULL);
+       return RESOURCED_ERROR_NONE;
+}
+
+static int heart_cpu_update_state(void *data)
+{
+       int ret, state;
+       GSList *giter = NULL;
+       struct proc_status *ps = (struct proc_status *)data;
+
+       if (!ps->pai) {
+               _E("Invalid parameter");
+               return RESOURCED_ERROR_INVALID_PARAMETER;
+       }
+       if (ps->pai->lru_state == PROC_FOREGROUND)
+               state = FOREG;
+       else
+               state = BACKG;
+
+       ret = heart_cpu_write_data(ps, ps->pid, state);
+       if (ret != RESOURCED_ERROR_NONE) {
+               _E("Failed to write cpu info %d", ps->pid);
+               return ret;
+       }
+       _D("heart_cpu_update_state : pid = %d, state = %d",
+                       ps->pid, state);
+       if (!ps->pai->childs)
+               return RESOURCED_ERROR_NONE;
+       gslist_for_each_item(giter, ps->pai->childs) {
+               pid_t child = GPOINTER_TO_PID(giter->data);
+               ret = heart_cpu_write_data(ps, child, state);
+               if (ret != RESOURCED_ERROR_NONE) {
+                       _E("Failed to write cpu info %d", child);
+                       return ret;
+               }
+       }
+       resourced_notify(RESOURCED_NOTIFIER_LOGGING_START, NULL);
+       return RESOURCED_ERROR_NONE;
+}
+
+static int heart_cpu_update_app_list(void *data)
+{
+       _cleanup_app_list_close_ GSList *proc_app_list = PAL_INIT_VALUE;
+       GSList *giter = NULL;
+       struct proc_app_info *pai = NULL;
+
+       proc_app_list = proc_app_list_open();
+       gslist_for_each_item(giter, proc_app_list) {
+               struct proc_status ps;
+               pai = (struct proc_app_info *)giter->data;
+               if (!pai->ai)
+                       continue;
+               ps.pid = pai->main_pid;
+               ps.pai = pai;
+               heart_cpu_update_state(&ps);
+       }
+       return RESOURCED_ERROR_NONE;
+}
+
+static void heart_cpu_free_uid(gpointer data)
+{
+       if (data)
+               free(data);
+}
+
+static void heart_cpu_free_dat_cache(gpointer data)
+{
+       struct heart_cpu_dat_cache *cache = (struct heart_cpu_dat_cache*)data;
+       if (cache) {
+               free(cache->path);
+               g_hash_table_destroy(cache->list);
+               free(cache);
+       }
+}
+
+static void heart_free_value(gpointer value)
+{
+       int i;
+       struct heart_cpu_info *info;
+       struct heart_cpu_table *table = (struct heart_cpu_table *)value;
+
+       if (!table)
+               return;
+
+       if (table->last_pid_info)
+               g_slist_free_full(table->last_pid_info, free);
+
+       if (table->cpu_info) {
+               for (i = 0; i < table->cpu_info->len; i++) {
+                       info = g_array_index(table->cpu_info,
+                                       struct heart_cpu_info *, i);
+                       free(info);
+               }
+               g_array_free(table->cpu_info, TRUE);
+       }
+
+       free(table);
+}
+
+static int heart_cpu_read_length(char *buf, int count)
+{
+       int i, find = 0;
+       int len = strlen(buf);
+
+       for (i = 0; i < len; i++) {
+               if (buf[i] == ' ')
+                       find++;
+               if (find == count)
+                       return i + 1;
+       }
+       return RESOURCED_ERROR_FAIL;
+}
+
+static int heart_cpu_read_from_file(struct heart_cpu_dat_cache *cache)
+{
+       int i, len, ret, fg_count, state;
+       unsigned long total_utime, total_stime;
+       unsigned long utime, stime;
+       unsigned long fg_time, bg_time;
+       pid_t pid;
+       FILE *fp;
+       struct heart_cpu_table *table;
+       char appid[MAX_APPID_LENGTH] = {0, };
+       char pkgid[MAX_PKGNAME_LENGTH] = {0, };
+       char buf[CPU_DATA_MAX] = {0, };
+
+       if (!cache) {
+               _E("Cache doesn't exist");
+               return RESOURCED_ERROR_INVALID_PARAMETER;
+       }
+
+       snprintf(buf, CPU_DATA_MAX, HEART_CPU_DATA_FILE, cache->path);
+       fp = fopen(buf, "r");
+       if (!fp) {
+               if (errno != ENOENT) {
+                       _E("Fail to open %s (%d)", buf, errno);
+                       return RESOURCED_ERROR_FAIL;
+               }
+
+               _D("%s doesn't exist. Make new one.", buf);
+               snprintf(buf, CPU_DATA_MAX, HEART_USER_FILE_PATH, cache->path);
+               ret = mkdir(buf, S_IRWXU | S_IRWXG | S_IROTH);
+               if (ret != 0 && errno != EEXIST) {
+                       _E("Fail to create %s (%d)", buf, errno);
+                       return RESOURCED_ERROR_FAIL;
+               }
+
+               snprintf(buf, CPU_DATA_MAX, HEART_CPU_DATA_FILE, cache->path);
+               fp = fopen(buf, "w+");
+               if (!fp) {
+                       _E("Fail to create %s (%d)", buf, errno);
+                       return RESOURCED_ERROR_FAIL;
+               }
+               fclose(fp);
+               return RESOURCED_ERROR_NONE;
+       }
+
+       while (fgets(buf, CPU_DATA_MAX, fp)) {
+               table = malloc(sizeof(struct heart_cpu_table));
+
+               if (!table) {
+                       _E("malloc failed");
+                       fclose(fp);
+                       return RESOURCED_ERROR_OUT_OF_MEMORY;
+               }
+
+               /* make return values */
+               ret = sscanf(buf, STR_FS(MAX_APPID_LENGTH_M1)" "STR_FS(MAX_PKGNAME_LENGTH_M1)" %lu %lu %lu %lu %lu %lu %d ",
+                               appid, pkgid,
+                               &total_utime, &total_stime,
+                               &utime, &stime,
+                               &fg_time, &bg_time, &fg_count);
+
+               if (ret <= 0) {
+                       _E("sscanf failed");
+                       free(table);
+                       fclose(fp);
+                       return RESOURCED_ERROR_FAIL;
+               }
+
+               if (snprintf(table->appid, MAX_APPID_LENGTH, "%s", appid) < 0) {
+                       _E("sprintf failed");
+                       free(table);
+                       fclose(fp);
+                       return RESOURCED_ERROR_OUT_OF_MEMORY;
+               }
+
+               if (snprintf(table->pkgid, MAX_PKGNAME_LENGTH, "%s", pkgid) < 0) {
+                       _E("snprintf failed");
+                       free(table);
+                       fclose(fp);
+                       return RESOURCED_ERROR_OUT_OF_MEMORY;
+               }
+               len = heart_cpu_read_length(buf, 9);
+               if (len <= 0) {
+                       _E("sscanf failed");
+                       free(table);
+                       fclose(fp);
+                       return RESOURCED_ERROR_FAIL;
+               }
+               table->total_utime = total_utime;
+               table->total_stime = total_stime;
+               table->utime = utime;
+               table->stime = stime;
+               table->last_pid_info = NULL;
+               table->last_pid = 0;
+               table->fg_time = fg_time;
+               table->bg_time = bg_time;
+               table->fg_count = fg_count;
+               table->last_renew_time = 0;
+               table->cpu_info =
+                       g_array_new(FALSE, FALSE, sizeof(struct heart_cpu_info *));
+
+               for (i = 0; i < CPU_ARRAY_MAX; i++) {
+                       struct heart_cpu_info *ci;
+
+                       ret = sscanf(buf + len, "%lu %lu %d %d ", &utime, &stime, &pid, &state);
+                       if (ret <= 0) {
+                               _E("file read fail %s", buf + len);
+                               free(table);
+                               fclose(fp);
+                               return RESOURCED_ERROR_FAIL;
+                       }
+                       ci = malloc(sizeof(struct heart_cpu_info));
+                       if (!ci) {
+                               free(table);
+                               fclose(fp);
+                               return RESOURCED_ERROR_OUT_OF_MEMORY;
+                       }
+                       ci->utime = utime;
+                       ci->stime = stime;
+                       ci->pid = pid;
+                       ci->state = state;
+                       len += heart_cpu_read_length(buf + len, 4);
+                       g_array_append_val(table->cpu_info, ci);
+               }
+
+               ret = pthread_mutex_lock(&heart_cpu_mutex);
+               if (ret) {
+                       _E("pthread_mutex_lock() failed, %d", ret);
+                       g_array_free(table->cpu_info, TRUE);
+                       free(table);
+                       fclose(fp);
+                       return RESOURCED_ERROR_FAIL;
+               }
+               g_hash_table_insert(cache->list, (gpointer)table->appid, (gpointer)table);
+               ret = pthread_mutex_unlock(&heart_cpu_mutex);
+               if (ret) {
+                       _E("pthread_mutex_unlock() failed, %d", ret);
+                       fclose(fp);
+                       return RESOURCED_ERROR_FAIL;
+               }
+       }
+
+       fclose(fp);
+
+       return RESOURCED_ERROR_NONE;
+}
+
+static int heart_cpu_save_to_file(struct heart_cpu_dat_cache *cache)
+{
+       int i, len, ret, array_len;
+       gpointer value;
+       gpointer key;
+       GHashTableIter iter;
+       struct heart_cpu_table *table;
+       FILE *fp;
+       char buf[CPU_DATA_MAX] = {0, };
+
+       if (!cache) {
+               _D("Cache is empty. Do nothing.");
+               return RESOURCED_ERROR_NONE;
+       }
+
+       snprintf(buf, CPU_DATA_MAX, HEART_CPU_DATA_FILE, cache->path);
+       fp = fopen(buf, "w");
+       if (!fp) {
+               _E("%s fopen failed %d", buf, errno);
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       if (!(cache->list)) {
+               _E("empty app list");
+               fclose(fp);
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       if (!g_hash_table_size(cache->list)) {
+               _E("hash table is empty");
+               fclose(fp);
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       ret = pthread_mutex_lock(&heart_cpu_mutex);
+       if (ret) {
+               _E("pthread_mutex_lock() failed, %d", ret);
+               fclose(fp);
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       g_hash_table_iter_init(&iter, cache->list);
+
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               table = (struct heart_cpu_table *)value;
+               array_len = table->cpu_info->len;
+               len = snprintf(buf, CPU_DATA_MAX, "%s %s %lu %lu %lu %lu %lu %lu %d ",
+                               table->appid, table->pkgid,
+                               table->total_utime,
+                               table->total_stime,
+                               table->utime,
+                               table->stime,
+                               table->fg_time,
+                               table->bg_time,
+                               table->fg_count);
+
+               for (i = 0; i < CPU_ARRAY_MAX; i++) {
+                       struct heart_cpu_info *ci;
+                       if (array_len <= i) {
+                               len += snprintf(buf + len, CPU_DATA_MAX - len, "0 0 0 0 ");
+                       } else {
+                               ci = g_array_index(table->cpu_info, struct heart_cpu_info *, i);
+                               if (!ci)
+                                       break;
+                               len += snprintf(buf + len, CPU_DATA_MAX - len, "%lu %lu %d %d ",
+                                               ci->utime,
+                                               ci->stime,
+                                               ci->pid,
+                                               ci->state);
+                       }
+               }
+               snprintf(buf + len, CPU_DATA_MAX - len, "\n");
+               fputs(buf, fp);
+       }
+       ret = pthread_mutex_unlock(&heart_cpu_mutex);
+       if (ret) {
+               _E("pthread_mutex_unlock() failed, %d", ret);
+               fclose(fp);
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       fclose(fp);
+
+       return RESOURCED_ERROR_NONE;
+}
+
+static int heart_cpu_hashtable_renew(GHashTable *hashtable, time_t now)
+{
+       int ret;
+       gpointer value;
+       gpointer key;
+       GHashTableIter iter;
+       struct heart_cpu_table *table;
+
+       if (!hashtable) {
+               _E("empty app list");
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       if (!g_hash_table_size(hashtable)) {
+               _E("hash table is empty");
+               return RESOURCED_ERROR_FAIL;
+       }
+       ret = pthread_mutex_lock(&heart_cpu_mutex);
+       if (ret) {
+               _E("pthread_mutex_lock() failed, %d", ret);
+               return RESOURCED_ERROR_FAIL;
+       }
+       g_hash_table_iter_init(&iter, hashtable);
+
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               table = (struct heart_cpu_table *)value;
+               table->total_utime = 0;
+               table->total_stime = 0;
+               table->last_renew_time = now;
+               table->fg_count = 0;
+               table->fg_time = 0;
+               table->bg_time = 0;
+       }
+       ret = pthread_mutex_unlock(&heart_cpu_mutex);
+       if (ret) {
+               _E("pthread_mutex_unlock() failed, %d", ret);
+               return RESOURCED_ERROR_FAIL;
+       }
+       return RESOURCED_ERROR_NONE;
+}
+
+void heart_cpu_update(struct logging_table_form *data, void *user_data)
+{
+       const char *path;
+       int ret;
+       pid_t pid;
+       uid_t *uid;
+       int state;
+       unsigned long utime, stime;
+       unsigned long utime_diff = 0, stime_diff = 0;
+       time_t curr_time = logging_get_time(CLOCK_BOOTTIME);
+       struct heart_cpu_table *table;
+       struct heart_cpu_info *ci = NULL;
+       struct heart_cpu_dat_cache *cache;
+       GHashTable *cpu_usage_list = NULL;
+
+       cache = (struct heart_cpu_dat_cache*)g_hash_table_lookup(
+                       heart_cpu_app_list, (gpointer)(&(data->uid)));
+       if (!cache) {
+               path = userinfo_find_home_dir((uid_t)data->uid);
+               if (!path) {
+                       _E("uid %d doesn't existed", data->uid);
+                       return;
+               }
+
+               cache = (struct heart_cpu_dat_cache*)malloc(sizeof(struct heart_cpu_dat_cache));
+               if (!cache) {
+                       _E("malloc failed");
+                       return;
+               }
+
+               cache->path = strndup(path, strlen(path));
+               if (!cache->path) {
+                       _E("strndup failed");
+                       free(cache);
+                       return;
+               }
+
+               cache->list = g_hash_table_new_full(
+                               g_str_hash,
+                               g_str_equal,
+                               NULL,
+                               heart_free_value);
+               if (!cache->list) {
+                       _E("g_hash_table_new_full failed");
+                       free(cache->path);
+                       free(cache);
+                       return;
+               }
+
+               uid = malloc(sizeof(uid_t));
+               if (!uid) {
+                       _E("malloc failed");
+                       g_hash_table_unref(cache->list);
+                       free(cache->path);
+                       free(cache);
+                       return;
+               }
+               *uid = (uid_t)data->uid;
+
+               g_hash_table_insert(heart_cpu_app_list, (gpointer)uid, (gpointer)cache);
+       }
+       cpu_usage_list = cache->list;
+
+       _D("%d %s %s %ld %s", data->uid, data->appid, data->pkgid, data->time, data->data);
+       if (sscanf(data->data, "%lu %lu %d %d ", &utime, &stime, &pid, &state) < 0) {
+               _E("sscanf failed");
+               return;
+       }
+
+       ret = pthread_mutex_lock(&heart_cpu_mutex);
+       if (ret) {
+               _E("pthread_mutex_lock() failed, %d", ret);
+               return;
+       }
+
+       /* update */
+       table = g_hash_table_lookup(cpu_usage_list, data->appid);
+       if (table) {
+
+               if (table->last_renew_time > data->time)
+                       goto unlock_exit;
+
+               ci = find_pid_info(table, pid);
+               if (table->last_pid_info && ci) {
+                       utime_diff = utime - ci->utime;
+                       table->utime += utime_diff;
+                       table->total_utime += utime_diff;
+                       stime_diff = stime - ci->stime;
+                       table->stime += stime_diff;
+                       table->total_stime += stime_diff;
+                       ci->utime = utime;
+                       ci->stime = stime;
+                       if (ci->state == BACKG || ci->state == SERVICE) {
+                               table->bg_time += utime_diff + stime_diff;
+                               if (state == FOREG)
+                                       table->fg_count++;
+                       } else
+                               table->fg_time += utime_diff + stime_diff;
+                       ci->state = state;
+               } else {
+                       table->utime += utime;
+                       table->total_utime += utime;
+                       table->stime += stime;
+                       table->total_stime += stime;
+                       if (table->last_pid_info)
+                               heart_cpu_remove_last_pid_info_exited(table);
+                       ci = malloc(sizeof(struct heart_cpu_info));
+                       if (!ci) {
+                               _E("malloc failed");
+                               goto unlock_exit;
+                       }
+                       ci->pid = pid;
+                       ci->utime = utime;
+                       ci->stime = stime;
+                       ci->state = state;
+                       if (ci->state == FOREG)
+                               table->fg_count++;
+                       table->last_pid_info = g_slist_prepend(table->last_pid_info, ci);
+                       table->last_pid = pid;
+               }
+       } else {
+               table = calloc(1, sizeof(struct heart_cpu_table));
+
+               if (!table) {
+                       _E("malloc failed");
+                       goto unlock_exit;
+               }
+
+               if (snprintf(table->appid, MAX_APPID_LENGTH,  "%s", data->appid) < 0) {
+                       free(table);
+                       _E("snprintf failed");
+                       goto unlock_exit;
+               }
+
+               if (snprintf(table->pkgid, MAX_PKGNAME_LENGTH, "%s", data->pkgid) < 0) {
+                       free(table);
+                       _E("snprintf failed");
+                       goto unlock_exit;
+               }
+               table->total_utime = utime;
+               table->total_stime = stime;
+               table->utime = utime;
+               table->stime = stime;
+               table->fg_count = 0;
+               table->fg_time = 0;
+               table->bg_time = 0;
+               if (state == FOREG)
+                       table->fg_count = 1;
+
+               table->cpu_info =
+                       g_array_new(FALSE, FALSE, sizeof(struct heart_cpu_info *));
+               if (!table->cpu_info) {
+                       free(table);
+                       _E("g_array_new failed");
+                       goto unlock_exit;
+               }
+
+               ci = malloc(sizeof(struct heart_cpu_info));
+               if (!ci) {
+                       _E("malloc failed");
+                       free(table);
+                       goto unlock_exit;
+               }
+               ci->pid = pid;
+               ci->utime = utime;
+               ci->stime = stime;
+               ci->state = state;
+               table->last_pid_info = g_slist_prepend(NULL, ci);
+               table->last_pid = pid;
+
+               g_hash_table_insert(cpu_usage_list, (gpointer)table->appid, (gpointer)table);
+       }
+       ret = pthread_mutex_unlock(&heart_cpu_mutex);
+       if (ret) {
+               _E("pthread_mutex_unlock() failed, %d", ret);
+               return;
+       }
+
+       if (cache->last_file_commit_time + HEART_CPU_SAVE_INTERVAL < curr_time) {
+               /* all hash table update and make new array */
+               gpointer value;
+               gpointer key;
+               GHashTableIter iter;
+               struct heart_cpu_table *search;
+               struct heart_cpu_info *ci;
+
+               ret = pthread_mutex_lock(&heart_cpu_mutex);
+               if (ret) {
+                       _E("pthread_mutex_lock() failed, %d", ret);
+                       return;
+               }
+
+               g_hash_table_iter_init(&iter, cpu_usage_list);
+
+               while (g_hash_table_iter_next(&iter, &key, &value)) {
+                       search = (struct heart_cpu_table *)value;
+
+                       ci = malloc(sizeof(struct heart_cpu_info));
+
+                       if (!ci) {
+                               _E("malloc failed");
+                               goto unlock_exit;
+                       }
+                       /* make new array node */
+                       ci->pid = search->last_pid;
+                       ci->utime = search->utime;
+                       ci->stime = search->stime;
+                       search->utime = 0;
+                       search->stime = 0;
+                       /* hashtable sliding : remove last node and make new one */
+                       if (search->cpu_info->len == CPU_ARRAY_MAX)
+                               g_array_remove_index(search->cpu_info, CPU_ARRAY_MAX - 1);
+                       g_array_prepend_val(search->cpu_info, ci);
+               }
+               ret = pthread_mutex_unlock(&heart_cpu_mutex);
+               if (ret) {
+                       _E("pthread_mutex_unlock() failed, %d", ret);
+                       return;
+               }
+               /* rewrite hashtable list file */
+               ret = heart_cpu_save_to_file(cache);
+               if (ret) {
+                       _E("save to file failed");
+                       goto unlock_exit;
+               }
+
+               cache->last_file_commit_time = curr_time;
+       }
+
+       return;
+
+unlock_exit:
+       ret = pthread_mutex_unlock(&heart_cpu_mutex);
+       if (ret) {
+               _E("pthread_mutex_unlock() failed, %d", ret);
+               return;
+       }
+}
+
+struct heart_cpu_data *heart_cpu_get_data(int uid, char *appid, enum heart_data_period period, struct heart_cpu_data *data)
+{
+       int index, i, ret;
+       struct heart_cpu_table *table;
+       GHashTable *hashtable;
+
+       if (!appid) {
+               _E("Wrong arguments!");
+               return NULL;
+       }
+
+       hashtable = heart_cpu_get_user_app_list(uid);
+       if (!hashtable) {
+               _E("Fail to get app list");
+               return NULL;
+       }
+
+       if (!g_hash_table_size(hashtable)) {
+               _D("hash table is empty");
+               return NULL;
+       }
+
+       switch (period) {
+       case DATA_LATEST:
+               index = 0;
+               break;
+       case DATA_3HOUR:
+               index = 3;
+               break;
+       case DATA_6HOUR:
+               index = 6;
+               break;
+       case DATA_12HOUR:
+               index = 12;
+               break;
+       case DATA_1DAY:
+               index = 24;
+               break;
+       default:
+               _E("Wrong message arguments! %d", period);
+               return NULL;
+       }
+
+       ret = pthread_mutex_lock(&heart_cpu_mutex);
+       if (ret) {
+               _E("pthread_mutex_lock() failed, %d", ret);
+               return NULL;
+       }
+
+       table = g_hash_table_lookup(hashtable, (gconstpointer)appid);
+       if (!table) {
+               data = NULL;
+               goto unlock_exit;
+       }
+       if (snprintf(data->appid, MAX_APPID_LENGTH, "%s", table->appid) < 0) {
+               _E("snprintf failed");
+               data = NULL;
+               goto unlock_exit;
+       }
+       if (snprintf(data->pkgid, MAX_PKGNAME_LENGTH, "%s", table->pkgid) < 0) {
+               _E("snprintf failed");
+               data = NULL;
+               goto unlock_exit;
+       }
+       if (period == DATA_LATEST) {
+               data->utime = table->total_utime;
+               data->stime = table->total_stime;
+       } else {
+               data->utime = table->utime;
+               data->stime = table->stime;
+               i = table->cpu_info->len;
+               if (i == 0) {
+                       data = NULL;
+                       goto unlock_exit;
+               }
+               if (i < index)
+                       index = i;
+               for (i = 0; i < index; i++) {
+                       struct heart_cpu_info *cpu_info;
+                       cpu_info =
+                               g_array_index(table->cpu_info, struct heart_cpu_info *, i);
+                       if (!cpu_info)
+                               break;
+                       data->utime += cpu_info->utime;
+                       data->stime += cpu_info->stime;
+               }
+       }
+unlock_exit:
+       ret = pthread_mutex_unlock(&heart_cpu_mutex);
+       if (ret) {
+               _E("pthread_mutex_unlock() failed, %d", ret);
+               return NULL;
+       }
+       return data;
+}
+
+static int compare_usage(const struct heart_app_usage *lau_a,
+           const struct heart_app_usage *lau_b)
+{
+       if (lau_a->point != lau_b->point)
+               return (lau_b->point - lau_a->point);
+
+       return 0;
+}
+
+/*
+ * Calculate application usage using frequency and time
+ */
+static double heart_cpu_get_point(int freq, int time)
+{
+       double weightForFrequence = 3;
+       double point = 0;
+       point = sqrt(time + (freq*weightForFrequence));
+       return point;
+}
+
+int heart_cpu_get_appusage_list(int uid, GHashTable *lists, int top)
+{
+       int index = top, i, ret;
+       gpointer value;
+       gpointer key;
+       GHashTableIter h_iter;
+       struct heart_cpu_table *table;
+       struct heart_app_usage lau;
+       GArray *app_lists = NULL;
+       GHashTable *hashtable;
+
+       hashtable = heart_cpu_get_user_app_list(uid);
+       if (!hashtable) {
+               _E("Fail to get app list");
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       if (!g_hash_table_size(hashtable)) {
+               _E("hash table is empty");
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       app_lists = g_array_new(false, false, sizeof(struct heart_app_usage));
+       ret = pthread_mutex_lock(&heart_cpu_mutex);
+       if (ret) {
+               _E("pthread_mutex_lock() failed, %d", ret);
+               g_array_free(app_lists, true);
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       g_hash_table_iter_init(&h_iter, hashtable);
+
+       while (g_hash_table_iter_next(&h_iter, &key, &value)) {
+
+               table = (struct heart_cpu_table *)value;
+               if (!table->fg_count)
+                       continue;
+
+               lau.appid = table->appid;
+               lau.pkgid = table->pkgid;
+               lau.fg_count = table->fg_count;
+               lau.used_time = table->fg_time;
+               lau.point = (int)heart_cpu_get_point(lau.fg_count, lau.used_time);
+               /*
+                * make all application lists with weighted point value excepting service application
+                */
+               g_array_append_val(app_lists, lau);
+       }
+       ret = pthread_mutex_unlock(&heart_cpu_mutex);
+       if (ret) {
+               _E("pthread_mutex_unlock() failed, %d", ret);
+               g_array_free(app_lists, true);
+               return RESOURCED_ERROR_FAIL;
+       }
+       if (app_lists->len < top) {
+               _I("too small data for making app usage lists");
+               g_array_free(app_lists, true);
+               return RESOURCED_ERROR_NO_DATA;
+       }
+
+       g_array_sort(app_lists, (GCompareFunc)compare_usage);
+
+       if (!top)
+               index = app_lists->len;
+
+       /*
+        * replace application usage lists with sorted usage arrays
+        */
+       g_hash_table_remove_all(lists);
+       for (i = 0; i < index; i++) {
+               struct heart_app_usage *usage = &g_array_index(app_lists, struct heart_app_usage, i);
+               _D("appid : %s, point : %d", usage->appid, usage->point);
+               g_hash_table_insert(lists, g_strndup(usage->appid, strlen(usage->appid)), GINT_TO_POINTER(1));
+       }
+       g_array_free(app_lists, true);
+       return RESOURCED_ERROR_NONE;
+}
+
+static int heart_cpu_update_appid(void *data)
+{
+       int pid;
+       char old_appid[MAX_APPID_LENGTH], new_appid[MAX_APPID_LENGTH];
+       char *info;
+
+       if (!data) {
+               _E("Invalid parameter");
+               return RESOURCED_ERROR_INVALID_PARAMETER;
+       }
+
+       info = (char*)data;
+       if (sscanf(info, "%d "STR_FS(MAX_APPID_LENGTH_M1)" "STR_FS(MAX_APPID_LENGTH_M1),
+                       &pid, old_appid, new_appid) < 0) {
+               _E("sscanf failed, %m");
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       return logging_modify_appid(CPU_NAME, old_appid, new_appid, pid);
+}
+
+static void dbus_heart_get_cpu_data(GDBusMethodInvocation *invocation, GVariant *params)
+{
+       int period = -1;
+       char *appid = NULL;
+       struct heart_cpu_data *data = NULL;
+
+       int uid = -1;
+
+       do_expr_unless_g_variant_get_typechecked(goto failure, params, "(i&si)", &uid, &appid, &period);
+       if (uid < 0 || !appid || period < 0) {
+               _E("Wrong message arguments!");
+               goto failure;
+       }
+
+       data = malloc(sizeof(struct heart_cpu_data));
+       if (!data) {
+               _E("malloc failed");
+               goto failure;
+       }
+
+       if (heart_cpu_get_data(uid, appid, period, data) == NULL)
+               goto failure;
+
+       g_dbus_method_invocation_return_value(invocation, g_variant_new("(ii)",
+                               data->utime, data->stime));
+       free(data);
+       return;
+
+failure:
+       if (data)
+               free(data);
+       D_BUS_REPLY_ERR(invocation);
+}
+
+static void dbus_heart_get_cpu_data_list(GDBusMethodInvocation *invocation, GVariant *params)
+{
+       int period = -1, index, i, ret;
+       gpointer value;
+       gpointer key;
+       GHashTableIter h_iter;
+       struct heart_cpu_table *table;
+
+       char *appid;
+       unsigned long utime, stime, ftime, total;
+
+       int uid = -1;
+       GHashTable *hashtable;
+
+       GVariantBuilder builder, *sub_builder;
+
+       utime = stime = ftime = total = 0;
+
+       do_expr_unless_g_variant_get_typechecked(goto failure, params, "(ii)", &uid, &period);
+       if (uid < 0 || period < 0) {
+               _E("Wrong message arguments!");
+               goto failure;
+       }
+
+       heart_cpu_update_app_list(NULL);
+
+       logging_save_to_storage(true);
+       /* update data list from db */
+       logging_update(true);
+
+       switch (period) {
+       case DATA_LATEST:
+               index = 0;
+               break;
+       case DATA_3HOUR:
+               index = 3;
+               break;
+       case DATA_6HOUR:
+               index = 6;
+               break;
+       case DATA_12HOUR:
+               index = 12;
+               break;
+       case DATA_1DAY:
+               index = 24;
+               break;
+       default:
+               _E("Wrong message arguments! %d", period);
+               goto failure;
+       }
+
+       hashtable = heart_cpu_get_user_app_list(uid);
+       if (!hashtable) {
+               _E("Fail to get app list");
+               goto failure;
+       }
+
+       if (!g_hash_table_size(hashtable)) {
+               _E("hash table is empty");
+               goto failure;
+       }
+
+       ret = pthread_mutex_lock(&heart_cpu_mutex);
+       if (ret) {
+               _E("pthread_mutex_lock() failed, %d", ret);
+               goto failure;
+       }
+
+       g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
+       sub_builder = g_variant_builder_new(G_VARIANT_TYPE("a(sii)"));
+
+       g_hash_table_iter_init(&h_iter, hashtable);
+       while (g_hash_table_iter_next(&h_iter, &key, &value)) {
+               table = (struct heart_cpu_table *)value;
+               if (!table)
+                       break;
+               if (period == DATA_LATEST) {
+                       utime = table->total_utime;
+                       stime = table->total_stime;
+               } else {
+                       utime = table->utime;
+                       stime = table->stime;
+                       i =  table->cpu_info->len;
+                       if (i < index)
+                               index = i;
+                       for (i = 0; i < index; i++) {
+                               struct heart_cpu_info *ci;
+                               ci = g_array_index(table->cpu_info, struct heart_cpu_info *, i);
+                               if (!ci)
+                                       break;
+                               utime += ci->utime;
+                               stime += ci->stime;
+                       }
+               }
+               ftime = table->fg_time;
+               total = utime + stime;
+               if (total == 0)
+                       continue;
+               appid = table->appid;
+
+               g_variant_builder_add(sub_builder, "(sii)", appid, total, ftime);
+       }
+
+       ret = pthread_mutex_unlock(&heart_cpu_mutex);
+       if (ret) {
+               _E("pthread_mutex_unlock() failed, %d", ret);
+               g_variant_builder_unref(sub_builder);
+               goto failure;
+       }
+
+       g_variant_builder_add_value(&builder, g_variant_new("a(sii)", sub_builder));
+       g_variant_builder_unref(sub_builder);
+
+       g_dbus_method_invocation_return_value(invocation, g_variant_builder_end(&builder));
+       return;
+
+failure:
+       D_BUS_REPLY_ERR(invocation);
+}
+
+static void dbus_heart_reset_cpu_data(GDBusMethodInvocation *invocation, GVariant *params)
+{
+       int ret = -1;
+
+       GHashTableIter iter_table;
+       gpointer key, value;
+
+       g_hash_table_iter_init(&iter_table, heart_cpu_app_list);
+       while (g_hash_table_iter_next(&iter_table, &key, &value))
+               ret = heart_cpu_hashtable_renew(((struct heart_cpu_dat_cache*)value)->list, time(NULL));
+
+
+       g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", ret));
+}
+
+static void dbus_heart_update_cpu_data(GDBusMethodInvocation *invocation, GVariant *params)
+{
+       heart_cpu_update_app_list(NULL);
+
+       g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", 0));
+}
+
+static void dbus_heart_sync_cpu_data(GDBusMethodInvocation *invocation, GVariant *params)
+{
+       int ret = 0;
+
+       heart_cpu_update_app_list(NULL);
+
+       ret = logging_sync(invocation);
+       if (ret)
+               g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", ret));
+}
+
+static void dbus_heart_save_to_file(GDBusMethodInvocation *invocation, GVariant *params)
+{
+       int ret;
+
+       GHashTableIter iter_table;
+       gpointer key, value;
+       struct heart_cpu_dat_cache *cache;
+
+       g_hash_table_iter_init(&iter_table, heart_cpu_app_list);
+       while (g_hash_table_iter_next(&iter_table, &key, &value)) {
+               cache = (struct heart_cpu_dat_cache*)value;
+               ret = heart_cpu_save_to_file(cache);
+               if (ret) {
+                       _E("save to file failed");
+                       D_BUS_REPLY_ERR(invocation);
+                       return;
+               }
+               cache->last_file_commit_time = logging_get_time(CLOCK_BOOTTIME);
+       }
+
+       g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", ret));
+}
+
+static const char dbus_methods_xml[] =
+"              <method name='GetCpuData'>"
+"                      <arg type='i' name='Uid' direction='in'/>"
+"                      <arg type='s' name='Appid' direction='in'/>"
+"                      <arg type='i' name='Period' direction='in'/>"
+"                      <arg type='i' name='Utime' direction='out'/>"
+"                      <arg type='i' name='Stime' direction='out'/>"
+"              </method>"
+"              <method name='GetCpuDataList'>"
+"                      <arg type='i' name='Uid' direction='in'/>"
+"                      <arg type='i' name='Period' direction='in'/>"
+"                      <arg type='a(sii)' name='CpuTimePerApp' direction='out'/>"
+"              </method>"
+"              <method name='ResetCpuData'>"
+"                      <arg type='i' name='ZeroOnSuccess' direction='out'/>"
+"              </method>"
+"              <method name='UpdateCpuData'>"
+"                      <arg type='i' name='Zero' direction='out'/>"
+"              </method>"
+"              <method name='SyncCpuData'>"
+"                      <arg type='i' name='ZeroOnSuccess' direction='out'/>"
+"              </method>"
+"              <method name='SaveCpuData'>"
+"                      <arg type='i' name='ZeroOnSuccess' direction='out'/>"
+"              </method>";
+
+static struct d_bus_method dbus_methods[] = {
+       { "GetCpuData",     dbus_heart_get_cpu_data },
+       { "GetCpuDataList", dbus_heart_get_cpu_data_list },
+       { "ResetCpuData",   dbus_heart_reset_cpu_data },
+       { "UpdateCpuData",  dbus_heart_update_cpu_data },
+       { "SyncCpuData",    dbus_heart_sync_cpu_data },
+       { "SaveCpuData",    dbus_heart_save_to_file },
+};
+
+static int heart_cpu_reset(void *data)
+{
+       GHashTableIter iter_table;
+       gpointer key, value;
+       int ret = RESOURCED_ERROR_FAIL;
+
+       g_hash_table_iter_init(&iter_table, heart_cpu_app_list);
+       while (g_hash_table_iter_next(&iter_table, &key, &value))
+               ret = heart_cpu_hashtable_renew(((struct heart_cpu_dat_cache*)value)->list, time(NULL));
+
+       return ret;
+}
+
+static int heart_cpu_init(void *data)
+{
+       const GArray *user_list = NULL;
+       int ret;
+       uid_t *uid;
+       struct heart_cpu_dat_cache *cache;
+
+       ret = logging_module_init(CPU_NAME, ONE_DAY, TEN_MINUTE, heart_cpu_update, TEN_MINUTE, USER_DEFAULT);
+       if (ret != RESOURCED_ERROR_NONE) {
+               _E("logging module init failed");
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       user_list = userinfo_get_list();
+       if (!user_list) {
+               _E("Fail to get user table");
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       if (!heart_cpu_app_list) {
+               heart_cpu_app_list = g_hash_table_new_full(
+                               g_int_hash,
+                               g_int_equal,
+                               heart_cpu_free_uid,
+                               heart_cpu_free_dat_cache);
+
+               userinfo_for_each(elem, user_list) {
+                       cache = (struct heart_cpu_dat_cache*)malloc(sizeof(struct heart_cpu_dat_cache));
+                       assert(cache);
+
+                       cache->path = strndup(elem->home_dir, strlen(elem->home_dir));
+                       cache->list = g_hash_table_new_full(
+                                       g_str_hash,
+                                       g_str_equal,
+                                       NULL,
+                                       heart_free_value);
+
+                       ret = heart_cpu_read_from_file(cache);
+                       assert(ret == RESOURCED_ERROR_NONE);
+
+                       cache->last_file_commit_time = logging_get_time(CLOCK_BOOTTIME);
+
+                       uid = malloc(sizeof(uid_t));
+                       assert(uid);
+
+                       *uid = elem->uid;
+                       g_hash_table_insert(heart_cpu_app_list, (gpointer)uid, (gpointer)cache);
+               }
+       }
+
+       heart_dbus_declare_methods(dbus_methods_xml, dbus_methods, ARRAY_SIZE(dbus_methods));
+
+       register_notifier(RESOURCED_NOTIFIER_SERVICE_LAUNCH, heart_cpu_service_launch);
+       register_notifier(RESOURCED_NOTIFIER_APP_FOREGRD, heart_cpu_foreground_state);
+       register_notifier(RESOURCED_NOTIFIER_APP_BACKGRD, heart_cpu_background_state);
+       register_notifier(RESOURCED_NOTIFIER_APP_GROUP, heart_cpu_update_appid);
+       register_notifier(RESOURCED_NOTIFIER_DATA_UPDATE, heart_cpu_update_app_list);
+       register_notifier(RESOURCED_NOTIFIER_DATA_RESET, heart_cpu_reset);
+
+       heart_cpu_get_appusage_list_func = heart_cpu_get_appusage_list;
+
+       _D("heart cpu init finished");
+       return RESOURCED_ERROR_NONE;
+}
+
+static int heart_cpu_exit(void *data)
+{
+       GHashTableIter iter;
+       gpointer key, value;
+       struct heart_cpu_dat_cache *cache;
+
+       unregister_notifier(RESOURCED_NOTIFIER_SERVICE_LAUNCH, heart_cpu_service_launch);
+       unregister_notifier(RESOURCED_NOTIFIER_APP_FOREGRD, heart_cpu_foreground_state);
+       unregister_notifier(RESOURCED_NOTIFIER_APP_BACKGRD, heart_cpu_background_state);
+       unregister_notifier(RESOURCED_NOTIFIER_APP_GROUP, heart_cpu_update_appid);
+       unregister_notifier(RESOURCED_NOTIFIER_DATA_UPDATE, heart_cpu_update_app_list);
+       unregister_notifier(RESOURCED_NOTIFIER_DATA_RESET, heart_cpu_reset);
+
+       if (heart_cpu_app_list) {
+               g_hash_table_iter_init(&iter, heart_cpu_app_list);
+               while (g_hash_table_iter_next(&iter, &key, &value)) {
+                       cache = (struct heart_cpu_dat_cache*)value;
+                       heart_cpu_save_to_file(cache);
+               }
+               g_hash_table_destroy(heart_cpu_app_list);
+       }
+
+       logging_module_exit();
+
+       heart_cpu_get_appusage_list_func = NULL;
+
+       _D("heart cpu exit");
+       return RESOURCED_ERROR_NONE;
+}
+
+static int heart_cpu_dump(FILE *fp, int mode, void *data)
+{
+       time_t starttime;
+       char timestr[80];
+       struct tm loc_tm;
+       static GHashTable *cpu_usage_list;
+       gpointer value;
+       gpointer key;
+       GHashTableIter h_iter;
+       struct heart_cpu_table *table;
+
+       starttime = time(NULL);
+
+       starttime -= mode;
+       localtime_r(&starttime, &loc_tm);
+       /* print timestamp */
+       strftime(timestr, sizeof(timestr),
+                       "%Y-%m-%d %H:%M:%S%z", &loc_tm);
+
+       cpu_usage_list = g_hash_table_new_full(
+                       g_str_hash,
+                       g_str_equal,
+                       NULL,
+                       free);
+
+
+       logging_read_foreach(CPU_NAME, NULL, NULL, starttime, 0,
+                       heart_cpu_update, cpu_usage_list);
+
+       if (!g_hash_table_size(cpu_usage_list)) {
+               _E("hash table is empty");
+               return 0;
+       }
+
+       LOG_DUMP(fp, "[CPU USAGE LISTS] since %s\n", timestr);
+       LOG_DUMP(fp, "appid pkgid total fg_count fg_time\n");
+       g_hash_table_iter_init(&h_iter, cpu_usage_list);
+
+       while (g_hash_table_iter_next(&h_iter, &key, &value)) {
+
+               table = (struct heart_cpu_table *)value;
+               if (!table)
+                       break;
+               LOG_DUMP(fp, "%s %s %ld %d %ld\n", table->appid, table->pkgid,
+                               table->total_utime + table->total_stime,
+                               table->fg_count, table->fg_time);
+       }
+       fflush(fp);
+       g_hash_table_destroy(cpu_usage_list);
+
+       return RESOURCED_ERROR_NONE;
+}
+
+static const struct heart_module_ops heart_cpu_ops = {
+       .name           = "CPU",
+       .init           = heart_cpu_init,
+       .dump               = heart_cpu_dump,
+       .exit           = heart_cpu_exit,
+};
+HEART_MODULE_REGISTER(&heart_cpu_ops)
diff --git a/src/resource-monitor/heart-memory.c b/src/resource-monitor/heart-memory.c
new file mode 100644 (file)
index 0000000..3aca2c1
--- /dev/null
@@ -0,0 +1,1411 @@
+/*
+ * resourced
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @file heart-memory.c
+ *
+ * @desc heart memory module
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <glib.h>
+
+#include "resourced.h"
+#include "trace.h"
+#include "module.h"
+#include "macro.h"
+#include "notifier.h"
+#include "proc-common.h"
+#include "heart.h"
+#include "logging.h"
+#include "heart-common.h"
+#include "dbus-handler.h"
+#include "procfs.h"
+#include "util.h"
+
+#include <sqlite3.h>
+#include <time.h>
+
+struct heart_memory_info {
+       unsigned int max_rss;
+       unsigned int avg_rss;
+};
+
+struct heart_memory_table {
+       char appid[MAX_APPID_LENGTH];
+       char pkgid[MAX_PKGNAME_LENGTH];
+       unsigned int total_rss;
+       unsigned int max_rss;
+       unsigned int latest_rss;
+       unsigned int count;
+       int renew;
+       GArray *memory_info;
+};
+
+static GHashTable *heart_memory_app_list;
+static pthread_mutex_t heart_memory_mutex = PTHREAD_MUTEX_INITIALIZER;
+static time_t last_file_update_time;
+static GSource *heart_memory_update_timer = NULL;
+
+struct heart_memory_table *heart_memory_find_info(GHashTable *hashtable, char *appid)
+{
+       int ret;
+       struct heart_memory_table *table;
+
+       if (!hashtable) {
+               _E("hashtable is NULL");
+               return NULL;
+       }
+
+       ret = pthread_mutex_lock(&heart_memory_mutex);
+       if (ret) {
+               _E("pthread_mutex_lock() failed, %d", ret);
+               return NULL;
+       }
+
+       table = g_hash_table_lookup(hashtable, (gconstpointer)appid);
+
+       ret = pthread_mutex_unlock(&heart_memory_mutex);
+       if (ret) {
+               _E("pthread_mutex_unlock() failed, %d", ret);
+               return NULL;
+       }
+
+       return table;
+}
+
+static void heart_memory_free_value(gpointer value)
+{
+       struct heart_memory_table * table = (struct heart_memory_table *)value;
+
+       if (table)
+               free(table);
+}
+
+static int heart_memory_read_length(char *buf, int count)
+{
+       int i, find = 0;
+       int len = strlen(buf);
+
+       for (i = 0; i < len; i++) {
+               if (buf[i] == ' ')
+                       find++;
+
+               if (find == count)
+                       return i+1;
+       }
+
+       return RESOURCED_ERROR_FAIL;
+}
+
+static int heart_memory_read_from_file(GHashTable *hashtable, char *filename)
+{
+       int i, len, ret, result;
+       unsigned int total_rss, max_rss, avg_rss;
+       unsigned int count;
+       FILE *fp;
+       struct heart_memory_table *table;
+       char appid[MAX_APPID_LENGTH] = {0, };
+       char pkgid[MAX_PKGNAME_LENGTH] = {0, };
+       char buf[MEM_DATA_MAX] = {0, };
+
+       fp = fopen(filename, "r");
+
+       if (!fp) {
+               _E("%s fopen failed %d", filename, errno);
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       while (fgets(buf, MEM_DATA_MAX, fp)) {
+               table = malloc(sizeof(struct heart_memory_table));
+
+               if (!table) {
+                       _E("malloc failed");
+                       fclose(fp);
+                       return RESOURCED_ERROR_OUT_OF_MEMORY;
+               }
+
+               /* make return values */
+               result = sscanf(buf, STR_FS(MAX_APPID_LENGTH_M1)" "STR_FS(MAX_PKGNAME_LENGTH_M1)" %u %u %u ",
+                               appid, pkgid, &total_rss, &max_rss, &count);
+
+               if (result < 0) {
+                       _E("sscanf failed");
+                       free(table);
+                       fclose(fp);
+                       return RESOURCED_ERROR_FAIL;
+               }
+
+               if (snprintf(table->appid, MAX_APPID_LENGTH, "%s", appid) < 0) {
+                       _E("snprintf failed");
+                       free(table);
+                       fclose(fp);
+                       return RESOURCED_ERROR_OUT_OF_MEMORY;
+               }
+
+               if (snprintf(table->pkgid, MAX_PKGNAME_LENGTH, "%s", pkgid) < 0) {
+                       _E("snprintf failed");
+                       free(table);
+                       fclose(fp);
+                       return RESOURCED_ERROR_OUT_OF_MEMORY;
+               }
+
+               len = heart_memory_read_length(buf, 7);
+
+               if (len < 0) {
+                       _E("7 space read length failed %s", buf);
+                       free(table);
+                       fclose(fp);
+                       return RESOURCED_ERROR_FAIL;
+               }
+
+               table->total_rss = total_rss;
+               table->max_rss = max_rss;
+               table->latest_rss = 0;
+               table->count = count;
+               table->memory_info =
+                       g_array_new(false, false, sizeof(struct heart_memory_info *));
+
+               for (i = 0; i < MEM_ARRAY_MAX; i++) {
+                       struct heart_memory_info *mi;
+
+                       result = sscanf(buf + len, "%u %u ",
+                                       &max_rss, &avg_rss);
+
+                       if (result <= 0) {
+                               _E("file read fail %s", buf + len);
+                               g_array_free(table->memory_info, true);
+                               free(table);
+                               fclose(fp);
+                               return RESOURCED_ERROR_FAIL;
+                       }
+
+                       mi = malloc(sizeof(struct heart_memory_info));
+
+                       if (!mi) {
+                               _E("malloc failed");
+                               g_array_free(table->memory_info, true);
+                               free(table);
+                               fclose(fp);
+                               return RESOURCED_ERROR_OUT_OF_MEMORY;
+                       }
+
+                       mi->max_rss = max_rss;
+                       mi->avg_rss = avg_rss;
+
+                       len += heart_memory_read_length(buf + len, 4);
+
+                       g_array_append_val(table->memory_info, mi);
+               }
+
+               ret = pthread_mutex_lock(&heart_memory_mutex);
+               if (ret) {
+                       _E("pthread_mutex_lock() failed, %d", ret);
+                       g_array_free(table->memory_info, true);
+                       free(table);
+                       fclose(fp);
+                       return RESOURCED_ERROR_FAIL;
+               }
+
+               g_hash_table_insert(hashtable, (gpointer)table->appid, (gpointer)table);
+
+               ret = pthread_mutex_unlock(&heart_memory_mutex);
+               if (ret) {
+                       _E("pthread_mutex_unlock() failed, %d", ret);
+                       fclose(fp);
+                       return RESOURCED_ERROR_FAIL;
+               }
+       }
+
+       fclose(fp);
+
+       return RESOURCED_ERROR_NONE;
+}
+
+static int heart_memory_save_to_file(GHashTable *hashtable, char *filename)
+{
+       int i, len, ret, array_len;
+       gpointer value;
+       gpointer key;
+       GHashTableIter iter;
+       struct heart_memory_table *table;
+       FILE *fp;
+       char buf[MEM_DATA_MAX] = {0, };
+
+       fp = fopen(filename, "w");
+       if (!fp) {
+               _E("%s fopen failed %d", filename, errno);
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       ret = pthread_mutex_lock(&heart_memory_mutex);
+       if (ret) {
+               _E("pthread_mutex_lock() failed, %d", ret);
+               fclose(fp);
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       g_hash_table_iter_init(&iter, hashtable);
+
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               table = (struct heart_memory_table *)value;
+
+               len = snprintf(buf, MEM_DATA_MAX, "%s %s %u %u %u ",
+                               table->appid, table->pkgid,
+                               table->total_rss, table->max_rss,
+                               table->count);
+
+               array_len = table->memory_info->len;
+
+               for (i = 0; i < MEM_ARRAY_MAX; i++) {
+                       struct heart_memory_info *mi;
+
+                       if (array_len <= i)
+                               len += snprintf(buf + len, MEM_DATA_MAX - len, "0 0 0 0 ");
+                       else {
+                               mi = g_array_index(table->memory_info, struct heart_memory_info *, i);
+
+                               len += snprintf(buf + len, MEM_DATA_MAX - len, "%u %u ",
+                                               mi->max_rss, mi->avg_rss);
+                       }
+               }
+
+               snprintf(buf + len, MEM_DATA_MAX - len, "%c\n", MEM_FILE_SEPERATOR);
+
+               fputs(buf, fp);
+       }
+
+       ret = pthread_mutex_unlock(&heart_memory_mutex);
+       if (ret) {
+               _E("pthread_mutex_unlock() failed, %d", ret);
+               fclose(fp);
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       fclose(fp);
+
+       return RESOURCED_ERROR_NONE;
+}
+
+void heart_memory_fill_array(struct logging_table_form *data, void *user_data)
+{
+       int i;
+       unsigned int rss;
+       struct heart_memory_data *md = NULL;
+       GArray *send = NULL;
+
+       _E("data : %s %s %d %s", data->appid, data->pkgid, (int)data->time, data->data);
+       send = (GArray *)user_data;
+
+       for (i = 0; i < send->len; i++) {
+               struct heart_memory_data *loop;
+               loop = g_array_index(send, struct heart_memory_data *, i);
+
+               if (!strncmp(loop->appid, data->appid, strlen(data->appid)+1)) {
+                       md = loop;
+                       break;
+               }
+       }
+
+       if (sscanf(data->data, "%u", &rss) < 0) {
+               _E("sscanf failed");
+               return;
+       }
+
+       if (!md) {
+               md = malloc(sizeof(struct heart_memory_data));
+
+               if (!md) {
+                       _E("malloc failed");
+                       return;
+               }
+
+               if (snprintf(md->appid, MAX_APPID_LENGTH, "%s", data->appid) < 0) {
+                       _E("snprintf failed");
+                       free(md);
+                       return;
+               }
+
+               if (snprintf(md->pkgid, MAX_PKGNAME_LENGTH, "%s", data->pkgid) < 0) {
+                       _E("snprintf failed");
+                       free(md);
+                       return;
+               }
+
+               md->max_rss = rss;
+               md->avg_rss = rss;
+
+               g_array_append_val(send, md);
+       } else {
+               if (md->max_rss < rss)
+                       md->max_rss = rss;
+
+               md->avg_rss = (md->avg_rss + rss) / 2;
+       }
+}
+
+int logging_memory_get_foreach(GArray *arrays, enum heart_data_period period)
+{
+       int ret;
+       time_t curr_time = time(NULL);
+
+       switch (period) {
+       case DATA_LATEST:
+               break;
+       case DATA_3HOUR:
+               curr_time -= 10800;
+               break;
+       case DATA_6HOUR:
+               curr_time -= 21600;
+               break;
+       case DATA_12HOUR:
+               curr_time -= 43200;
+               break;
+       case DATA_1DAY:
+               curr_time -= 86400;
+               break;
+       default:
+               _E("Wrong message arguments! %d", period);
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       ret = logging_read_foreach(MEM_NAME, NULL, NULL, curr_time, 0, heart_memory_fill_array, arrays);
+
+       if (ret) {
+               _E("failed logging_read_foreach");
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       return RESOURCED_ERROR_NONE;
+}
+
+int heart_memory_get_query(GArray *arrays, enum heart_data_period period)
+{
+       int count, result;
+       time_t curr_time = time(NULL);
+       sqlite3 *heart_db = NULL;
+       sqlite3_stmt *stmt = NULL;
+       gpointer value;
+       gpointer key;
+       char *data;
+       unsigned int rss;
+       GHashTableIter h_iter;
+       struct heart_memory_data *md;
+       struct heart_memory_table *table;
+       char buf[MEM_DATA_MAX] = {0, };
+
+       switch (period) {
+       case DATA_LATEST:
+               break;
+       case DATA_3HOUR:
+               curr_time -= 10800;
+               break;
+       case DATA_6HOUR:
+               curr_time -= 21600;
+               break;
+       case DATA_12HOUR:
+               curr_time -= 43200;
+               break;
+       case DATA_1DAY:
+               curr_time -= 86400;
+               break;
+       default:
+               _E("Wrong message arguments! %d", period);
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       if (logging_get_default_db(MEM_NAME, &heart_db) != RESOURCED_ERROR_NONE) {
+               _E("Fail to get DB path");
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       g_hash_table_iter_init(&h_iter, heart_memory_app_list);
+
+       while (g_hash_table_iter_next(&h_iter, &key, &value)) {
+               table = (struct heart_memory_table *)value;
+
+               md = malloc(sizeof(struct heart_memory_data));
+
+               if (!md) {
+                       _E("malloc failed");
+                       sqlite3_finalize(stmt);
+                       return RESOURCED_ERROR_OUT_OF_MEMORY;
+               }
+
+               if (snprintf(md->appid, MAX_APPID_LENGTH, "%s", table->appid) < 0) {
+                       _E("snprintf failed");
+                       free(md);
+                       sqlite3_finalize(stmt);
+                       return RESOURCED_ERROR_OUT_OF_MEMORY;
+               }
+
+               if (snprintf(md->pkgid, MAX_PKGNAME_LENGTH,  "%s", table->pkgid) < 0) {
+                       _E("asprintf failed");
+                       free(md);
+                       sqlite3_finalize(stmt);
+                       return RESOURCED_ERROR_OUT_OF_MEMORY;
+               }
+
+               count = 0;
+               md->max_rss = 0;
+               md->avg_rss = 0;
+
+               snprintf(buf, MEM_DATA_MAX, "select * from memory where appid = \'%s\' AND time > %d",
+                               table->appid, (int)curr_time);
+
+               /* search from db */
+               if (sqlite3_prepare_v2(heart_db, buf, -1, &stmt, NULL) != SQLITE_OK) {
+                       _E("select failed");
+                       free(md);
+                       sqlite3_finalize(stmt);
+                       return RESOURCED_ERROR_DB_FAILED;
+               }
+
+               do {
+                       result = sqlite3_step(stmt);
+                       switch (result) {
+                       case SQLITE_ROW:
+                               data = (char *)sqlite3_column_text(stmt, 3);
+
+                               if (sscanf(data, "%u", &rss) < 0) {
+                                       _E("sscanf failed");
+                                       free(md);
+                                       sqlite3_finalize(stmt);
+                                       return RESOURCED_ERROR_DB_FAILED;
+                               }
+
+                               if (md->max_rss < rss)
+                                       md->max_rss = rss;
+
+                               md->avg_rss += rss;
+                               count++;
+                               break;
+                       case SQLITE_DONE:
+                               break;
+                       case SQLITE_ERROR:
+                               _E("select %s table failed %s",
+                                               MEM_NAME, sqlite3_errmsg(heart_db));
+                               /* FALLTHROUGH */
+                       default:
+                               free(md);
+                               sqlite3_finalize(stmt);
+                               return RESOURCED_ERROR_DB_FAILED;
+                       }
+               } while (result == SQLITE_ROW);
+               if (count)
+                       md->avg_rss /= count;
+
+               g_array_append_val(arrays, md);
+       }
+
+       sqlite3_finalize(stmt);
+
+       return RESOURCED_ERROR_NONE;
+}
+
+struct heart_memory_data *heart_memory_get_data(char *appid, enum heart_data_period period)
+{
+       int index, i, ret, count, time;
+       unsigned int max_rss = 0, avg_rss = 0, total_rss = 0;
+       struct heart_memory_table *table;
+       struct heart_memory_data *md;
+
+       if (!heart_memory_app_list)
+               return NULL;
+
+       if (!appid) {
+               _E("Wrong message arguments!");
+               return NULL;
+       }
+
+       switch (period) {
+       case DATA_LATEST:
+               index = 0;
+               break;
+       case DATA_3HOUR:
+               index = 3;
+               break;
+       case DATA_6HOUR:
+               index = 6;
+               break;
+       case DATA_12HOUR:
+               index = 12;
+               break;
+       case DATA_1DAY:
+               index = 24;
+               break;
+       default:
+               _E("Wrong message arguments! %d", period);
+               return NULL;
+       }
+
+       /* read from hash and make reply hash */
+       /* loop in file read and make reply */
+       ret = pthread_mutex_lock(&heart_memory_mutex);
+       if (ret) {
+               _E("pthread_mutex_lock() failed, %d", ret);
+               return NULL;
+       }
+
+       table = g_hash_table_lookup(heart_memory_app_list, (gconstpointer)appid);
+       if (!table)
+               goto unlock_exit;
+       md = malloc(sizeof(struct heart_memory_data));
+       if (!md) {
+               _E("malloc failed");
+               goto unlock_exit;
+       }
+
+       if (snprintf(md->appid, MAX_APPID_LENGTH, "%s", table->appid) < 0) {
+               _E("snprintf failed");
+               free(md);
+               goto unlock_exit;
+       }
+
+       if (snprintf(md->pkgid, MAX_PKGNAME_LENGTH, "%s", table->pkgid) < 0) {
+               _E("snprintf failed");
+               free(md);
+               goto unlock_exit;
+       }
+
+       count = table->count;
+       total_rss = table->total_rss;
+       max_rss = table->max_rss;
+       avg_rss = total_rss / count;
+       time = 1;
+
+       if (period != DATA_LATEST) {
+               i = table->memory_info->len;
+
+               if (i < index)
+                       index = i;
+
+               for (i = 0; i < index; i++) {
+                       struct heart_memory_info *mi;
+
+                       mi = g_array_index(table->memory_info, struct heart_memory_info *, i);
+
+                       if (mi->max_rss || mi->avg_rss)
+                               time++;
+
+                       if (max_rss < mi->max_rss)
+                               max_rss = mi->max_rss;
+
+                       avg_rss += mi->avg_rss;
+               }
+
+               if (time)
+                       avg_rss /= time;
+
+       }
+
+       md->max_rss = max_rss;
+       md->avg_rss = avg_rss;
+
+       ret = pthread_mutex_unlock(&heart_memory_mutex);
+       if (ret) {
+               _E("pthread_mutex_unlock() failed, %d", ret);
+               free(md);
+               return NULL;
+       }
+       return md;
+
+unlock_exit:
+       ret = pthread_mutex_unlock(&heart_memory_mutex);
+       if (ret) {
+               _E("pthread_mutex_unlock() failed, %d", ret);
+               return NULL;
+       }
+       return NULL;
+}
+
+int heart_memory_get_latest_data(char *appid, unsigned int *rss)
+{
+       int ret;
+       char *data;
+       struct heart_memory_table *table;
+
+       if (!appid) {
+               _E("Wrong message arguments!");
+               return RESOURCED_ERROR_INVALID_PARAMETER;
+       }
+
+       if (!heart_memory_app_list) {
+               _E("hashtable heart_memory_app_list is NULL");
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       /* read from hash and make reply hash */
+       /* loop in file read and make reply */
+       ret = pthread_mutex_lock(&heart_memory_mutex);
+       if (ret) {
+               _E("pthread_mutex_lock() failed, %d", ret);
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       table = g_hash_table_lookup(heart_memory_app_list, (gconstpointer)appid);
+       if (!table) {
+               _E("NOT found in table %s", appid);
+
+               ret = logging_get_latest_in_cache(MEM_NAME, appid, &data);
+
+               if (ret) {
+                       _E("logging_get_latest_in_cache failed");
+
+                       ret = pthread_mutex_unlock(&heart_memory_mutex);
+                       if (ret) {
+                               _E("pthread_mutex_unlock() failed, %d", ret);
+                               return RESOURCED_ERROR_FAIL;
+                       }
+                       return RESOURCED_ERROR_FAIL;
+               }
+
+               if (sscanf(data, "%u", rss) < 0) {
+                       _E("sscanf failed");
+                       ret = pthread_mutex_unlock(&heart_memory_mutex);
+                       if (ret) {
+                               _E("pthread_mutex_unlock() failed, %d", ret);
+                               return RESOURCED_ERROR_FAIL;
+                       }
+                       return RESOURCED_ERROR_FAIL;
+               }
+
+               ret = pthread_mutex_unlock(&heart_memory_mutex);
+               if (ret) {
+                       _E("pthread_mutex_unlock() failed, %d", ret);
+                       return RESOURCED_ERROR_FAIL;
+               }
+               return RESOURCED_ERROR_NONE;
+       }
+
+       if (table->latest_rss) {
+               *rss = table->latest_rss;
+       } else {
+               ret = logging_get_latest_in_cache(MEM_NAME, appid, &data);
+
+               if (ret) {
+                       _E("logging_get_latest_in_cache failed");
+                       ret = pthread_mutex_unlock(&heart_memory_mutex);
+                       if (ret) {
+                               _E("pthread_mutex_unlock() failed, %d", ret);
+                               return RESOURCED_ERROR_FAIL;
+                       }
+                       return RESOURCED_ERROR_FAIL;
+               }
+
+               if (sscanf(data, "%u", rss) < 0) {
+                       _E("sscanf failed");
+                       ret = pthread_mutex_unlock(&heart_memory_mutex);
+                       if (ret) {
+                               _E("pthread_mutex_unlock() failed, %d", ret);
+                               return RESOURCED_ERROR_FAIL;
+                       }
+                       return RESOURCED_ERROR_FAIL;
+               }
+       }
+
+       ret = pthread_mutex_unlock(&heart_memory_mutex);
+       if (ret) {
+               _E("pthread_mutex_unlock() failed, %d", ret);
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       return RESOURCED_ERROR_NONE;
+}
+
+int heart_memory_get_table(GArray *arrays, enum heart_data_period period)
+{
+       int index, i, ret, count, time;
+       gpointer value;
+       gpointer key;
+       unsigned int max_rss = 0, avg_rss = 0, total_rss = 0;
+       GHashTableIter h_iter;
+       struct heart_memory_table *table;
+       struct heart_memory_data *md;
+
+       switch (period) {
+       case DATA_LATEST:
+               index = 0;
+               break;
+       case DATA_3HOUR:
+               index = 3;
+               break;
+       case DATA_6HOUR:
+               index = 6;
+               break;
+       case DATA_12HOUR:
+               index = 12;
+               break;
+       case DATA_1DAY:
+               index = 24;
+               break;
+       default:
+               _E("Wrong message arguments! %d", period);
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       /* read from hash and make reply hash */
+       /* loop in file read and make reply */
+       ret = pthread_mutex_lock(&heart_memory_mutex);
+       if (ret) {
+               _E("pthread_mutex_lock() failed, %d", ret);
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       g_hash_table_iter_init(&h_iter, heart_memory_app_list);
+
+       while (g_hash_table_iter_next(&h_iter, &key, &value)) {
+               table = (struct heart_memory_table *)value;
+
+               md = malloc(sizeof(struct heart_memory_data));
+               if (!md) {
+                       _E("malloc failed");
+                       goto unlock_out_of_memory_exit;
+               }
+
+               if (snprintf(md->appid, MAX_APPID_LENGTH, "%s", table->appid) < 0) {
+                       _E("snprintf failed");
+                       free(md);
+                       goto unlock_out_of_memory_exit;
+               }
+
+               if (snprintf(md->pkgid, MAX_PKGNAME_LENGTH, "%s", table->pkgid) < 0) {
+                       _E("snprintf failed");
+                       free(md);
+                       goto unlock_out_of_memory_exit;
+               }
+
+               count = table->count;
+               total_rss = table->total_rss;
+               max_rss = table->max_rss;
+               avg_rss = total_rss / count;
+               time = 1;
+
+               if (period != DATA_LATEST) {
+                       i = table->memory_info->len;
+
+                       if (i < index)
+                               index = i;
+
+                       for (i = 0; i < index; i++) {
+                               struct heart_memory_info *mi;
+
+                               mi = g_array_index(table->memory_info, struct heart_memory_info *, i);
+
+                               if (mi->max_rss || mi->avg_rss)
+                                       time++;
+
+                               if (max_rss < mi->max_rss)
+                                       max_rss = mi->max_rss;
+
+                               avg_rss += mi->avg_rss;
+                       }
+
+                       if (time)
+                               avg_rss /= time;
+               }
+
+               md->max_rss = max_rss;
+               md->avg_rss = avg_rss;
+               g_array_append_val(arrays, md);
+       }
+
+       ret = pthread_mutex_unlock(&heart_memory_mutex);
+       if (ret) {
+               _E("pthread_mutex_unlock() failed, %d", ret);
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       return RESOURCED_ERROR_NONE;
+
+unlock_out_of_memory_exit:
+       ret = pthread_mutex_unlock(&heart_memory_mutex);
+       if (ret) {
+               _E("pthread_mutex_unlock() failed, %d", ret);
+               return RESOURCED_ERROR_FAIL;
+       }
+       return RESOURCED_ERROR_OUT_OF_MEMORY;
+}
+
+void heart_memory_update(struct logging_table_form *data, void *user_data)
+{
+       int ret;
+       unsigned int rss;
+       time_t curr_time = logging_get_time(CLOCK_BOOTTIME);
+       struct heart_memory_table *find;
+       struct heart_memory_table *table;
+
+       if (sscanf(data->data, "%u", &rss) < 0) {
+               _E("sscanf failed");
+               return;
+       }
+
+       find = heart_memory_find_info(heart_memory_app_list, data->appid);
+
+       /* get last node and update it & re-insert to hash table  */
+       /* update */
+       if (find) {
+               ret = pthread_mutex_lock(&heart_memory_mutex);
+               if (ret) {
+                       _E("pthread_mutex_lock() failed, %d", ret);
+                       return;
+               }
+
+               if (find->renew) {
+                       find->count = 0;
+                       find->max_rss = 0;
+                       find->total_rss = 0;
+                       find->renew = 0;
+               }
+
+               find->total_rss += rss;
+
+               if (find->max_rss < rss)
+                       find->max_rss = rss;
+
+               find->latest_rss = rss;
+
+               find->count++;
+
+               table = find;
+
+               ret = pthread_mutex_unlock(&heart_memory_mutex);
+               if (ret) {
+                       _E("pthread_mutex_unlock() failed, %d", ret);
+                       return;
+               }
+       } else {
+               table = malloc(sizeof(struct heart_memory_table));
+
+               if (!table) {
+                       _E("malloc failed");
+                       return;
+               }
+
+               if (snprintf(table->appid, MAX_APPID_LENGTH, "%s", data->appid) < 0) {
+                       free(table);
+                       _E("snprintf failed");
+                       return;
+               }
+
+               if (snprintf(table->pkgid, MAX_PKGNAME_LENGTH, "%s", data->pkgid) < 0) {
+                       free(table);
+                       _E("snprintf failed");
+                       return;
+               }
+
+               table->memory_info =
+                       g_array_new(false, false, sizeof(struct heart_memory_info *));
+
+               table->total_rss = rss;
+
+               table->max_rss = rss;
+
+               table->latest_rss = rss;
+
+               table->count = 1;
+
+               ret = pthread_mutex_lock(&heart_memory_mutex);
+               if (ret) {
+                       free(table);
+                       _E("pthread_mutex_lock() failed, %d", ret);
+                       return;
+               }
+
+               g_hash_table_insert(heart_memory_app_list, (gpointer)table->appid, (gpointer)table);
+
+               ret = pthread_mutex_unlock(&heart_memory_mutex);
+               if (ret) {
+                       _E("pthread_mutex_unlock() failed, %d", ret);
+                       return;
+               }
+       }
+
+       if (last_file_update_time + HEART_MEMORY_SAVE_INTERVAL < curr_time) {
+               /* all hash table update and make new array */
+               gpointer value;
+               gpointer key;
+               GHashTableIter iter;
+               struct heart_memory_table *search;
+               struct heart_memory_info *new_memory_info;
+
+               ret = pthread_mutex_lock(&heart_memory_mutex);
+               if (ret) {
+                       _E("pthread_mutex_lock() failed, %d", ret);
+                       return;
+               }
+
+               g_hash_table_iter_init(&iter, heart_memory_app_list);
+
+               while (g_hash_table_iter_next(&iter, &key, &value)) {
+                       search = (struct heart_memory_table *)value;
+
+                       new_memory_info = malloc(sizeof(struct heart_memory_info));
+
+                       if (!new_memory_info) {
+                               ret = pthread_mutex_unlock(&heart_memory_mutex);
+                               if (ret) {
+                                       _E("pthread_mutex_lock() failed, %d", ret);
+                                       return;
+                               }
+                               _E("malloc failed");
+                               return;
+                       }
+
+                       /* make new array node */
+                       new_memory_info->max_rss = search->max_rss;
+
+                       if (search->count)
+                               new_memory_info->avg_rss = search->total_rss / search->count;
+                       else
+                               new_memory_info->avg_rss = search->total_rss;
+
+                       new_memory_info->max_rss = search->max_rss;
+
+                       search->renew = 1;
+
+                       /* hashtable sliding : remove last node and make new one */
+                       g_array_remove_index(search->memory_info, MEM_ARRAY_MAX-1);
+                       g_array_prepend_val(search->memory_info, new_memory_info);
+               }
+
+               ret = pthread_mutex_unlock(&heart_memory_mutex);
+               if (ret) {
+                       _E("pthread_mutex_unlock() failed, %d", ret);
+                       return;
+               }
+               /* rewrite hashtable list file */
+               ret = heart_memory_save_to_file(heart_memory_app_list, HEART_MEMORY_FILE);
+               if (ret) {
+                       _E("save to file failed");
+                       return;
+               }
+
+               last_file_update_time = curr_time;
+       }
+}
+
+static int heart_memory_write(char *appid, char *pkgid, struct proc_status *p_data)
+{
+       _cleanup_free_ char *info = NULL;
+       unsigned int usage = 0;
+       int ret;
+       struct proc_app_info *pai = p_data->pai;
+
+       /* For write to data crud during period */
+       /* write memory usage in proc_list */
+       ret = proc_get_mem_usage(p_data->pid, &usage);
+       if (ret < 0) {
+               _E("Failed to get PID(%d) rss: %m", p_data->pid);
+               return ret;
+       }
+
+       if (pai && pai->childs) {
+               unsigned int child_usage;
+               GSList *iterchild;
+
+               gslist_for_each_item(iterchild, pai->childs) {
+                       pid_t child = GPOINTER_TO_PID(iterchild->data);
+                       ret = proc_get_mem_usage(child, &child_usage);
+                       if (ret < 0) {
+                               _E("Failed to get PID(%d) rss: %m", child);
+                               continue;
+                       }
+                       usage += child_usage;
+               }
+       }
+
+       _SD("memory write : %s(%d), usage %u", appid, p_data->pid, usage);
+       ret = asprintf(&info, "%u", usage);
+       if (ret < 0) {
+               _E("Failed to allocate memory");
+               return -ENOMEM;
+       }
+
+       ret = logging_write(p_data->pid, MEM_NAME, appid, pkgid, time(NULL), info);
+
+       if (ret)
+               _E("logging_write failed %d", ret);
+
+       return ret;
+}
+
+static int heart_memory_state_cb(void *data)
+{
+       int ret;
+       char *appid, *pkgid;
+       struct proc_status *ps = (struct proc_status *)data;
+
+       ret = proc_get_id_info(ps, &appid, &pkgid);
+       if (ret != RESOURCED_ERROR_NONE) {
+               _E("Failed to proc_get_id_info");
+               return ret;
+       }
+
+       heart_memory_write(appid, pkgid, ps);
+
+       return RESOURCED_ERROR_NONE;
+}
+
+static gboolean heart_memory_notify(gpointer data)
+{
+       resourced_notify(RESOURCED_NOTIFIER_LOGGING_START, NULL);
+
+       return true;
+}
+
+static void dbus_get_memory_latest(GDBusMethodInvocation *invocation, GVariant *params)
+{
+       int ret;
+       char *appid = NULL;
+       unsigned int rss = 0;
+
+       do_expr_unless_g_variant_get_typechecked(goto failure, params, "(&s)", &appid);
+       if (!appid) {
+               _E("Wrong message arguments!");
+               goto failure;
+       }
+
+       ret = heart_memory_get_latest_data(appid, &rss);
+
+       if (ret) {
+               _E("heart_memory_get_latest_data failed %d", ret);
+               goto failure;
+       }
+
+       g_dbus_method_invocation_return_value(invocation, g_variant_new("(u)", rss));
+       return;
+
+failure:
+       D_BUS_REPLY_ERR(invocation);
+}
+
+static void dbus_get_memory_data(GDBusMethodInvocation *invocation, GVariant *params)
+{
+       int period = -1;
+       char *appid = NULL;
+       struct heart_memory_data *md;
+
+       do_expr_unless_g_variant_get_typechecked(goto failure, params, "(&si)", &appid, &period);
+       if (!appid || period < 0) {
+               _E("Wrong message arguments!");
+               goto failure;
+       }
+
+       md = heart_memory_get_data(appid, period);
+       if (!md) {
+               _E("heart_memory_get_data failed");
+               goto failure;
+       }
+
+       g_dbus_method_invocation_return_value(invocation, g_variant_new("(uu)", md->max_rss, md->avg_rss));
+
+       free(md);
+       return;
+
+failure:
+       D_BUS_REPLY_ERR(invocation);
+}
+
+static void dbus_get_memory_data_list(GDBusMethodInvocation *invocation, GVariant *params)
+{
+       int i, ret, period = -1;
+       char *appid, *pkgid;
+       GArray *temp_array;
+       GVariantBuilder builder, *sub_builder;
+
+       do_expr_unless_g_variant_get_typechecked(goto failure, params, "(i)", &period);
+       if (period < 0) {
+               _E("Wrong message arguments!");
+               goto failure;
+       }
+
+       temp_array = g_array_new(false, false, sizeof(struct heart_memory_data *));
+
+       ret = heart_memory_get_table(temp_array, period);
+
+       if (ret) {
+               _E("heart_memory_get_table failed %d", ret);
+               goto failure;
+       }
+
+       g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
+       sub_builder = g_variant_builder_new(G_VARIANT_TYPE("a(ssuu)"));
+
+       for (i = 0; i < temp_array->len; i++) {
+               struct heart_memory_data *md;
+
+               md = g_array_index(temp_array, struct heart_memory_data *, i);
+
+               appid = md->appid;
+               pkgid = md->pkgid;
+
+               g_variant_builder_add(sub_builder, "(ssuu)", appid, pkgid, md->max_rss, md->avg_rss);
+       }
+       g_variant_builder_add_value(&builder, g_variant_new("a(ssuu)", sub_builder));
+       g_variant_builder_unref(sub_builder);
+
+       g_dbus_method_invocation_return_value(invocation, g_variant_builder_end(&builder));
+
+       g_array_free(temp_array, true);
+       return;
+
+failure:
+       D_BUS_REPLY_ERR(invocation);
+}
+
+static void dbus_get_memorydb(GDBusMethodInvocation *invocation, GVariant *params)
+{
+       int i, period = -1;
+       char *appid, *pkgid;
+       GArray *temp_array;
+       GVariantBuilder builder, *sub_builder;
+
+       do_expr_unless_g_variant_get_typechecked(goto failure, params, "(i)", &period);
+       if (period < 0) {
+               _E("Wrong message arguments!");
+               goto failure;
+       }
+
+       temp_array = g_array_new(false, false, sizeof(struct heart_memory_data *));
+       _E("start get read query!!! %ld", time(NULL));
+       heart_memory_get_query(temp_array, period);
+       _E("end get read query!!! %ld", time(NULL));
+
+       g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
+       sub_builder = g_variant_builder_new(G_VARIANT_TYPE("a(ssuu)"));
+
+       for (i = 0; i < temp_array->len; i++) {
+               struct heart_memory_data *md;
+
+               md = g_array_index(temp_array, struct heart_memory_data *, i);
+
+               appid = md->appid;
+               pkgid = md->pkgid;
+
+               g_variant_builder_add(sub_builder, "(ssuu)", appid, pkgid, md->max_rss, md->avg_rss);
+       }
+       g_variant_builder_add_value(&builder, g_variant_new("a(ssuu)", sub_builder));
+       g_variant_builder_unref(sub_builder);
+
+       g_dbus_method_invocation_return_value(invocation, g_variant_builder_end(&builder));
+
+       g_array_free(temp_array, true);
+       return;
+
+failure:
+       D_BUS_REPLY_ERR(invocation);
+}
+
+static void dbus_get_memoryforeach(GDBusMethodInvocation *invocation, GVariant *params)
+{
+       int i, period = -1;
+       char *appid, *pkgid;
+       GArray *temp_array;
+       GVariantBuilder builder, *sub_builder;
+
+       do_expr_unless_g_variant_get_typechecked(goto failure, params, "(i)", &period);
+       if (period < 0) {
+               _E("Wrong message arguments!");
+               goto failure;
+       }
+
+       /* read from query */
+       temp_array = g_array_new(false, false, sizeof(struct heart_memory_data *));
+       _E("start get read foreach!!! %ld", time(NULL));
+       logging_memory_get_foreach(temp_array, period);
+       _E("end get read foreach!!! %ld", time(NULL));
+
+       g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
+       sub_builder = g_variant_builder_new(G_VARIANT_TYPE("a(ssuu)"));
+
+       for (i = 0; i < temp_array->len; i++) {
+               struct heart_memory_data *md;
+
+               md = g_array_index(temp_array, struct heart_memory_data *, i);
+
+               appid = md->appid;
+               pkgid = md->pkgid;
+
+               g_variant_builder_add(sub_builder, "(ssuu)", appid, pkgid, md->max_rss, md->avg_rss);
+       }
+       g_variant_builder_add_value(&builder, g_variant_new("a(ssuu)", sub_builder));
+       g_variant_builder_unref(sub_builder);
+
+       g_dbus_method_invocation_return_value(invocation, g_variant_builder_end(&builder));
+
+       g_array_free(temp_array, true);
+       return;
+
+failure:
+       D_BUS_REPLY_ERR(invocation);
+}
+
+static void dbus_memory_save_to_file(GDBusMethodInvocation *invocation, GVariant *params)
+{
+       int ret;
+
+       ret = heart_memory_save_to_file(heart_memory_app_list, HEART_MEMORY_FILE);
+
+       if (ret) {
+               _E("save to file failed");
+               D_BUS_REPLY_ERR(invocation);
+               return;
+       }
+
+       g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", ret));
+}
+
+static const char dbus_methods_xml[] =
+"              <method name='GetMemoryLatest'>"
+"                      <arg type='s' name='Appid' direction='in'/>"
+"                      <arg type='u' name='Rss' direction='out'/>"
+"              </method>"
+"              <method name='GetMemoryData'>"
+"                      <arg type='s' name='Appid' direction='in'/>"
+"                      <arg type='i' name='Period' direction='in'/>"
+"                      <arg type='u' name='MaxRss' direction='out'/>"
+"                      <arg type='u' name='AvgRss' direction='out'/>"
+"              </method>"
+"              <method name='GetMemoryDataList'>"
+"                      <arg type='i' name='Period' direction='in'/>"
+"                      <arg type='a(ssuu)' name='MemoryUsagePerApp' direction='out'/>"
+"              </method>"
+"              <method name='GetMemoryDB'>"
+"                      <arg type='i' name='Period' direction='in'/>"
+"                      <arg type='a(ssuu)' name='MemoryUsagePerApp' direction='out'/>"
+"              </method>"
+"              <method name='GetMemoryforeach'>"
+"                      <arg type='i' name='Period' direction='in'/>"
+"                      <arg type='a(ssuu)' name='MemoryUsagePerApp' direction='out'/>"
+"              </method>"
+"              <method name='SaveMemoryData'>"
+"                      <arg type='i' name='ZeroOnSuccess' direction='out'/>"
+"              </method>";
+
+static struct d_bus_method dbus_methods[] = {
+       { "GetMemoryLatest",   dbus_get_memory_latest },
+       { "GetMemoryData",     dbus_get_memory_data },
+       { "GetMemoryDataList", dbus_get_memory_data_list },
+       { "GetMemoryDB",       dbus_get_memorydb },
+       { "GetMemoryforeach",  dbus_get_memoryforeach },
+       { "SaveMemoryData",    dbus_memory_save_to_file },
+};
+
+static int heart_memory_init(void *data)
+{
+       int ret;
+
+       ret = logging_module_init(MEM_NAME, ONE_DAY, TEN_MINUTE, heart_memory_update, TEN_MINUTE, USER_DEFAULT);
+
+       if (ret != RESOURCED_ERROR_NONE) {
+               _E("logging module init failed");
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       if (!heart_memory_app_list) {
+               heart_memory_app_list = g_hash_table_new_full(
+                               g_str_hash,
+                               g_str_equal,
+                               NULL,
+                               heart_memory_free_value);
+
+               /* make hash from file */
+               ret = heart_memory_read_from_file(heart_memory_app_list, HEART_MEMORY_FILE);
+
+               if (ret == RESOURCED_ERROR_OUT_OF_MEMORY) {
+                       _E("heart_memory_init failed");
+                       return ret;
+               }
+       }
+
+       register_notifier(RESOURCED_NOTIFIER_SERVICE_LAUNCH, heart_memory_state_cb);
+       register_notifier(RESOURCED_NOTIFIER_APP_FOREGRD, heart_memory_state_cb);
+       register_notifier(RESOURCED_NOTIFIER_APP_BACKGRD, heart_memory_state_cb);
+
+       heart_dbus_declare_methods(dbus_methods_xml, dbus_methods, ARRAY_SIZE(dbus_methods));
+
+       last_file_update_time = logging_get_time(CLOCK_BOOTTIME);
+
+       if (heart_memory_update_timer == NULL) {
+               _D("logging memory update timer start");
+               heart_memory_update_timer = g_timeout_source_new_seconds(TEN_MINUTE);
+               g_source_set_callback(heart_memory_update_timer, heart_memory_notify, NULL, NULL);
+               g_source_attach(heart_memory_update_timer, NULL);
+       }
+
+       heart_memory_get_data_func = heart_memory_get_data;
+
+       _D("heart memory init finished");
+       return RESOURCED_ERROR_NONE;
+}
+
+static int heart_memory_exit(void *data)
+{
+       int ret;
+
+       /* update timer delete */
+       g_source_destroy(heart_memory_update_timer);
+       heart_memory_update_timer = NULL;
+
+       unregister_notifier(RESOURCED_NOTIFIER_SERVICE_LAUNCH, heart_memory_state_cb);
+       unregister_notifier(RESOURCED_NOTIFIER_APP_FOREGRD, heart_memory_state_cb);
+       unregister_notifier(RESOURCED_NOTIFIER_APP_BACKGRD, heart_memory_state_cb);
+
+       if (heart_memory_app_list) {
+               ret = heart_memory_save_to_file(heart_memory_app_list, HEART_MEMORY_FILE);
+
+               if (ret)
+                       _E("save file failed %d", ret);
+
+               if (heart_memory_app_list) {
+                       gpointer value;
+                       gpointer key;
+                       GHashTableIter iter;
+
+                       g_hash_table_iter_init(&iter, heart_memory_app_list);
+
+                       while (g_hash_table_iter_next(&iter, &key, &value)) {
+                               struct heart_memory_table *table = (struct heart_memory_table *)value;
+
+                               if (table->memory_info)
+                                       g_array_free(table->memory_info, true);
+                       }
+
+                       g_hash_table_destroy(heart_memory_app_list);
+               }
+       }
+
+       heart_memory_get_data_func = NULL;
+
+       logging_module_exit();
+       _D("heart memory exit");
+       return RESOURCED_ERROR_NONE;
+}
+
+static const struct heart_module_ops heart_memory_ops = {
+       .name           = "MEMORY",
+       .init           = heart_memory_init,
+       .exit           = heart_memory_exit,
+};
+HEART_MODULE_REGISTER(&heart_memory_ops)
diff --git a/src/resource-monitor/heart-storage.c b/src/resource-monitor/heart-storage.c
new file mode 100644 (file)
index 0000000..42d8f03
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * resourced
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @file heart-storage.c
+ *
+ * @desc heart storage module
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <glib.h>
+#include <stdbool.h>
+#include <time.h>
+
+#include "resourced.h"
+#include "trace.h"
+#include "module.h"
+#include "macro.h"
+#include "notifier.h"
+#include "heart.h"
+#include "logging.h"
+#include "heart-common.h"
+#include "dbus-handler.h"
+#include "proc-common.h"
+
+#include <sqlite3.h>
+
+#define STORAGE_NAME           "storage"
+
+static bool heart_storage_initailized = false;
+
+static void dbus_insert_log(GDBusMethodInvocation *invocation, GVariant *params)
+{
+       int ret;
+       int pid = 0;
+       char *pkgid = NULL;
+       char *data = NULL;
+       struct proc_app_info *pai;
+
+       do_expr_unless_g_variant_get_typechecked(goto finish, params, "(&s&s)", &pkgid, &data);
+       if (!pkgid) {
+               _E("Wrong message arguments!");
+               goto finish;
+       }
+
+       pai = find_app_info_by_appid(pkgid);
+       if (!pai) {
+               _E("Failed to find the app info of %s", pkgid);
+               goto finish;
+       }
+
+       pid = pai->main_pid;
+
+       _SD("Insert record (%s, %s)", pkgid, data);
+       ret = logging_write(pid, STORAGE_NAME, pkgid, pkgid, time(NULL), data);
+       if (ret != RESOURCED_ERROR_NONE)
+               _E("Write request failed");
+
+finish:
+       g_dbus_method_invocation_return_value(invocation, NULL);
+}
+
+static const char dbus_methods_xml[] =
+"              <method name='Insert'>"
+"                      <arg type='s' name='Pkgid' direction='in'/>"
+"                      <arg type='s' name='UserData' direction='in'/>"
+"              </method>";
+
+static struct d_bus_method dbus_methods[] = {
+       { "Insert", dbus_insert_log },
+};
+
+static bool is_storage_logging(void)
+{
+       static const struct module_ops *block;
+
+       if (!block) {
+               block = find_module("block");
+               if (block)
+                       heart_storage_initailized = true;
+       }
+
+       return heart_storage_initailized;
+}
+
+static int heart_storage_write(void *data)
+{
+       int ret;
+       struct logging_data *ld = (struct logging_data *)data;
+
+       ret = logging_write(ld->pid, STORAGE_NAME, ld->appid, ld->pkgid, time(NULL), ld->data);
+       return ret;
+}
+
+static int heart_storage_init(void *data)
+{
+       int ret;
+
+       if (!is_storage_logging())
+               return RESOURCED_ERROR_UNINITIALIZED;
+
+       ret = logging_module_init(STORAGE_NAME, FOUR_MONTH, FIVE_MINUTE, NULL, 0, USER_OWN);
+       if (ret != RESOURCED_ERROR_NONE) {
+               _E("logging module init failed");
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       heart_dbus_declare_methods(dbus_methods_xml, dbus_methods, ARRAY_SIZE(dbus_methods));
+
+       register_notifier(RESOURCED_NOTIFIER_LOGGING_WRITE, heart_storage_write);
+       return RESOURCED_ERROR_NONE;
+}
+
+static int heart_storage_exit(void *data)
+{
+       if (!heart_storage_initailized)
+               return RESOURCED_ERROR_NONE;
+
+       _D("heart_storage exit");
+       unregister_notifier(RESOURCED_NOTIFIER_LOGGING_WRITE, heart_storage_write);
+       logging_module_exit();
+       return RESOURCED_ERROR_NONE;
+}
+
+static const struct heart_module_ops heart_storage_ops = {
+       .name           = "STORAGE",
+       .init           = heart_storage_init,
+       .exit           = heart_storage_exit,
+};
+HEART_MODULE_REGISTER(&heart_storage_ops)
diff --git a/src/resource-monitor/memory/heart-memory.c b/src/resource-monitor/memory/heart-memory.c
deleted file mode 100644 (file)
index 3aca2c1..0000000
+++ /dev/null
@@ -1,1411 +0,0 @@
-/*
- * resourced
- *
- * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * @file heart-memory.c
- *
- * @desc heart memory module
- *
- * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-#include <glib.h>
-
-#include "resourced.h"
-#include "trace.h"
-#include "module.h"
-#include "macro.h"
-#include "notifier.h"
-#include "proc-common.h"
-#include "heart.h"
-#include "logging.h"
-#include "heart-common.h"
-#include "dbus-handler.h"
-#include "procfs.h"
-#include "util.h"
-
-#include <sqlite3.h>
-#include <time.h>
-
-struct heart_memory_info {
-       unsigned int max_rss;
-       unsigned int avg_rss;
-};
-
-struct heart_memory_table {
-       char appid[MAX_APPID_LENGTH];
-       char pkgid[MAX_PKGNAME_LENGTH];
-       unsigned int total_rss;
-       unsigned int max_rss;
-       unsigned int latest_rss;
-       unsigned int count;
-       int renew;
-       GArray *memory_info;
-};
-
-static GHashTable *heart_memory_app_list;
-static pthread_mutex_t heart_memory_mutex = PTHREAD_MUTEX_INITIALIZER;
-static time_t last_file_update_time;
-static GSource *heart_memory_update_timer = NULL;
-
-struct heart_memory_table *heart_memory_find_info(GHashTable *hashtable, char *appid)
-{
-       int ret;
-       struct heart_memory_table *table;
-
-       if (!hashtable) {
-               _E("hashtable is NULL");
-               return NULL;
-       }
-
-       ret = pthread_mutex_lock(&heart_memory_mutex);
-       if (ret) {
-               _E("pthread_mutex_lock() failed, %d", ret);
-               return NULL;
-       }
-
-       table = g_hash_table_lookup(hashtable, (gconstpointer)appid);
-
-       ret = pthread_mutex_unlock(&heart_memory_mutex);
-       if (ret) {
-               _E("pthread_mutex_unlock() failed, %d", ret);
-               return NULL;
-       }
-
-       return table;
-}
-
-static void heart_memory_free_value(gpointer value)
-{
-       struct heart_memory_table * table = (struct heart_memory_table *)value;
-
-       if (table)
-               free(table);
-}
-
-static int heart_memory_read_length(char *buf, int count)
-{
-       int i, find = 0;
-       int len = strlen(buf);
-
-       for (i = 0; i < len; i++) {
-               if (buf[i] == ' ')
-                       find++;
-
-               if (find == count)
-                       return i+1;
-       }
-
-       return RESOURCED_ERROR_FAIL;
-}
-
-static int heart_memory_read_from_file(GHashTable *hashtable, char *filename)
-{
-       int i, len, ret, result;
-       unsigned int total_rss, max_rss, avg_rss;
-       unsigned int count;
-       FILE *fp;
-       struct heart_memory_table *table;
-       char appid[MAX_APPID_LENGTH] = {0, };
-       char pkgid[MAX_PKGNAME_LENGTH] = {0, };
-       char buf[MEM_DATA_MAX] = {0, };
-
-       fp = fopen(filename, "r");
-
-       if (!fp) {
-               _E("%s fopen failed %d", filename, errno);
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       while (fgets(buf, MEM_DATA_MAX, fp)) {
-               table = malloc(sizeof(struct heart_memory_table));
-
-               if (!table) {
-                       _E("malloc failed");
-                       fclose(fp);
-                       return RESOURCED_ERROR_OUT_OF_MEMORY;
-               }
-
-               /* make return values */
-               result = sscanf(buf, STR_FS(MAX_APPID_LENGTH_M1)" "STR_FS(MAX_PKGNAME_LENGTH_M1)" %u %u %u ",
-                               appid, pkgid, &total_rss, &max_rss, &count);
-
-               if (result < 0) {
-                       _E("sscanf failed");
-                       free(table);
-                       fclose(fp);
-                       return RESOURCED_ERROR_FAIL;
-               }
-
-               if (snprintf(table->appid, MAX_APPID_LENGTH, "%s", appid) < 0) {
-                       _E("snprintf failed");
-                       free(table);
-                       fclose(fp);
-                       return RESOURCED_ERROR_OUT_OF_MEMORY;
-               }
-
-               if (snprintf(table->pkgid, MAX_PKGNAME_LENGTH, "%s", pkgid) < 0) {
-                       _E("snprintf failed");
-                       free(table);
-                       fclose(fp);
-                       return RESOURCED_ERROR_OUT_OF_MEMORY;
-               }
-
-               len = heart_memory_read_length(buf, 7);
-
-               if (len < 0) {
-                       _E("7 space read length failed %s", buf);
-                       free(table);
-                       fclose(fp);
-                       return RESOURCED_ERROR_FAIL;
-               }
-
-               table->total_rss = total_rss;
-               table->max_rss = max_rss;
-               table->latest_rss = 0;
-               table->count = count;
-               table->memory_info =
-                       g_array_new(false, false, sizeof(struct heart_memory_info *));
-
-               for (i = 0; i < MEM_ARRAY_MAX; i++) {
-                       struct heart_memory_info *mi;
-
-                       result = sscanf(buf + len, "%u %u ",
-                                       &max_rss, &avg_rss);
-
-                       if (result <= 0) {
-                               _E("file read fail %s", buf + len);
-                               g_array_free(table->memory_info, true);
-                               free(table);
-                               fclose(fp);
-                               return RESOURCED_ERROR_FAIL;
-                       }
-
-                       mi = malloc(sizeof(struct heart_memory_info));
-
-                       if (!mi) {
-                               _E("malloc failed");
-                               g_array_free(table->memory_info, true);
-                               free(table);
-                               fclose(fp);
-                               return RESOURCED_ERROR_OUT_OF_MEMORY;
-                       }
-
-                       mi->max_rss = max_rss;
-                       mi->avg_rss = avg_rss;
-
-                       len += heart_memory_read_length(buf + len, 4);
-
-                       g_array_append_val(table->memory_info, mi);
-               }
-
-               ret = pthread_mutex_lock(&heart_memory_mutex);
-               if (ret) {
-                       _E("pthread_mutex_lock() failed, %d", ret);
-                       g_array_free(table->memory_info, true);
-                       free(table);
-                       fclose(fp);
-                       return RESOURCED_ERROR_FAIL;
-               }
-
-               g_hash_table_insert(hashtable, (gpointer)table->appid, (gpointer)table);
-
-               ret = pthread_mutex_unlock(&heart_memory_mutex);
-               if (ret) {
-                       _E("pthread_mutex_unlock() failed, %d", ret);
-                       fclose(fp);
-                       return RESOURCED_ERROR_FAIL;
-               }
-       }
-
-       fclose(fp);
-
-       return RESOURCED_ERROR_NONE;
-}
-
-static int heart_memory_save_to_file(GHashTable *hashtable, char *filename)
-{
-       int i, len, ret, array_len;
-       gpointer value;
-       gpointer key;
-       GHashTableIter iter;
-       struct heart_memory_table *table;
-       FILE *fp;
-       char buf[MEM_DATA_MAX] = {0, };
-
-       fp = fopen(filename, "w");
-       if (!fp) {
-               _E("%s fopen failed %d", filename, errno);
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       ret = pthread_mutex_lock(&heart_memory_mutex);
-       if (ret) {
-               _E("pthread_mutex_lock() failed, %d", ret);
-               fclose(fp);
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       g_hash_table_iter_init(&iter, hashtable);
-
-       while (g_hash_table_iter_next(&iter, &key, &value)) {
-               table = (struct heart_memory_table *)value;
-
-               len = snprintf(buf, MEM_DATA_MAX, "%s %s %u %u %u ",
-                               table->appid, table->pkgid,
-                               table->total_rss, table->max_rss,
-                               table->count);
-
-               array_len = table->memory_info->len;
-
-               for (i = 0; i < MEM_ARRAY_MAX; i++) {
-                       struct heart_memory_info *mi;
-
-                       if (array_len <= i)
-                               len += snprintf(buf + len, MEM_DATA_MAX - len, "0 0 0 0 ");
-                       else {
-                               mi = g_array_index(table->memory_info, struct heart_memory_info *, i);
-
-                               len += snprintf(buf + len, MEM_DATA_MAX - len, "%u %u ",
-                                               mi->max_rss, mi->avg_rss);
-                       }
-               }
-
-               snprintf(buf + len, MEM_DATA_MAX - len, "%c\n", MEM_FILE_SEPERATOR);
-
-               fputs(buf, fp);
-       }
-
-       ret = pthread_mutex_unlock(&heart_memory_mutex);
-       if (ret) {
-               _E("pthread_mutex_unlock() failed, %d", ret);
-               fclose(fp);
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       fclose(fp);
-
-       return RESOURCED_ERROR_NONE;
-}
-
-void heart_memory_fill_array(struct logging_table_form *data, void *user_data)
-{
-       int i;
-       unsigned int rss;
-       struct heart_memory_data *md = NULL;
-       GArray *send = NULL;
-
-       _E("data : %s %s %d %s", data->appid, data->pkgid, (int)data->time, data->data);
-       send = (GArray *)user_data;
-
-       for (i = 0; i < send->len; i++) {
-               struct heart_memory_data *loop;
-               loop = g_array_index(send, struct heart_memory_data *, i);
-
-               if (!strncmp(loop->appid, data->appid, strlen(data->appid)+1)) {
-                       md = loop;
-                       break;
-               }
-       }
-
-       if (sscanf(data->data, "%u", &rss) < 0) {
-               _E("sscanf failed");
-               return;
-       }
-
-       if (!md) {
-               md = malloc(sizeof(struct heart_memory_data));
-
-               if (!md) {
-                       _E("malloc failed");
-                       return;
-               }
-
-               if (snprintf(md->appid, MAX_APPID_LENGTH, "%s", data->appid) < 0) {
-                       _E("snprintf failed");
-                       free(md);
-                       return;
-               }
-
-               if (snprintf(md->pkgid, MAX_PKGNAME_LENGTH, "%s", data->pkgid) < 0) {
-                       _E("snprintf failed");
-                       free(md);
-                       return;
-               }
-
-               md->max_rss = rss;
-               md->avg_rss = rss;
-
-               g_array_append_val(send, md);
-       } else {
-               if (md->max_rss < rss)
-                       md->max_rss = rss;
-
-               md->avg_rss = (md->avg_rss + rss) / 2;
-       }
-}
-
-int logging_memory_get_foreach(GArray *arrays, enum heart_data_period period)
-{
-       int ret;
-       time_t curr_time = time(NULL);
-
-       switch (period) {
-       case DATA_LATEST:
-               break;
-       case DATA_3HOUR:
-               curr_time -= 10800;
-               break;
-       case DATA_6HOUR:
-               curr_time -= 21600;
-               break;
-       case DATA_12HOUR:
-               curr_time -= 43200;
-               break;
-       case DATA_1DAY:
-               curr_time -= 86400;
-               break;
-       default:
-               _E("Wrong message arguments! %d", period);
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       ret = logging_read_foreach(MEM_NAME, NULL, NULL, curr_time, 0, heart_memory_fill_array, arrays);
-
-       if (ret) {
-               _E("failed logging_read_foreach");
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       return RESOURCED_ERROR_NONE;
-}
-
-int heart_memory_get_query(GArray *arrays, enum heart_data_period period)
-{
-       int count, result;
-       time_t curr_time = time(NULL);
-       sqlite3 *heart_db = NULL;
-       sqlite3_stmt *stmt = NULL;
-       gpointer value;
-       gpointer key;
-       char *data;
-       unsigned int rss;
-       GHashTableIter h_iter;
-       struct heart_memory_data *md;
-       struct heart_memory_table *table;
-       char buf[MEM_DATA_MAX] = {0, };
-
-       switch (period) {
-       case DATA_LATEST:
-               break;
-       case DATA_3HOUR:
-               curr_time -= 10800;
-               break;
-       case DATA_6HOUR:
-               curr_time -= 21600;
-               break;
-       case DATA_12HOUR:
-               curr_time -= 43200;
-               break;
-       case DATA_1DAY:
-               curr_time -= 86400;
-               break;
-       default:
-               _E("Wrong message arguments! %d", period);
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       if (logging_get_default_db(MEM_NAME, &heart_db) != RESOURCED_ERROR_NONE) {
-               _E("Fail to get DB path");
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       g_hash_table_iter_init(&h_iter, heart_memory_app_list);
-
-       while (g_hash_table_iter_next(&h_iter, &key, &value)) {
-               table = (struct heart_memory_table *)value;
-
-               md = malloc(sizeof(struct heart_memory_data));
-
-               if (!md) {
-                       _E("malloc failed");
-                       sqlite3_finalize(stmt);
-                       return RESOURCED_ERROR_OUT_OF_MEMORY;
-               }
-
-               if (snprintf(md->appid, MAX_APPID_LENGTH, "%s", table->appid) < 0) {
-                       _E("snprintf failed");
-                       free(md);
-                       sqlite3_finalize(stmt);
-                       return RESOURCED_ERROR_OUT_OF_MEMORY;
-               }
-
-               if (snprintf(md->pkgid, MAX_PKGNAME_LENGTH,  "%s", table->pkgid) < 0) {
-                       _E("asprintf failed");
-                       free(md);
-                       sqlite3_finalize(stmt);
-                       return RESOURCED_ERROR_OUT_OF_MEMORY;
-               }
-
-               count = 0;
-               md->max_rss = 0;
-               md->avg_rss = 0;
-
-               snprintf(buf, MEM_DATA_MAX, "select * from memory where appid = \'%s\' AND time > %d",
-                               table->appid, (int)curr_time);
-
-               /* search from db */
-               if (sqlite3_prepare_v2(heart_db, buf, -1, &stmt, NULL) != SQLITE_OK) {
-                       _E("select failed");
-                       free(md);
-                       sqlite3_finalize(stmt);
-                       return RESOURCED_ERROR_DB_FAILED;
-               }
-
-               do {
-                       result = sqlite3_step(stmt);
-                       switch (result) {
-                       case SQLITE_ROW:
-                               data = (char *)sqlite3_column_text(stmt, 3);
-
-                               if (sscanf(data, "%u", &rss) < 0) {
-                                       _E("sscanf failed");
-                                       free(md);
-                                       sqlite3_finalize(stmt);
-                                       return RESOURCED_ERROR_DB_FAILED;
-                               }
-
-                               if (md->max_rss < rss)
-                                       md->max_rss = rss;
-
-                               md->avg_rss += rss;
-                               count++;
-                               break;
-                       case SQLITE_DONE:
-                               break;
-                       case SQLITE_ERROR:
-                               _E("select %s table failed %s",
-                                               MEM_NAME, sqlite3_errmsg(heart_db));
-                               /* FALLTHROUGH */
-                       default:
-                               free(md);
-                               sqlite3_finalize(stmt);
-                               return RESOURCED_ERROR_DB_FAILED;
-                       }
-               } while (result == SQLITE_ROW);
-               if (count)
-                       md->avg_rss /= count;
-
-               g_array_append_val(arrays, md);
-       }
-
-       sqlite3_finalize(stmt);
-
-       return RESOURCED_ERROR_NONE;
-}
-
-struct heart_memory_data *heart_memory_get_data(char *appid, enum heart_data_period period)
-{
-       int index, i, ret, count, time;
-       unsigned int max_rss = 0, avg_rss = 0, total_rss = 0;
-       struct heart_memory_table *table;
-       struct heart_memory_data *md;
-
-       if (!heart_memory_app_list)
-               return NULL;
-
-       if (!appid) {
-               _E("Wrong message arguments!");
-               return NULL;
-       }
-
-       switch (period) {
-       case DATA_LATEST:
-               index = 0;
-               break;
-       case DATA_3HOUR:
-               index = 3;
-               break;
-       case DATA_6HOUR:
-               index = 6;
-               break;
-       case DATA_12HOUR:
-               index = 12;
-               break;
-       case DATA_1DAY:
-               index = 24;
-               break;
-       default:
-               _E("Wrong message arguments! %d", period);
-               return NULL;
-       }
-
-       /* read from hash and make reply hash */
-       /* loop in file read and make reply */
-       ret = pthread_mutex_lock(&heart_memory_mutex);
-       if (ret) {
-               _E("pthread_mutex_lock() failed, %d", ret);
-               return NULL;
-       }
-
-       table = g_hash_table_lookup(heart_memory_app_list, (gconstpointer)appid);
-       if (!table)
-               goto unlock_exit;
-       md = malloc(sizeof(struct heart_memory_data));
-       if (!md) {
-               _E("malloc failed");
-               goto unlock_exit;
-       }
-
-       if (snprintf(md->appid, MAX_APPID_LENGTH, "%s", table->appid) < 0) {
-               _E("snprintf failed");
-               free(md);
-               goto unlock_exit;
-       }
-
-       if (snprintf(md->pkgid, MAX_PKGNAME_LENGTH, "%s", table->pkgid) < 0) {
-               _E("snprintf failed");
-               free(md);
-               goto unlock_exit;
-       }
-
-       count = table->count;
-       total_rss = table->total_rss;
-       max_rss = table->max_rss;
-       avg_rss = total_rss / count;
-       time = 1;
-
-       if (period != DATA_LATEST) {
-               i = table->memory_info->len;
-
-               if (i < index)
-                       index = i;
-
-               for (i = 0; i < index; i++) {
-                       struct heart_memory_info *mi;
-
-                       mi = g_array_index(table->memory_info, struct heart_memory_info *, i);
-
-                       if (mi->max_rss || mi->avg_rss)
-                               time++;
-
-                       if (max_rss < mi->max_rss)
-                               max_rss = mi->max_rss;
-
-                       avg_rss += mi->avg_rss;
-               }
-
-               if (time)
-                       avg_rss /= time;
-
-       }
-
-       md->max_rss = max_rss;
-       md->avg_rss = avg_rss;
-
-       ret = pthread_mutex_unlock(&heart_memory_mutex);
-       if (ret) {
-               _E("pthread_mutex_unlock() failed, %d", ret);
-               free(md);
-               return NULL;
-       }
-       return md;
-
-unlock_exit:
-       ret = pthread_mutex_unlock(&heart_memory_mutex);
-       if (ret) {
-               _E("pthread_mutex_unlock() failed, %d", ret);
-               return NULL;
-       }
-       return NULL;
-}
-
-int heart_memory_get_latest_data(char *appid, unsigned int *rss)
-{
-       int ret;
-       char *data;
-       struct heart_memory_table *table;
-
-       if (!appid) {
-               _E("Wrong message arguments!");
-               return RESOURCED_ERROR_INVALID_PARAMETER;
-       }
-
-       if (!heart_memory_app_list) {
-               _E("hashtable heart_memory_app_list is NULL");
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       /* read from hash and make reply hash */
-       /* loop in file read and make reply */
-       ret = pthread_mutex_lock(&heart_memory_mutex);
-       if (ret) {
-               _E("pthread_mutex_lock() failed, %d", ret);
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       table = g_hash_table_lookup(heart_memory_app_list, (gconstpointer)appid);
-       if (!table) {
-               _E("NOT found in table %s", appid);
-
-               ret = logging_get_latest_in_cache(MEM_NAME, appid, &data);
-
-               if (ret) {
-                       _E("logging_get_latest_in_cache failed");
-
-                       ret = pthread_mutex_unlock(&heart_memory_mutex);
-                       if (ret) {
-                               _E("pthread_mutex_unlock() failed, %d", ret);
-                               return RESOURCED_ERROR_FAIL;
-                       }
-                       return RESOURCED_ERROR_FAIL;
-               }
-
-               if (sscanf(data, "%u", rss) < 0) {
-                       _E("sscanf failed");
-                       ret = pthread_mutex_unlock(&heart_memory_mutex);
-                       if (ret) {
-                               _E("pthread_mutex_unlock() failed, %d", ret);
-                               return RESOURCED_ERROR_FAIL;
-                       }
-                       return RESOURCED_ERROR_FAIL;
-               }
-
-               ret = pthread_mutex_unlock(&heart_memory_mutex);
-               if (ret) {
-                       _E("pthread_mutex_unlock() failed, %d", ret);
-                       return RESOURCED_ERROR_FAIL;
-               }
-               return RESOURCED_ERROR_NONE;
-       }
-
-       if (table->latest_rss) {
-               *rss = table->latest_rss;
-       } else {
-               ret = logging_get_latest_in_cache(MEM_NAME, appid, &data);
-
-               if (ret) {
-                       _E("logging_get_latest_in_cache failed");
-                       ret = pthread_mutex_unlock(&heart_memory_mutex);
-                       if (ret) {
-                               _E("pthread_mutex_unlock() failed, %d", ret);
-                               return RESOURCED_ERROR_FAIL;
-                       }
-                       return RESOURCED_ERROR_FAIL;
-               }
-
-               if (sscanf(data, "%u", rss) < 0) {
-                       _E("sscanf failed");
-                       ret = pthread_mutex_unlock(&heart_memory_mutex);
-                       if (ret) {
-                               _E("pthread_mutex_unlock() failed, %d", ret);
-                               return RESOURCED_ERROR_FAIL;
-                       }
-                       return RESOURCED_ERROR_FAIL;
-               }
-       }
-
-       ret = pthread_mutex_unlock(&heart_memory_mutex);
-       if (ret) {
-               _E("pthread_mutex_unlock() failed, %d", ret);
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       return RESOURCED_ERROR_NONE;
-}
-
-int heart_memory_get_table(GArray *arrays, enum heart_data_period period)
-{
-       int index, i, ret, count, time;
-       gpointer value;
-       gpointer key;
-       unsigned int max_rss = 0, avg_rss = 0, total_rss = 0;
-       GHashTableIter h_iter;
-       struct heart_memory_table *table;
-       struct heart_memory_data *md;
-
-       switch (period) {
-       case DATA_LATEST:
-               index = 0;
-               break;
-       case DATA_3HOUR:
-               index = 3;
-               break;
-       case DATA_6HOUR:
-               index = 6;
-               break;
-       case DATA_12HOUR:
-               index = 12;
-               break;
-       case DATA_1DAY:
-               index = 24;
-               break;
-       default:
-               _E("Wrong message arguments! %d", period);
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       /* read from hash and make reply hash */
-       /* loop in file read and make reply */
-       ret = pthread_mutex_lock(&heart_memory_mutex);
-       if (ret) {
-               _E("pthread_mutex_lock() failed, %d", ret);
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       g_hash_table_iter_init(&h_iter, heart_memory_app_list);
-
-       while (g_hash_table_iter_next(&h_iter, &key, &value)) {
-               table = (struct heart_memory_table *)value;
-
-               md = malloc(sizeof(struct heart_memory_data));
-               if (!md) {
-                       _E("malloc failed");
-                       goto unlock_out_of_memory_exit;
-               }
-
-               if (snprintf(md->appid, MAX_APPID_LENGTH, "%s", table->appid) < 0) {
-                       _E("snprintf failed");
-                       free(md);
-                       goto unlock_out_of_memory_exit;
-               }
-
-               if (snprintf(md->pkgid, MAX_PKGNAME_LENGTH, "%s", table->pkgid) < 0) {
-                       _E("snprintf failed");
-                       free(md);
-                       goto unlock_out_of_memory_exit;
-               }
-
-               count = table->count;
-               total_rss = table->total_rss;
-               max_rss = table->max_rss;
-               avg_rss = total_rss / count;
-               time = 1;
-
-               if (period != DATA_LATEST) {
-                       i = table->memory_info->len;
-
-                       if (i < index)
-                               index = i;
-
-                       for (i = 0; i < index; i++) {
-                               struct heart_memory_info *mi;
-
-                               mi = g_array_index(table->memory_info, struct heart_memory_info *, i);
-
-                               if (mi->max_rss || mi->avg_rss)
-                                       time++;
-
-                               if (max_rss < mi->max_rss)
-                                       max_rss = mi->max_rss;
-
-                               avg_rss += mi->avg_rss;
-                       }
-
-                       if (time)
-                               avg_rss /= time;
-               }
-
-               md->max_rss = max_rss;
-               md->avg_rss = avg_rss;
-               g_array_append_val(arrays, md);
-       }
-
-       ret = pthread_mutex_unlock(&heart_memory_mutex);
-       if (ret) {
-               _E("pthread_mutex_unlock() failed, %d", ret);
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       return RESOURCED_ERROR_NONE;
-
-unlock_out_of_memory_exit:
-       ret = pthread_mutex_unlock(&heart_memory_mutex);
-       if (ret) {
-               _E("pthread_mutex_unlock() failed, %d", ret);
-               return RESOURCED_ERROR_FAIL;
-       }
-       return RESOURCED_ERROR_OUT_OF_MEMORY;
-}
-
-void heart_memory_update(struct logging_table_form *data, void *user_data)
-{
-       int ret;
-       unsigned int rss;
-       time_t curr_time = logging_get_time(CLOCK_BOOTTIME);
-       struct heart_memory_table *find;
-       struct heart_memory_table *table;
-
-       if (sscanf(data->data, "%u", &rss) < 0) {
-               _E("sscanf failed");
-               return;
-       }
-
-       find = heart_memory_find_info(heart_memory_app_list, data->appid);
-
-       /* get last node and update it & re-insert to hash table  */
-       /* update */
-       if (find) {
-               ret = pthread_mutex_lock(&heart_memory_mutex);
-               if (ret) {
-                       _E("pthread_mutex_lock() failed, %d", ret);
-                       return;
-               }
-
-               if (find->renew) {
-                       find->count = 0;
-                       find->max_rss = 0;
-                       find->total_rss = 0;
-                       find->renew = 0;
-               }
-
-               find->total_rss += rss;
-
-               if (find->max_rss < rss)
-                       find->max_rss = rss;
-
-               find->latest_rss = rss;
-
-               find->count++;
-
-               table = find;
-
-               ret = pthread_mutex_unlock(&heart_memory_mutex);
-               if (ret) {
-                       _E("pthread_mutex_unlock() failed, %d", ret);
-                       return;
-               }
-       } else {
-               table = malloc(sizeof(struct heart_memory_table));
-
-               if (!table) {
-                       _E("malloc failed");
-                       return;
-               }
-
-               if (snprintf(table->appid, MAX_APPID_LENGTH, "%s", data->appid) < 0) {
-                       free(table);
-                       _E("snprintf failed");
-                       return;
-               }
-
-               if (snprintf(table->pkgid, MAX_PKGNAME_LENGTH, "%s", data->pkgid) < 0) {
-                       free(table);
-                       _E("snprintf failed");
-                       return;
-               }
-
-               table->memory_info =
-                       g_array_new(false, false, sizeof(struct heart_memory_info *));
-
-               table->total_rss = rss;
-
-               table->max_rss = rss;
-
-               table->latest_rss = rss;
-
-               table->count = 1;
-
-               ret = pthread_mutex_lock(&heart_memory_mutex);
-               if (ret) {
-                       free(table);
-                       _E("pthread_mutex_lock() failed, %d", ret);
-                       return;
-               }
-
-               g_hash_table_insert(heart_memory_app_list, (gpointer)table->appid, (gpointer)table);
-
-               ret = pthread_mutex_unlock(&heart_memory_mutex);
-               if (ret) {
-                       _E("pthread_mutex_unlock() failed, %d", ret);
-                       return;
-               }
-       }
-
-       if (last_file_update_time + HEART_MEMORY_SAVE_INTERVAL < curr_time) {
-               /* all hash table update and make new array */
-               gpointer value;
-               gpointer key;
-               GHashTableIter iter;
-               struct heart_memory_table *search;
-               struct heart_memory_info *new_memory_info;
-
-               ret = pthread_mutex_lock(&heart_memory_mutex);
-               if (ret) {
-                       _E("pthread_mutex_lock() failed, %d", ret);
-                       return;
-               }
-
-               g_hash_table_iter_init(&iter, heart_memory_app_list);
-
-               while (g_hash_table_iter_next(&iter, &key, &value)) {
-                       search = (struct heart_memory_table *)value;
-
-                       new_memory_info = malloc(sizeof(struct heart_memory_info));
-
-                       if (!new_memory_info) {
-                               ret = pthread_mutex_unlock(&heart_memory_mutex);
-                               if (ret) {
-                                       _E("pthread_mutex_lock() failed, %d", ret);
-                                       return;
-                               }
-                               _E("malloc failed");
-                               return;
-                       }
-
-                       /* make new array node */
-                       new_memory_info->max_rss = search->max_rss;
-
-                       if (search->count)
-                               new_memory_info->avg_rss = search->total_rss / search->count;
-                       else
-                               new_memory_info->avg_rss = search->total_rss;
-
-                       new_memory_info->max_rss = search->max_rss;
-
-                       search->renew = 1;
-
-                       /* hashtable sliding : remove last node and make new one */
-                       g_array_remove_index(search->memory_info, MEM_ARRAY_MAX-1);
-                       g_array_prepend_val(search->memory_info, new_memory_info);
-               }
-
-               ret = pthread_mutex_unlock(&heart_memory_mutex);
-               if (ret) {
-                       _E("pthread_mutex_unlock() failed, %d", ret);
-                       return;
-               }
-               /* rewrite hashtable list file */
-               ret = heart_memory_save_to_file(heart_memory_app_list, HEART_MEMORY_FILE);
-               if (ret) {
-                       _E("save to file failed");
-                       return;
-               }
-
-               last_file_update_time = curr_time;
-       }
-}
-
-static int heart_memory_write(char *appid, char *pkgid, struct proc_status *p_data)
-{
-       _cleanup_free_ char *info = NULL;
-       unsigned int usage = 0;
-       int ret;
-       struct proc_app_info *pai = p_data->pai;
-
-       /* For write to data crud during period */
-       /* write memory usage in proc_list */
-       ret = proc_get_mem_usage(p_data->pid, &usage);
-       if (ret < 0) {
-               _E("Failed to get PID(%d) rss: %m", p_data->pid);
-               return ret;
-       }
-
-       if (pai && pai->childs) {
-               unsigned int child_usage;
-               GSList *iterchild;
-
-               gslist_for_each_item(iterchild, pai->childs) {
-                       pid_t child = GPOINTER_TO_PID(iterchild->data);
-                       ret = proc_get_mem_usage(child, &child_usage);
-                       if (ret < 0) {
-                               _E("Failed to get PID(%d) rss: %m", child);
-                               continue;
-                       }
-                       usage += child_usage;
-               }
-       }
-
-       _SD("memory write : %s(%d), usage %u", appid, p_data->pid, usage);
-       ret = asprintf(&info, "%u", usage);
-       if (ret < 0) {
-               _E("Failed to allocate memory");
-               return -ENOMEM;
-       }
-
-       ret = logging_write(p_data->pid, MEM_NAME, appid, pkgid, time(NULL), info);
-
-       if (ret)
-               _E("logging_write failed %d", ret);
-
-       return ret;
-}
-
-static int heart_memory_state_cb(void *data)
-{
-       int ret;
-       char *appid, *pkgid;
-       struct proc_status *ps = (struct proc_status *)data;
-
-       ret = proc_get_id_info(ps, &appid, &pkgid);
-       if (ret != RESOURCED_ERROR_NONE) {
-               _E("Failed to proc_get_id_info");
-               return ret;
-       }
-
-       heart_memory_write(appid, pkgid, ps);
-
-       return RESOURCED_ERROR_NONE;
-}
-
-static gboolean heart_memory_notify(gpointer data)
-{
-       resourced_notify(RESOURCED_NOTIFIER_LOGGING_START, NULL);
-
-       return true;
-}
-
-static void dbus_get_memory_latest(GDBusMethodInvocation *invocation, GVariant *params)
-{
-       int ret;
-       char *appid = NULL;
-       unsigned int rss = 0;
-
-       do_expr_unless_g_variant_get_typechecked(goto failure, params, "(&s)", &appid);
-       if (!appid) {
-               _E("Wrong message arguments!");
-               goto failure;
-       }
-
-       ret = heart_memory_get_latest_data(appid, &rss);
-
-       if (ret) {
-               _E("heart_memory_get_latest_data failed %d", ret);
-               goto failure;
-       }
-
-       g_dbus_method_invocation_return_value(invocation, g_variant_new("(u)", rss));
-       return;
-
-failure:
-       D_BUS_REPLY_ERR(invocation);
-}
-
-static void dbus_get_memory_data(GDBusMethodInvocation *invocation, GVariant *params)
-{
-       int period = -1;
-       char *appid = NULL;
-       struct heart_memory_data *md;
-
-       do_expr_unless_g_variant_get_typechecked(goto failure, params, "(&si)", &appid, &period);
-       if (!appid || period < 0) {
-               _E("Wrong message arguments!");
-               goto failure;
-       }
-
-       md = heart_memory_get_data(appid, period);
-       if (!md) {
-               _E("heart_memory_get_data failed");
-               goto failure;
-       }
-
-       g_dbus_method_invocation_return_value(invocation, g_variant_new("(uu)", md->max_rss, md->avg_rss));
-
-       free(md);
-       return;
-
-failure:
-       D_BUS_REPLY_ERR(invocation);
-}
-
-static void dbus_get_memory_data_list(GDBusMethodInvocation *invocation, GVariant *params)
-{
-       int i, ret, period = -1;
-       char *appid, *pkgid;
-       GArray *temp_array;
-       GVariantBuilder builder, *sub_builder;
-
-       do_expr_unless_g_variant_get_typechecked(goto failure, params, "(i)", &period);
-       if (period < 0) {
-               _E("Wrong message arguments!");
-               goto failure;
-       }
-
-       temp_array = g_array_new(false, false, sizeof(struct heart_memory_data *));
-
-       ret = heart_memory_get_table(temp_array, period);
-
-       if (ret) {
-               _E("heart_memory_get_table failed %d", ret);
-               goto failure;
-       }
-
-       g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
-       sub_builder = g_variant_builder_new(G_VARIANT_TYPE("a(ssuu)"));
-
-       for (i = 0; i < temp_array->len; i++) {
-               struct heart_memory_data *md;
-
-               md = g_array_index(temp_array, struct heart_memory_data *, i);
-
-               appid = md->appid;
-               pkgid = md->pkgid;
-
-               g_variant_builder_add(sub_builder, "(ssuu)", appid, pkgid, md->max_rss, md->avg_rss);
-       }
-       g_variant_builder_add_value(&builder, g_variant_new("a(ssuu)", sub_builder));
-       g_variant_builder_unref(sub_builder);
-
-       g_dbus_method_invocation_return_value(invocation, g_variant_builder_end(&builder));
-
-       g_array_free(temp_array, true);
-       return;
-
-failure:
-       D_BUS_REPLY_ERR(invocation);
-}
-
-static void dbus_get_memorydb(GDBusMethodInvocation *invocation, GVariant *params)
-{
-       int i, period = -1;
-       char *appid, *pkgid;
-       GArray *temp_array;
-       GVariantBuilder builder, *sub_builder;
-
-       do_expr_unless_g_variant_get_typechecked(goto failure, params, "(i)", &period);
-       if (period < 0) {
-               _E("Wrong message arguments!");
-               goto failure;
-       }
-
-       temp_array = g_array_new(false, false, sizeof(struct heart_memory_data *));
-       _E("start get read query!!! %ld", time(NULL));
-       heart_memory_get_query(temp_array, period);
-       _E("end get read query!!! %ld", time(NULL));
-
-       g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
-       sub_builder = g_variant_builder_new(G_VARIANT_TYPE("a(ssuu)"));
-
-       for (i = 0; i < temp_array->len; i++) {
-               struct heart_memory_data *md;
-
-               md = g_array_index(temp_array, struct heart_memory_data *, i);
-
-               appid = md->appid;
-               pkgid = md->pkgid;
-
-               g_variant_builder_add(sub_builder, "(ssuu)", appid, pkgid, md->max_rss, md->avg_rss);
-       }
-       g_variant_builder_add_value(&builder, g_variant_new("a(ssuu)", sub_builder));
-       g_variant_builder_unref(sub_builder);
-
-       g_dbus_method_invocation_return_value(invocation, g_variant_builder_end(&builder));
-
-       g_array_free(temp_array, true);
-       return;
-
-failure:
-       D_BUS_REPLY_ERR(invocation);
-}
-
-static void dbus_get_memoryforeach(GDBusMethodInvocation *invocation, GVariant *params)
-{
-       int i, period = -1;
-       char *appid, *pkgid;
-       GArray *temp_array;
-       GVariantBuilder builder, *sub_builder;
-
-       do_expr_unless_g_variant_get_typechecked(goto failure, params, "(i)", &period);
-       if (period < 0) {
-               _E("Wrong message arguments!");
-               goto failure;
-       }
-
-       /* read from query */
-       temp_array = g_array_new(false, false, sizeof(struct heart_memory_data *));
-       _E("start get read foreach!!! %ld", time(NULL));
-       logging_memory_get_foreach(temp_array, period);
-       _E("end get read foreach!!! %ld", time(NULL));
-
-       g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
-       sub_builder = g_variant_builder_new(G_VARIANT_TYPE("a(ssuu)"));
-
-       for (i = 0; i < temp_array->len; i++) {
-               struct heart_memory_data *md;
-
-               md = g_array_index(temp_array, struct heart_memory_data *, i);
-
-               appid = md->appid;
-               pkgid = md->pkgid;
-
-               g_variant_builder_add(sub_builder, "(ssuu)", appid, pkgid, md->max_rss, md->avg_rss);
-       }
-       g_variant_builder_add_value(&builder, g_variant_new("a(ssuu)", sub_builder));
-       g_variant_builder_unref(sub_builder);
-
-       g_dbus_method_invocation_return_value(invocation, g_variant_builder_end(&builder));
-
-       g_array_free(temp_array, true);
-       return;
-
-failure:
-       D_BUS_REPLY_ERR(invocation);
-}
-
-static void dbus_memory_save_to_file(GDBusMethodInvocation *invocation, GVariant *params)
-{
-       int ret;
-
-       ret = heart_memory_save_to_file(heart_memory_app_list, HEART_MEMORY_FILE);
-
-       if (ret) {
-               _E("save to file failed");
-               D_BUS_REPLY_ERR(invocation);
-               return;
-       }
-
-       g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", ret));
-}
-
-static const char dbus_methods_xml[] =
-"              <method name='GetMemoryLatest'>"
-"                      <arg type='s' name='Appid' direction='in'/>"
-"                      <arg type='u' name='Rss' direction='out'/>"
-"              </method>"
-"              <method name='GetMemoryData'>"
-"                      <arg type='s' name='Appid' direction='in'/>"
-"                      <arg type='i' name='Period' direction='in'/>"
-"                      <arg type='u' name='MaxRss' direction='out'/>"
-"                      <arg type='u' name='AvgRss' direction='out'/>"
-"              </method>"
-"              <method name='GetMemoryDataList'>"
-"                      <arg type='i' name='Period' direction='in'/>"
-"                      <arg type='a(ssuu)' name='MemoryUsagePerApp' direction='out'/>"
-"              </method>"
-"              <method name='GetMemoryDB'>"
-"                      <arg type='i' name='Period' direction='in'/>"
-"                      <arg type='a(ssuu)' name='MemoryUsagePerApp' direction='out'/>"
-"              </method>"
-"              <method name='GetMemoryforeach'>"
-"                      <arg type='i' name='Period' direction='in'/>"
-"                      <arg type='a(ssuu)' name='MemoryUsagePerApp' direction='out'/>"
-"              </method>"
-"              <method name='SaveMemoryData'>"
-"                      <arg type='i' name='ZeroOnSuccess' direction='out'/>"
-"              </method>";
-
-static struct d_bus_method dbus_methods[] = {
-       { "GetMemoryLatest",   dbus_get_memory_latest },
-       { "GetMemoryData",     dbus_get_memory_data },
-       { "GetMemoryDataList", dbus_get_memory_data_list },
-       { "GetMemoryDB",       dbus_get_memorydb },
-       { "GetMemoryforeach",  dbus_get_memoryforeach },
-       { "SaveMemoryData",    dbus_memory_save_to_file },
-};
-
-static int heart_memory_init(void *data)
-{
-       int ret;
-
-       ret = logging_module_init(MEM_NAME, ONE_DAY, TEN_MINUTE, heart_memory_update, TEN_MINUTE, USER_DEFAULT);
-
-       if (ret != RESOURCED_ERROR_NONE) {
-               _E("logging module init failed");
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       if (!heart_memory_app_list) {
-               heart_memory_app_list = g_hash_table_new_full(
-                               g_str_hash,
-                               g_str_equal,
-                               NULL,
-                               heart_memory_free_value);
-
-               /* make hash from file */
-               ret = heart_memory_read_from_file(heart_memory_app_list, HEART_MEMORY_FILE);
-
-               if (ret == RESOURCED_ERROR_OUT_OF_MEMORY) {
-                       _E("heart_memory_init failed");
-                       return ret;
-               }
-       }
-
-       register_notifier(RESOURCED_NOTIFIER_SERVICE_LAUNCH, heart_memory_state_cb);
-       register_notifier(RESOURCED_NOTIFIER_APP_FOREGRD, heart_memory_state_cb);
-       register_notifier(RESOURCED_NOTIFIER_APP_BACKGRD, heart_memory_state_cb);
-
-       heart_dbus_declare_methods(dbus_methods_xml, dbus_methods, ARRAY_SIZE(dbus_methods));
-
-       last_file_update_time = logging_get_time(CLOCK_BOOTTIME);
-
-       if (heart_memory_update_timer == NULL) {
-               _D("logging memory update timer start");
-               heart_memory_update_timer = g_timeout_source_new_seconds(TEN_MINUTE);
-               g_source_set_callback(heart_memory_update_timer, heart_memory_notify, NULL, NULL);
-               g_source_attach(heart_memory_update_timer, NULL);
-       }
-
-       heart_memory_get_data_func = heart_memory_get_data;
-
-       _D("heart memory init finished");
-       return RESOURCED_ERROR_NONE;
-}
-
-static int heart_memory_exit(void *data)
-{
-       int ret;
-
-       /* update timer delete */
-       g_source_destroy(heart_memory_update_timer);
-       heart_memory_update_timer = NULL;
-
-       unregister_notifier(RESOURCED_NOTIFIER_SERVICE_LAUNCH, heart_memory_state_cb);
-       unregister_notifier(RESOURCED_NOTIFIER_APP_FOREGRD, heart_memory_state_cb);
-       unregister_notifier(RESOURCED_NOTIFIER_APP_BACKGRD, heart_memory_state_cb);
-
-       if (heart_memory_app_list) {
-               ret = heart_memory_save_to_file(heart_memory_app_list, HEART_MEMORY_FILE);
-
-               if (ret)
-                       _E("save file failed %d", ret);
-
-               if (heart_memory_app_list) {
-                       gpointer value;
-                       gpointer key;
-                       GHashTableIter iter;
-
-                       g_hash_table_iter_init(&iter, heart_memory_app_list);
-
-                       while (g_hash_table_iter_next(&iter, &key, &value)) {
-                               struct heart_memory_table *table = (struct heart_memory_table *)value;
-
-                               if (table->memory_info)
-                                       g_array_free(table->memory_info, true);
-                       }
-
-                       g_hash_table_destroy(heart_memory_app_list);
-               }
-       }
-
-       heart_memory_get_data_func = NULL;
-
-       logging_module_exit();
-       _D("heart memory exit");
-       return RESOURCED_ERROR_NONE;
-}
-
-static const struct heart_module_ops heart_memory_ops = {
-       .name           = "MEMORY",
-       .init           = heart_memory_init,
-       .exit           = heart_memory_exit,
-};
-HEART_MODULE_REGISTER(&heart_memory_ops)
diff --git a/src/resource-monitor/storage/heart-storage.c b/src/resource-monitor/storage/heart-storage.c
deleted file mode 100644 (file)
index 42d8f03..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * resourced
- *
- * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * @file heart-storage.c
- *
- * @desc heart storage module
- *
- * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
- *
- */
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <glib.h>
-#include <stdbool.h>
-#include <time.h>
-
-#include "resourced.h"
-#include "trace.h"
-#include "module.h"
-#include "macro.h"
-#include "notifier.h"
-#include "heart.h"
-#include "logging.h"
-#include "heart-common.h"
-#include "dbus-handler.h"
-#include "proc-common.h"
-
-#include <sqlite3.h>
-
-#define STORAGE_NAME           "storage"
-
-static bool heart_storage_initailized = false;
-
-static void dbus_insert_log(GDBusMethodInvocation *invocation, GVariant *params)
-{
-       int ret;
-       int pid = 0;
-       char *pkgid = NULL;
-       char *data = NULL;
-       struct proc_app_info *pai;
-
-       do_expr_unless_g_variant_get_typechecked(goto finish, params, "(&s&s)", &pkgid, &data);
-       if (!pkgid) {
-               _E("Wrong message arguments!");
-               goto finish;
-       }
-
-       pai = find_app_info_by_appid(pkgid);
-       if (!pai) {
-               _E("Failed to find the app info of %s", pkgid);
-               goto finish;
-       }
-
-       pid = pai->main_pid;
-
-       _SD("Insert record (%s, %s)", pkgid, data);
-       ret = logging_write(pid, STORAGE_NAME, pkgid, pkgid, time(NULL), data);
-       if (ret != RESOURCED_ERROR_NONE)
-               _E("Write request failed");
-
-finish:
-       g_dbus_method_invocation_return_value(invocation, NULL);
-}
-
-static const char dbus_methods_xml[] =
-"              <method name='Insert'>"
-"                      <arg type='s' name='Pkgid' direction='in'/>"
-"                      <arg type='s' name='UserData' direction='in'/>"
-"              </method>";
-
-static struct d_bus_method dbus_methods[] = {
-       { "Insert", dbus_insert_log },
-};
-
-static bool is_storage_logging(void)
-{
-       static const struct module_ops *block;
-
-       if (!block) {
-               block = find_module("block");
-               if (block)
-                       heart_storage_initailized = true;
-       }
-
-       return heart_storage_initailized;
-}
-
-static int heart_storage_write(void *data)
-{
-       int ret;
-       struct logging_data *ld = (struct logging_data *)data;
-
-       ret = logging_write(ld->pid, STORAGE_NAME, ld->appid, ld->pkgid, time(NULL), ld->data);
-       return ret;
-}
-
-static int heart_storage_init(void *data)
-{
-       int ret;
-
-       if (!is_storage_logging())
-               return RESOURCED_ERROR_UNINITIALIZED;
-
-       ret = logging_module_init(STORAGE_NAME, FOUR_MONTH, FIVE_MINUTE, NULL, 0, USER_OWN);
-       if (ret != RESOURCED_ERROR_NONE) {
-               _E("logging module init failed");
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       heart_dbus_declare_methods(dbus_methods_xml, dbus_methods, ARRAY_SIZE(dbus_methods));
-
-       register_notifier(RESOURCED_NOTIFIER_LOGGING_WRITE, heart_storage_write);
-       return RESOURCED_ERROR_NONE;
-}
-
-static int heart_storage_exit(void *data)
-{
-       if (!heart_storage_initailized)
-               return RESOURCED_ERROR_NONE;
-
-       _D("heart_storage exit");
-       unregister_notifier(RESOURCED_NOTIFIER_LOGGING_WRITE, heart_storage_write);
-       logging_module_exit();
-       return RESOURCED_ERROR_NONE;
-}
-
-static const struct heart_module_ops heart_storage_ops = {
-       .name           = "STORAGE",
-       .init           = heart_storage_init,
-       .exit           = heart_storage_exit,
-};
-HEART_MODULE_REGISTER(&heart_storage_ops)
diff --git a/src/resource-optimizer/memory/compaction.c b/src/resource-optimizer/memory/compaction.c
new file mode 100644 (file)
index 0000000..cde73aa
--- /dev/null
@@ -0,0 +1,710 @@
+/*
+ * resourced:compaction
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <glib.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+#include <sys/syscall.h>
+
+#include "config-parser.h"
+#include "module.h"
+#include "macro.h"
+#include "memory-cgroup.h"
+#include "notifier.h"
+#include "procfs.h"
+#include "resourced.h"
+#include "trace.h"
+#include "util.h"
+#include "compact-common.h"
+
+/**
+ * State bit for zone's fragmentation warning
+ * ZONE_FRAG_WARN_RAISE bit is set for each zone
+ * when the fragmentation level reaches specified
+ * value for at least one of supported page orders.
+ */
+#define ZONE_FRAG_WARN_RAISE   (0x1 << 0)
+
+/* Internal compaction module states */
+#define COMPACT_IDLE           (0)
+/* State NOTIFIED is to eliminate spurious thread wakeups */
+#define COMPACT_NOTIFIED       (1 << 0)
+/* Failed to write to procfs entry */
+#define COMPACT_FAILURE                (1 << 1)
+/**
+ * Failed to perform one of the basic operations:
+ * like reading /proc/zoneinfo or /proc/pagetypeinfo
+ * Set to indicate that there is no point of return
+ * and that the compaction thread should/can safely
+ * clean things up and call it a day.
+ **/
+#define COMPACT_WITHDRAW       (1 << 2)
+/**
+ * Set when compaction module has been explicitly
+ * requested to quit
+ */
+#define COMPACT_CANCEL         (1 << 3)
+#define COMPACT_SKIP           (COMPACT_WITHDRAW | COMPACT_CANCEL)
+
+#define MAX_PAGE_ORDER         0xa
+#define ZONE_MAX_NR            4
+
+#define PROC_COMPACT_ENTRY     "/proc/sys/vm/compact_memory"
+#define COMPACT_CONF_FILE                   RD_CONFIG_FILE(optimizer)
+
+#define COMPACT_CONFIG_SECTION "Compaction"
+#define COMPACT_CONFIG_ENABLE  "CompactEnable"
+#define COMPACT_CONFIG_FRAG    "Fraglevel"
+
+/**
+ * Default frag level (percentage, order-based) which determines
+ * when to trigger compaction.
+ */
+#define COMPACT_DEF_FRAG_LEVEL 800 /* 80% */
+
+/*
+ * Note: Tightly coupled with corresponding ids.
+ * Mind while modifying.
+ */
+static const char *zone_names[]        = {"Normal", "DMA", "HighMem", "DMA32"};
+
+struct parser_data {
+       struct memory_info      *mem_info;
+       struct zone_info        *zone;
+};
+
+struct zone_info {
+       unsigned int            id;
+       unsigned long           pages_per_order[MAX_PAGE_ORDER +1];
+       unsigned long           free_pages;
+       unsigned long           wm_min;
+       unsigned long           wm_low;
+       unsigned long           wm_high;
+       unsigned long           managed;
+       unsigned int            frag_map:MAX_PAGE_ORDER+1;
+       unsigned int            frag_warn:2;
+};
+
+struct memory_info {
+       unsigned int            zone_count;
+       struct zone_info        zones[ZONE_MAX_NR];
+};
+
+struct compact_control {
+       struct memory_info      *mem_info;
+       pthread_t               compact_thread;
+       pthread_mutex_t         lock;
+       int             frag_level;
+       unsigned int            status;
+       unsigned int            compact_type;
+};
+
+#define PARSE_TAG(exp, fn, id)         \
+       {                               \
+               .re_exp  = exp,         \
+               .callback = fn,         \
+               .tag = PARSE_TAG_##id,  \
+       }
+
+#define PARSE_TAG_EMPTY()  {0,}
+
+/*
+ * @TODO: This should be attached to module ops
+ */
+struct compact_data {
+       struct compact_control *compact;
+       pthread_mutex_t notify_lock;
+       pthread_cond_t  notify;
+       pthread_mutex_t drained_lock;
+       pthread_cond_t  drained;
+};
+
+static struct compact_data compact_data = {
+       .notify_lock    = PTHREAD_MUTEX_INITIALIZER,
+       .notify         = PTHREAD_COND_INITIALIZER,
+       .drained_lock   = PTHREAD_MUTEX_INITIALIZER,
+       .drained        = PTHREAD_COND_INITIALIZER
+};
+
+static inline unsigned int get_zone_id(const char *zone_name, size_t len)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(zone_names); ++i) {
+               if (!strncmp(zone_name, zone_names[i], len))
+                       return 1 << i;
+       }
+       return 0;
+}
+
+static inline const char *get_zone_name(unsigned int zone_id)
+{
+       unsigned int i = ffs(zone_id) - 1;
+
+       return (i < ARRAY_SIZE(zone_names)) ? zone_names[i] : NULL;
+}
+
+/*
+ * External fragmentation is an issue but one that mostly kernel
+ * should be concerned about, not the user space.
+ * Still though, fragmented *physical* memory may (but does not
+ * have to) lead to system getting less responsive - as the kernel
+ * might get trapped waiting for allocation of high-order
+ * physically-contiguous pages. The fragmentation issue gets more
+ * significant in case of huge pages - thought this is left aside
+ * due to not being relevant, in this particular case.
+ *
+ * Triggering the compaction from the user-space is a rather
+ * nasty hack. But if this is to be done, than...
+ * 1. There is not much point in triggering compaction if
+ *    the system is already at a heavy memory pressure
+ *    and it is struggling to satisfy 0-order allocations
+ * 2. Specifying the overall fragmentation level is quite tricky
+ *    and without some decent background of what is/has been going
+ *    on as far as memory allocations are being concern (both from
+ *    user-space and from the kernel) is not really reliable, to say
+ *    at least. All in all, what's the acceptable (whatever it means)
+ *    level for external fragmentation? Having most of the available
+ *    memory within the low-order page blocks should raise an alert,
+ *    but that's only in theory. Things get more complicated when taking
+ *    into consideration the migration types of available pages.
+ *    This might go wrong in so many ways .....
+ *    Shall this be continued ?
+ */
+static void compaction_start(struct compact_control *compact)
+{
+       struct memory_info *mem_info;
+       int current_status = COMPACT_IDLE;
+       _cleanup_close_ int fd = -1;
+       int n = 1;
+
+       pthread_mutex_lock(&compact->lock);
+
+       if (compact->status & COMPACT_SKIP)
+               current_status |= COMPACT_WITHDRAW;
+
+       pthread_mutex_unlock(&compact->lock);
+
+       if (current_status & COMPACT_WITHDRAW)
+               return;
+
+       mem_info = compact->mem_info;
+
+
+       fd = open(PROC_COMPACT_ENTRY,  O_WRONLY);
+       if (fd < 0) {
+               if (errno == EACCES || errno == EFAULT || errno == ENOENT)
+                       current_status |= COMPACT_WITHDRAW;
+               _E("Compaction: failed to open procfs entry [%d]\n", errno);
+               goto leave;
+       }
+       /*
+        * It doesn't really matter what gets written,
+        * as long as smth gets....
+        */
+       if (write(fd, &n, sizeof(n)) <= 0)
+               current_status |= COMPACT_FAILURE;
+       /*
+        * Reset the external fragmentation warnings.
+        * Locking is not required here as all updates will get suspended
+        * until the compaction status won't indicate all is done here
+        */
+       if (current_status & COMPACT_FAILURE)
+               goto leave;
+
+       for (n = 0; n < mem_info->zone_count; ++n)
+               mem_info->zones[n].frag_warn &= ~ZONE_FRAG_WARN_RAISE;
+leave:
+
+       pthread_mutex_lock(&compact->lock);
+       compact->status |= current_status;
+       pthread_mutex_unlock(&compact->lock);
+}
+
+static void compact_validate_zone(struct zone_info *zone,
+                                 unsigned int frag_level,
+                                 struct memory_info *mem_info)
+{
+       int order, req_order;
+       unsigned int current_frag_map = 0;
+       /*
+        * Skip compaction if the system is below the low watermark.
+        * It's gonna be done either way
+        */
+       if (zone->free_pages < zone->wm_low) {
+               _I("Skipping validation due to falling below the low watermark\n");
+               _I("Zone %s: number of free pages: %lu low watermark: %lu\n",
+                               get_zone_name(zone->id),
+                               zone->free_pages, zone->wm_low);
+               return;
+       }
+
+       for (req_order = 1; req_order <= MAX_PAGE_ORDER; ++req_order) {
+               unsigned long available_pages = 0;
+
+               for (order = req_order; order <= MAX_PAGE_ORDER; ++order)
+                       available_pages += zone->pages_per_order[order] << order;
+
+               if (zone->free_pages > 0 && (1000 - (available_pages * 1000 / zone->free_pages)) >= frag_level)
+                       current_frag_map |= 1 << req_order;
+       }
+
+       if (current_frag_map) {
+
+               if ((!zone->frag_map && current_frag_map) ||
+                   ((zone->frag_map ^ current_frag_map) &&
+                   !((zone->frag_map ^ current_frag_map) & zone->frag_map)))
+
+                       zone->frag_warn |= ZONE_FRAG_WARN_RAISE;
+       }
+
+       zone->frag_map = current_frag_map;
+}
+
+static void compaction_verify_zone(struct compact_control *compact,
+                                  struct zone_info *zone)
+{
+       struct memory_info *mem_info = compact->mem_info;
+
+       /*
+        * Here comes the shady part:
+        * without some decent memory tracing here it is
+        * truly difficult to determine whether the compaction
+        * is required or not.
+        */
+       compact_validate_zone(zone, compact->frag_level, mem_info);
+}
+
+static void compaction_verify(struct compact_control *compact)
+{
+       /* Get the overall idea of current external fragmentation */
+       struct memory_info *mem_info = compact->mem_info;
+       unsigned int compact_targets = 0;
+       int n;
+
+       /*
+        * Verify each zone although the compaction can be
+        * triggered per node (or globally) only.
+        */
+       for (n = 0; n < mem_info->zone_count; ++n) {
+               struct zone_info *zone = &mem_info->zones[n];
+
+               /*
+                * Some devices make a zone but don't allocate any pages for it.
+                * We can ignore these empty zones.
+                */
+               if (zone->managed <= 0)
+                       continue;
+
+               compaction_verify_zone(compact, zone);
+               if (zone->frag_warn & ZONE_FRAG_WARN_RAISE) {
+                       /*
+                        * As the compaction can be triggered either globally
+                        * or on per-node it's enough to have at least one
+                        * zone for which the external fragmentation got
+                        * dangerously high. Still to have a minimum control
+                        * over the whole process - validate all zones.
+                        */
+                       ++compact_targets;
+               }
+       }
+
+       if (compact_targets)
+               compaction_start(compact);
+}
+
+
+#define compact_zoneinfo_set(zone, _off, v) \
+       (*(typeof(v)*)(((char*)(zone)) + _off) = v)
+
+
+static int compact_parse_zone(const char *s, regmatch_t *match,
+                               unsigned int parse_tag, void *data)
+{
+       struct parser_data *parser_data = (struct parser_data *)data;
+       unsigned int zone_id;
+       struct zone_info *zone;
+
+       if (parse_tag != PARSE_TAG_ZONE)
+               return -EINVAL;
+
+       zone_id = get_zone_id(s + match[1].rm_so,
+                                match[1].rm_eo - match[1].rm_so);
+       zone = parser_data->mem_info->zones;
+
+       if (!zone_id)
+               return -EINVAL;
+
+       while (zone->id && zone->id != zone_id)
+               ++zone;
+
+       if (!zone->id) {
+               ++parser_data->mem_info->zone_count;
+               zone->id = zone_id;
+       }
+
+       parser_data->zone = zone;
+       return 0;
+}
+
+static int compact_parse_zoneinfo(const char *s, regmatch_t *match,
+                                 unsigned int parse_tag,
+                                 void *data)
+{
+       struct parser_data *parser_data = (struct parser_data *)data;
+       char *e;
+       unsigned long v;
+
+       v = strtoul(s + match[1].rm_so, &e, 0);
+       if (!(s != e))
+               return -EINVAL;
+
+       switch (parse_tag) {
+       case PARSE_TAG_WM_MIN:
+               compact_zoneinfo_set(parser_data->zone,
+                               offsetof(struct zone_info, wm_min), v);
+               break;
+       case PARSE_TAG_WM_LOW:
+               compact_zoneinfo_set(parser_data->zone,
+                               offsetof(struct zone_info, wm_low), v);
+
+               break;
+       case PARSE_TAG_WM_HIGH:
+               compact_zoneinfo_set(parser_data->zone,
+                               offsetof(struct zone_info, wm_high), v);
+               break;
+       case PARSE_TAG_MANAGED:
+               compact_zoneinfo_set(parser_data->zone,
+                               offsetof(struct zone_info, managed), v);
+               break;
+       }
+       return 0;
+}
+
+static int compact_parse_pages(const char *s, regmatch_t *match,
+                               unsigned int parse_tag, void *data)
+{
+       struct parser_data *parser_data = (struct parser_data *)data;
+       char *e;
+       unsigned long v, page_count = 0;
+       int order;
+
+       if (parse_tag != PARSE_TAG_PAGE_COUNT)
+               return -EINVAL;
+
+       for (order = 0; order < MAX_PAGE_ORDER; ++order) {
+
+               v = strtoul(s, &e, 0);
+               if (!(s != e))
+                       return -EINVAL;
+               parser_data->zone->pages_per_order[order] = v;
+               page_count += v << order;
+               s = e;
+       }
+
+       if (parser_data->zone->free_pages != page_count) {
+               /*
+                * The drop of number of available pages is being handled
+                * on a per-order basis, thought this might be a good point
+                * to validate the zone's watermarks
+                */
+               parser_data->zone->free_pages = page_count;
+       }
+       return 0;
+}
+
+static int compact_get_buddyinfo(struct compact_control *compact)
+{
+       const struct parse_arg args[] = {
+               PARSE_TAG("zone[[:blank:]]+(Normal|DMA|DMA32|HighMem)",
+                       compact_parse_zone, ZONE),
+               PARSE_TAG("([[:blank:]]+([0-9]+))+",
+                       compact_parse_pages, PAGE_COUNT),
+               PARSE_TAG_EMPTY(),
+       };
+
+       struct parser_data parser_data = {
+               .mem_info = compact->mem_info,
+               .zone = &compact->mem_info->zones[0],
+       };
+
+       return proc_parse_buddyinfo(args, &parser_data);
+}
+
+static int compact_get_zoneinfo(struct compact_control *compact)
+{
+       const struct parse_arg args[] = {
+               PARSE_TAG("zone[[:blank:]]+(Normal|DMA|DMA32|HighMem)",
+                         compact_parse_zone, ZONE),
+               PARSE_TAG("min[[:blank:]]+([0-9]+)\n",
+                         compact_parse_zoneinfo, WM_MIN),
+               PARSE_TAG("low[[:blank:]]+([0-9]+)\n",
+                         compact_parse_zoneinfo, WM_LOW),
+               PARSE_TAG("high[[:blank:]]+([0-9]+)\n",
+                         compact_parse_zoneinfo, WM_HIGH),
+               PARSE_TAG("managed[[:blank:]]+([0-9]+)\n",
+                         compact_parse_zoneinfo, MANAGED),
+               PARSE_TAG_EMPTY(),
+       };
+
+       struct parser_data parser_data = {
+               .mem_info = compact->mem_info,
+               .zone = &compact->mem_info->zones[0],
+       };
+       return proc_parse_zoneinfo(args, &parser_data);
+}
+
+static void compact_track_frag_level(struct compact_control *compact)
+{
+       int woken = 1;
+
+       do {
+               /* Eliminate updates on spurious wake-ups */
+               if (woken) {
+                       compact_get_buddyinfo(compact);
+                       compaction_verify(compact);
+               }
+
+               pthread_mutex_lock(&compact_data.notify_lock);
+               pthread_cond_wait(&compact_data.notify,
+                               &compact_data.notify_lock);
+               pthread_mutex_unlock(&compact_data.notify_lock);
+
+               pthread_mutex_lock(&compact->lock);
+               woken = compact->status & COMPACT_NOTIFIED ? 1 : 0;
+               compact->status &= ~COMPACT_NOTIFIED;
+               pthread_mutex_unlock(&compact->lock);
+
+       } while (!(compact->status & COMPACT_SKIP));
+
+}
+
+static int compact_mem_state_changed(void *data)
+{
+       struct compact_control *compact;
+       struct memory_info *mem_info;
+       int result = RESOURCED_ERROR_NONE;
+
+       pthread_mutex_lock(&compact_data.drained_lock);
+       compact = compact_data.compact;
+       mem_info = compact ? compact->mem_info : NULL;
+       if (mem_info) {
+               int new_state = *((int *)data);
+
+               if (new_state < MEM_LEVEL_HIGH || new_state >= MEM_LEVEL_MAX) {
+                       result = RESOURCED_ERROR_FAIL;
+                       goto leave;
+               }
+
+               pthread_mutex_lock(&compact_data.compact->lock);
+               if (!(compact->status & COMPACT_SKIP)) {
+                       compact->status |= COMPACT_NOTIFIED;
+                       pthread_cond_signal(&compact_data.notify);
+               }
+               pthread_mutex_unlock(&compact_data.compact->lock);
+       }
+leave:
+       pthread_mutex_unlock(&compact_data.drained_lock);
+       return result;
+}
+
+static void compact_cleanup(struct compact_control *compact)
+{
+       struct memory_info *mem_info = compact->mem_info;
+
+       if (!(compact->status & COMPACT_SKIP))
+               _E("Invalid compact thread state [%d]\n", compact->status);
+
+       unregister_notifier(RESOURCED_NOTIFIER_MEM_LEVEL_CHANGED,
+                               compact_mem_state_changed);
+
+       (void) pthread_mutex_destroy(&compact->lock);
+
+       free(mem_info);
+       free(compact);
+}
+
+static void *compact_tracer(void *arg)
+{
+       struct compact_data *cdata = (struct compact_data *)arg;
+       struct compact_control *compact = cdata->compact;
+
+       if (compact_get_zoneinfo(compact) == RESOURCED_ERROR_NONE)
+               compact_track_frag_level(compact);
+
+       /* Dropped - so clean-up */
+       pthread_mutex_lock(&compact->lock);
+       compact->status |= COMPACT_WITHDRAW;
+       pthread_mutex_unlock(&compact->lock);
+
+       pthread_mutex_lock(&cdata->drained_lock);
+       compact_cleanup(compact);
+       cdata->compact = NULL;
+       pthread_mutex_unlock(&cdata->drained_lock);
+
+       pthread_cond_signal(&cdata->drained);
+
+       pthread_exit(NULL);
+}
+
+static int compact_parse_config_file(struct compact_control *compact)
+{
+       struct compact_conf *compact_conf = get_compact_conf();
+       if (!compact_conf) {
+               _E("Compact configuration should not be NULL");
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       if (!compact_conf->enable) {
+               (void) pthread_mutex_lock(&compact->lock);
+               compact->status |= COMPACT_SKIP;
+               (void) pthread_mutex_unlock(&compact->lock);
+
+               goto free_compact_conf;
+       }
+
+       if (compact_conf->frag_level > 0)
+               compact->frag_level = compact_conf->frag_level;
+
+       _I("[COMPACTION] compact status: %d", compact->status);
+       _I("[COMPACTION] compact frag_level: %d", compact->frag_level);
+
+free_compact_conf:
+       free_compact_conf();
+
+       return RESOURCED_ERROR_NONE;
+}
+
+static int compact_init(void *data)
+{
+       struct memory_info      *mem_info;
+       struct compact_control  *compact;
+       int result = RESOURCED_ERROR_OUT_OF_MEMORY;
+
+       _I("[COMPACTION] compact init");
+
+       pthread_mutex_lock(&compact_data.drained_lock);
+       if (compact_data.compact) {
+               _E("[COMPACTION] Unbalanced calls to compact module load/unload\n");
+               result = RESOURCED_ERROR_NONE;
+               goto leave;
+       }
+
+       compact = calloc(1, sizeof(*compact));
+       if (!compact)
+               goto leave;
+
+       mem_info = calloc(1, sizeof(*mem_info));
+       if (!mem_info)
+               goto cleanup;
+
+       compact->mem_info = mem_info;
+       compact->frag_level  = COMPACT_DEF_FRAG_LEVEL;
+
+       result = pthread_mutex_init(&compact->lock, NULL);
+       if (result) {
+               _E("[COMPACTION] Failed to init compact lock: %m");
+               goto cleanup_all;
+       }
+
+       /* Load configuration */
+       compact_parse_config_file(compact);
+
+       if (compact->status & COMPACT_SKIP) {
+               _I("[COMPACTION] Compaction module disabled.");
+               result = RESOURCED_ERROR_FAIL;
+               goto cleanup_all;
+       }
+
+       compact_data.compact = compact;
+
+       result = pthread_create(&compact->compact_thread, NULL,
+                       compact_tracer, (void*)&compact_data);
+       if (result) {
+               compact_data.compact = NULL;
+               goto cleanup_all;
+       }
+
+       pthread_detach(compact->compact_thread);
+       pthread_mutex_unlock(&compact_data.drained_lock);
+
+       register_notifier(RESOURCED_NOTIFIER_MEM_LEVEL_CHANGED,
+                                compact_mem_state_changed);
+       return RESOURCED_ERROR_NONE;
+
+cleanup_all:
+       free(mem_info);
+cleanup:
+       free(compact);
+leave:
+       pthread_mutex_unlock(&compact_data.drained_lock);
+       return result;
+}
+
+static int compact_exit(void *data)
+{
+       struct compact_control *compact;
+
+       pthread_mutex_lock(&compact_data.drained_lock);
+       compact = compact_data.compact;
+       compact_data.compact = NULL;
+
+       if (!compact)
+               goto leave;
+
+       pthread_mutex_lock(&compact->lock);
+       compact->status |= COMPACT_CANCEL;
+       pthread_mutex_unlock(&compact->lock);
+
+       pthread_cond_signal(&compact_data.notify);
+       pthread_cond_wait(&compact_data.drained, &compact_data.drained_lock);
+leave:
+       pthread_mutex_unlock(&compact_data.drained_lock);
+       return 0;
+}
+
+static int compact_runtime_support(void *data)
+{
+       _cleanup_close_ int fd = -1;
+
+       fd = open(PROC_COMPACT_ENTRY, O_WRONLY);
+       if (fd < 0) {
+               _E("Unable to open compaction procfs entry\n");
+               return RESOURCED_ERROR_NO_DATA;
+       }
+       return RESOURCED_ERROR_NONE;
+}
+
+static struct module_ops compact_module_ops = {
+       .priority               = MODULE_PRIORITY_LATE,
+       .name                   = "compact",
+       .init                   = compact_init,
+       .exit                   = compact_exit,
+       .check_runtime_support  = compact_runtime_support,
+};
+
+MODULE_REGISTER(&compact_module_ops)
+
diff --git a/src/resource-optimizer/memory/compaction/compaction.c b/src/resource-optimizer/memory/compaction/compaction.c
deleted file mode 100644 (file)
index cde73aa..0000000
+++ /dev/null
@@ -1,710 +0,0 @@
-/*
- * resourced:compaction
- *
- * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <glib.h>
-#include <time.h>
-#include <unistd.h>
-#include <sys/time.h>
-#include <sys/types.h>
-
-#include <sys/syscall.h>
-
-#include "config-parser.h"
-#include "module.h"
-#include "macro.h"
-#include "memory-cgroup.h"
-#include "notifier.h"
-#include "procfs.h"
-#include "resourced.h"
-#include "trace.h"
-#include "util.h"
-#include "compact-common.h"
-
-/**
- * State bit for zone's fragmentation warning
- * ZONE_FRAG_WARN_RAISE bit is set for each zone
- * when the fragmentation level reaches specified
- * value for at least one of supported page orders.
- */
-#define ZONE_FRAG_WARN_RAISE   (0x1 << 0)
-
-/* Internal compaction module states */
-#define COMPACT_IDLE           (0)
-/* State NOTIFIED is to eliminate spurious thread wakeups */
-#define COMPACT_NOTIFIED       (1 << 0)
-/* Failed to write to procfs entry */
-#define COMPACT_FAILURE                (1 << 1)
-/**
- * Failed to perform one of the basic operations:
- * like reading /proc/zoneinfo or /proc/pagetypeinfo
- * Set to indicate that there is no point of return
- * and that the compaction thread should/can safely
- * clean things up and call it a day.
- **/
-#define COMPACT_WITHDRAW       (1 << 2)
-/**
- * Set when compaction module has been explicitly
- * requested to quit
- */
-#define COMPACT_CANCEL         (1 << 3)
-#define COMPACT_SKIP           (COMPACT_WITHDRAW | COMPACT_CANCEL)
-
-#define MAX_PAGE_ORDER         0xa
-#define ZONE_MAX_NR            4
-
-#define PROC_COMPACT_ENTRY     "/proc/sys/vm/compact_memory"
-#define COMPACT_CONF_FILE                   RD_CONFIG_FILE(optimizer)
-
-#define COMPACT_CONFIG_SECTION "Compaction"
-#define COMPACT_CONFIG_ENABLE  "CompactEnable"
-#define COMPACT_CONFIG_FRAG    "Fraglevel"
-
-/**
- * Default frag level (percentage, order-based) which determines
- * when to trigger compaction.
- */
-#define COMPACT_DEF_FRAG_LEVEL 800 /* 80% */
-
-/*
- * Note: Tightly coupled with corresponding ids.
- * Mind while modifying.
- */
-static const char *zone_names[]        = {"Normal", "DMA", "HighMem", "DMA32"};
-
-struct parser_data {
-       struct memory_info      *mem_info;
-       struct zone_info        *zone;
-};
-
-struct zone_info {
-       unsigned int            id;
-       unsigned long           pages_per_order[MAX_PAGE_ORDER +1];
-       unsigned long           free_pages;
-       unsigned long           wm_min;
-       unsigned long           wm_low;
-       unsigned long           wm_high;
-       unsigned long           managed;
-       unsigned int            frag_map:MAX_PAGE_ORDER+1;
-       unsigned int            frag_warn:2;
-};
-
-struct memory_info {
-       unsigned int            zone_count;
-       struct zone_info        zones[ZONE_MAX_NR];
-};
-
-struct compact_control {
-       struct memory_info      *mem_info;
-       pthread_t               compact_thread;
-       pthread_mutex_t         lock;
-       int             frag_level;
-       unsigned int            status;
-       unsigned int            compact_type;
-};
-
-#define PARSE_TAG(exp, fn, id)         \
-       {                               \
-               .re_exp  = exp,         \
-               .callback = fn,         \
-               .tag = PARSE_TAG_##id,  \
-       }
-
-#define PARSE_TAG_EMPTY()  {0,}
-
-/*
- * @TODO: This should be attached to module ops
- */
-struct compact_data {
-       struct compact_control *compact;
-       pthread_mutex_t notify_lock;
-       pthread_cond_t  notify;
-       pthread_mutex_t drained_lock;
-       pthread_cond_t  drained;
-};
-
-static struct compact_data compact_data = {
-       .notify_lock    = PTHREAD_MUTEX_INITIALIZER,
-       .notify         = PTHREAD_COND_INITIALIZER,
-       .drained_lock   = PTHREAD_MUTEX_INITIALIZER,
-       .drained        = PTHREAD_COND_INITIALIZER
-};
-
-static inline unsigned int get_zone_id(const char *zone_name, size_t len)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(zone_names); ++i) {
-               if (!strncmp(zone_name, zone_names[i], len))
-                       return 1 << i;
-       }
-       return 0;
-}
-
-static inline const char *get_zone_name(unsigned int zone_id)
-{
-       unsigned int i = ffs(zone_id) - 1;
-
-       return (i < ARRAY_SIZE(zone_names)) ? zone_names[i] : NULL;
-}
-
-/*
- * External fragmentation is an issue but one that mostly kernel
- * should be concerned about, not the user space.
- * Still though, fragmented *physical* memory may (but does not
- * have to) lead to system getting less responsive - as the kernel
- * might get trapped waiting for allocation of high-order
- * physically-contiguous pages. The fragmentation issue gets more
- * significant in case of huge pages - thought this is left aside
- * due to not being relevant, in this particular case.
- *
- * Triggering the compaction from the user-space is a rather
- * nasty hack. But if this is to be done, than...
- * 1. There is not much point in triggering compaction if
- *    the system is already at a heavy memory pressure
- *    and it is struggling to satisfy 0-order allocations
- * 2. Specifying the overall fragmentation level is quite tricky
- *    and without some decent background of what is/has been going
- *    on as far as memory allocations are being concern (both from
- *    user-space and from the kernel) is not really reliable, to say
- *    at least. All in all, what's the acceptable (whatever it means)
- *    level for external fragmentation? Having most of the available
- *    memory within the low-order page blocks should raise an alert,
- *    but that's only in theory. Things get more complicated when taking
- *    into consideration the migration types of available pages.
- *    This might go wrong in so many ways .....
- *    Shall this be continued ?
- */
-static void compaction_start(struct compact_control *compact)
-{
-       struct memory_info *mem_info;
-       int current_status = COMPACT_IDLE;
-       _cleanup_close_ int fd = -1;
-       int n = 1;
-
-       pthread_mutex_lock(&compact->lock);
-
-       if (compact->status & COMPACT_SKIP)
-               current_status |= COMPACT_WITHDRAW;
-
-       pthread_mutex_unlock(&compact->lock);
-
-       if (current_status & COMPACT_WITHDRAW)
-               return;
-
-       mem_info = compact->mem_info;
-
-
-       fd = open(PROC_COMPACT_ENTRY,  O_WRONLY);
-       if (fd < 0) {
-               if (errno == EACCES || errno == EFAULT || errno == ENOENT)
-                       current_status |= COMPACT_WITHDRAW;
-               _E("Compaction: failed to open procfs entry [%d]\n", errno);
-               goto leave;
-       }
-       /*
-        * It doesn't really matter what gets written,
-        * as long as smth gets....
-        */
-       if (write(fd, &n, sizeof(n)) <= 0)
-               current_status |= COMPACT_FAILURE;
-       /*
-        * Reset the external fragmentation warnings.
-        * Locking is not required here as all updates will get suspended
-        * until the compaction status won't indicate all is done here
-        */
-       if (current_status & COMPACT_FAILURE)
-               goto leave;
-
-       for (n = 0; n < mem_info->zone_count; ++n)
-               mem_info->zones[n].frag_warn &= ~ZONE_FRAG_WARN_RAISE;
-leave:
-
-       pthread_mutex_lock(&compact->lock);
-       compact->status |= current_status;
-       pthread_mutex_unlock(&compact->lock);
-}
-
-static void compact_validate_zone(struct zone_info *zone,
-                                 unsigned int frag_level,
-                                 struct memory_info *mem_info)
-{
-       int order, req_order;
-       unsigned int current_frag_map = 0;
-       /*
-        * Skip compaction if the system is below the low watermark.
-        * It's gonna be done either way
-        */
-       if (zone->free_pages < zone->wm_low) {
-               _I("Skipping validation due to falling below the low watermark\n");
-               _I("Zone %s: number of free pages: %lu low watermark: %lu\n",
-                               get_zone_name(zone->id),
-                               zone->free_pages, zone->wm_low);
-               return;
-       }
-
-       for (req_order = 1; req_order <= MAX_PAGE_ORDER; ++req_order) {
-               unsigned long available_pages = 0;
-
-               for (order = req_order; order <= MAX_PAGE_ORDER; ++order)
-                       available_pages += zone->pages_per_order[order] << order;
-
-               if (zone->free_pages > 0 && (1000 - (available_pages * 1000 / zone->free_pages)) >= frag_level)
-                       current_frag_map |= 1 << req_order;
-       }
-
-       if (current_frag_map) {
-
-               if ((!zone->frag_map && current_frag_map) ||
-                   ((zone->frag_map ^ current_frag_map) &&
-                   !((zone->frag_map ^ current_frag_map) & zone->frag_map)))
-
-                       zone->frag_warn |= ZONE_FRAG_WARN_RAISE;
-       }
-
-       zone->frag_map = current_frag_map;
-}
-
-static void compaction_verify_zone(struct compact_control *compact,
-                                  struct zone_info *zone)
-{
-       struct memory_info *mem_info = compact->mem_info;
-
-       /*
-        * Here comes the shady part:
-        * without some decent memory tracing here it is
-        * truly difficult to determine whether the compaction
-        * is required or not.
-        */
-       compact_validate_zone(zone, compact->frag_level, mem_info);
-}
-
-static void compaction_verify(struct compact_control *compact)
-{
-       /* Get the overall idea of current external fragmentation */
-       struct memory_info *mem_info = compact->mem_info;
-       unsigned int compact_targets = 0;
-       int n;
-
-       /*
-        * Verify each zone although the compaction can be
-        * triggered per node (or globally) only.
-        */
-       for (n = 0; n < mem_info->zone_count; ++n) {
-               struct zone_info *zone = &mem_info->zones[n];
-
-               /*
-                * Some devices make a zone but don't allocate any pages for it.
-                * We can ignore these empty zones.
-                */
-               if (zone->managed <= 0)
-                       continue;
-
-               compaction_verify_zone(compact, zone);
-               if (zone->frag_warn & ZONE_FRAG_WARN_RAISE) {
-                       /*
-                        * As the compaction can be triggered either globally
-                        * or on per-node it's enough to have at least one
-                        * zone for which the external fragmentation got
-                        * dangerously high. Still to have a minimum control
-                        * over the whole process - validate all zones.
-                        */
-                       ++compact_targets;
-               }
-       }
-
-       if (compact_targets)
-               compaction_start(compact);
-}
-
-
-#define compact_zoneinfo_set(zone, _off, v) \
-       (*(typeof(v)*)(((char*)(zone)) + _off) = v)
-
-
-static int compact_parse_zone(const char *s, regmatch_t *match,
-                               unsigned int parse_tag, void *data)
-{
-       struct parser_data *parser_data = (struct parser_data *)data;
-       unsigned int zone_id;
-       struct zone_info *zone;
-
-       if (parse_tag != PARSE_TAG_ZONE)
-               return -EINVAL;
-
-       zone_id = get_zone_id(s + match[1].rm_so,
-                                match[1].rm_eo - match[1].rm_so);
-       zone = parser_data->mem_info->zones;
-
-       if (!zone_id)
-               return -EINVAL;
-
-       while (zone->id && zone->id != zone_id)
-               ++zone;
-
-       if (!zone->id) {
-               ++parser_data->mem_info->zone_count;
-               zone->id = zone_id;
-       }
-
-       parser_data->zone = zone;
-       return 0;
-}
-
-static int compact_parse_zoneinfo(const char *s, regmatch_t *match,
-                                 unsigned int parse_tag,
-                                 void *data)
-{
-       struct parser_data *parser_data = (struct parser_data *)data;
-       char *e;
-       unsigned long v;
-
-       v = strtoul(s + match[1].rm_so, &e, 0);
-       if (!(s != e))
-               return -EINVAL;
-
-       switch (parse_tag) {
-       case PARSE_TAG_WM_MIN:
-               compact_zoneinfo_set(parser_data->zone,
-                               offsetof(struct zone_info, wm_min), v);
-               break;
-       case PARSE_TAG_WM_LOW:
-               compact_zoneinfo_set(parser_data->zone,
-                               offsetof(struct zone_info, wm_low), v);
-
-               break;
-       case PARSE_TAG_WM_HIGH:
-               compact_zoneinfo_set(parser_data->zone,
-                               offsetof(struct zone_info, wm_high), v);
-               break;
-       case PARSE_TAG_MANAGED:
-               compact_zoneinfo_set(parser_data->zone,
-                               offsetof(struct zone_info, managed), v);
-               break;
-       }
-       return 0;
-}
-
-static int compact_parse_pages(const char *s, regmatch_t *match,
-                               unsigned int parse_tag, void *data)
-{
-       struct parser_data *parser_data = (struct parser_data *)data;
-       char *e;
-       unsigned long v, page_count = 0;
-       int order;
-
-       if (parse_tag != PARSE_TAG_PAGE_COUNT)
-               return -EINVAL;
-
-       for (order = 0; order < MAX_PAGE_ORDER; ++order) {
-
-               v = strtoul(s, &e, 0);
-               if (!(s != e))
-                       return -EINVAL;
-               parser_data->zone->pages_per_order[order] = v;
-               page_count += v << order;
-               s = e;
-       }
-
-       if (parser_data->zone->free_pages != page_count) {
-               /*
-                * The drop of number of available pages is being handled
-                * on a per-order basis, thought this might be a good point
-                * to validate the zone's watermarks
-                */
-               parser_data->zone->free_pages = page_count;
-       }
-       return 0;
-}
-
-static int compact_get_buddyinfo(struct compact_control *compact)
-{
-       const struct parse_arg args[] = {
-               PARSE_TAG("zone[[:blank:]]+(Normal|DMA|DMA32|HighMem)",
-                       compact_parse_zone, ZONE),
-               PARSE_TAG("([[:blank:]]+([0-9]+))+",
-                       compact_parse_pages, PAGE_COUNT),
-               PARSE_TAG_EMPTY(),
-       };
-
-       struct parser_data parser_data = {
-               .mem_info = compact->mem_info,
-               .zone = &compact->mem_info->zones[0],
-       };
-
-       return proc_parse_buddyinfo(args, &parser_data);
-}
-
-static int compact_get_zoneinfo(struct compact_control *compact)
-{
-       const struct parse_arg args[] = {
-               PARSE_TAG("zone[[:blank:]]+(Normal|DMA|DMA32|HighMem)",
-                         compact_parse_zone, ZONE),
-               PARSE_TAG("min[[:blank:]]+([0-9]+)\n",
-                         compact_parse_zoneinfo, WM_MIN),
-               PARSE_TAG("low[[:blank:]]+([0-9]+)\n",
-                         compact_parse_zoneinfo, WM_LOW),
-               PARSE_TAG("high[[:blank:]]+([0-9]+)\n",
-                         compact_parse_zoneinfo, WM_HIGH),
-               PARSE_TAG("managed[[:blank:]]+([0-9]+)\n",
-                         compact_parse_zoneinfo, MANAGED),
-               PARSE_TAG_EMPTY(),
-       };
-
-       struct parser_data parser_data = {
-               .mem_info = compact->mem_info,
-               .zone = &compact->mem_info->zones[0],
-       };
-       return proc_parse_zoneinfo(args, &parser_data);
-}
-
-static void compact_track_frag_level(struct compact_control *compact)
-{
-       int woken = 1;
-
-       do {
-               /* Eliminate updates on spurious wake-ups */
-               if (woken) {
-                       compact_get_buddyinfo(compact);
-                       compaction_verify(compact);
-               }
-
-               pthread_mutex_lock(&compact_data.notify_lock);
-               pthread_cond_wait(&compact_data.notify,
-                               &compact_data.notify_lock);
-               pthread_mutex_unlock(&compact_data.notify_lock);
-
-               pthread_mutex_lock(&compact->lock);
-               woken = compact->status & COMPACT_NOTIFIED ? 1 : 0;
-               compact->status &= ~COMPACT_NOTIFIED;
-               pthread_mutex_unlock(&compact->lock);
-
-       } while (!(compact->status & COMPACT_SKIP));
-
-}
-
-static int compact_mem_state_changed(void *data)
-{
-       struct compact_control *compact;
-       struct memory_info *mem_info;
-       int result = RESOURCED_ERROR_NONE;
-
-       pthread_mutex_lock(&compact_data.drained_lock);
-       compact = compact_data.compact;
-       mem_info = compact ? compact->mem_info : NULL;
-       if (mem_info) {
-               int new_state = *((int *)data);
-
-               if (new_state < MEM_LEVEL_HIGH || new_state >= MEM_LEVEL_MAX) {
-                       result = RESOURCED_ERROR_FAIL;
-                       goto leave;
-               }
-
-               pthread_mutex_lock(&compact_data.compact->lock);
-               if (!(compact->status & COMPACT_SKIP)) {
-                       compact->status |= COMPACT_NOTIFIED;
-                       pthread_cond_signal(&compact_data.notify);
-               }
-               pthread_mutex_unlock(&compact_data.compact->lock);
-       }
-leave:
-       pthread_mutex_unlock(&compact_data.drained_lock);
-       return result;
-}
-
-static void compact_cleanup(struct compact_control *compact)
-{
-       struct memory_info *mem_info = compact->mem_info;
-
-       if (!(compact->status & COMPACT_SKIP))
-               _E("Invalid compact thread state [%d]\n", compact->status);
-
-       unregister_notifier(RESOURCED_NOTIFIER_MEM_LEVEL_CHANGED,
-                               compact_mem_state_changed);
-
-       (void) pthread_mutex_destroy(&compact->lock);
-
-       free(mem_info);
-       free(compact);
-}
-
-static void *compact_tracer(void *arg)
-{
-       struct compact_data *cdata = (struct compact_data *)arg;
-       struct compact_control *compact = cdata->compact;
-
-       if (compact_get_zoneinfo(compact) == RESOURCED_ERROR_NONE)
-               compact_track_frag_level(compact);
-
-       /* Dropped - so clean-up */
-       pthread_mutex_lock(&compact->lock);
-       compact->status |= COMPACT_WITHDRAW;
-       pthread_mutex_unlock(&compact->lock);
-
-       pthread_mutex_lock(&cdata->drained_lock);
-       compact_cleanup(compact);
-       cdata->compact = NULL;
-       pthread_mutex_unlock(&cdata->drained_lock);
-
-       pthread_cond_signal(&cdata->drained);
-
-       pthread_exit(NULL);
-}
-
-static int compact_parse_config_file(struct compact_control *compact)
-{
-       struct compact_conf *compact_conf = get_compact_conf();
-       if (!compact_conf) {
-               _E("Compact configuration should not be NULL");
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       if (!compact_conf->enable) {
-               (void) pthread_mutex_lock(&compact->lock);
-               compact->status |= COMPACT_SKIP;
-               (void) pthread_mutex_unlock(&compact->lock);
-
-               goto free_compact_conf;
-       }
-
-       if (compact_conf->frag_level > 0)
-               compact->frag_level = compact_conf->frag_level;
-
-       _I("[COMPACTION] compact status: %d", compact->status);
-       _I("[COMPACTION] compact frag_level: %d", compact->frag_level);
-
-free_compact_conf:
-       free_compact_conf();
-
-       return RESOURCED_ERROR_NONE;
-}
-
-static int compact_init(void *data)
-{
-       struct memory_info      *mem_info;
-       struct compact_control  *compact;
-       int result = RESOURCED_ERROR_OUT_OF_MEMORY;
-
-       _I("[COMPACTION] compact init");
-
-       pthread_mutex_lock(&compact_data.drained_lock);
-       if (compact_data.compact) {
-               _E("[COMPACTION] Unbalanced calls to compact module load/unload\n");
-               result = RESOURCED_ERROR_NONE;
-               goto leave;
-       }
-
-       compact = calloc(1, sizeof(*compact));
-       if (!compact)
-               goto leave;
-
-       mem_info = calloc(1, sizeof(*mem_info));
-       if (!mem_info)
-               goto cleanup;
-
-       compact->mem_info = mem_info;
-       compact->frag_level  = COMPACT_DEF_FRAG_LEVEL;
-
-       result = pthread_mutex_init(&compact->lock, NULL);
-       if (result) {
-               _E("[COMPACTION] Failed to init compact lock: %m");
-               goto cleanup_all;
-       }
-
-       /* Load configuration */
-       compact_parse_config_file(compact);
-
-       if (compact->status & COMPACT_SKIP) {
-               _I("[COMPACTION] Compaction module disabled.");
-               result = RESOURCED_ERROR_FAIL;
-               goto cleanup_all;
-       }
-
-       compact_data.compact = compact;
-
-       result = pthread_create(&compact->compact_thread, NULL,
-                       compact_tracer, (void*)&compact_data);
-       if (result) {
-               compact_data.compact = NULL;
-               goto cleanup_all;
-       }
-
-       pthread_detach(compact->compact_thread);
-       pthread_mutex_unlock(&compact_data.drained_lock);
-
-       register_notifier(RESOURCED_NOTIFIER_MEM_LEVEL_CHANGED,
-                                compact_mem_state_changed);
-       return RESOURCED_ERROR_NONE;
-
-cleanup_all:
-       free(mem_info);
-cleanup:
-       free(compact);
-leave:
-       pthread_mutex_unlock(&compact_data.drained_lock);
-       return result;
-}
-
-static int compact_exit(void *data)
-{
-       struct compact_control *compact;
-
-       pthread_mutex_lock(&compact_data.drained_lock);
-       compact = compact_data.compact;
-       compact_data.compact = NULL;
-
-       if (!compact)
-               goto leave;
-
-       pthread_mutex_lock(&compact->lock);
-       compact->status |= COMPACT_CANCEL;
-       pthread_mutex_unlock(&compact->lock);
-
-       pthread_cond_signal(&compact_data.notify);
-       pthread_cond_wait(&compact_data.drained, &compact_data.drained_lock);
-leave:
-       pthread_mutex_unlock(&compact_data.drained_lock);
-       return 0;
-}
-
-static int compact_runtime_support(void *data)
-{
-       _cleanup_close_ int fd = -1;
-
-       fd = open(PROC_COMPACT_ENTRY, O_WRONLY);
-       if (fd < 0) {
-               _E("Unable to open compaction procfs entry\n");
-               return RESOURCED_ERROR_NO_DATA;
-       }
-       return RESOURCED_ERROR_NONE;
-}
-
-static struct module_ops compact_module_ops = {
-       .priority               = MODULE_PRIORITY_LATE,
-       .name                   = "compact",
-       .init                   = compact_init,
-       .exit                   = compact_exit,
-       .check_runtime_support  = compact_runtime_support,
-};
-
-MODULE_REGISTER(&compact_module_ops)
-
diff --git a/src/resource-optimizer/memory/dedup.c b/src/resource-optimizer/memory/dedup.c
new file mode 100644 (file)
index 0000000..fba82c5
--- /dev/null
@@ -0,0 +1,601 @@
+/*
+ * resourced
+ *
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+/*
+ * @file dedup.c
+ * @desc dedup process
+ */
+#include <trace.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/vfs.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <pthread.h>
+#include <sys/sysinfo.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <memory-cgroup.h>
+#include <linux/loop.h>
+#include <fcntl.h>
+#include <string.h>
+#include <time.h>
+
+#include "macro.h"
+#include "util.h"
+#include "module.h"
+#include "module-data.h"
+#include "dedup-common.h"
+#include "config-parser.h"
+#include "lowmem-handler.h"
+#include "notifier.h"
+#include "const.h"
+#include "file-helper.h"
+
+#define DEDUP_PRIORITY              20
+#define DEDUP_ON_BOOT_TIME          60
+#define DEDUP_FULL_SCAN_INTERVAL    60
+#define DEDUP_INIT_SCAN_INTERVAL    300
+#define DEDUP_STAT_INTERVAL         60
+
+enum dedup_thread_op {
+       DEDUP_OP_ACTIVATE,
+       DEDUP_OP_SCANONCE,
+       DEDUP_OP_STAT,
+       DEDUP_OP_DEACTIVATE,
+       DEDUP_OP_MAX,
+};
+
+struct dedup_thread_bundle {
+       enum dedup_thread_op op;
+       enum ksm_scan_mode mode;
+};
+
+static struct module_ops dedup_module_ops;
+
+//static enum dedup_state dedup_state; /* see src/common/dedup-common.h */
+static bool dedup_activated = false;
+
+static bool dedup_enable = false;
+static bool dedup_at_boot_enable = false;
+static enum dedup_mode dedup_mode = DEDUP_MODE_PERIODIC;
+static bool dedup_on_lowmem = false;
+
+static int dedup_at_boot_delay_sec = 60;
+static int dedup_full_scan_interval_sec = 600;
+static int dedup_stat_interval_sec = 60;
+static int dedup_partial_scan_interval_sec = 10;
+
+static GSource *dedup_activating_timer = NULL;
+static GSource *dedup_scanning_timer = NULL;
+static GSource *dedup_stat_timer = NULL;
+
+static int dedup_do_scan(enum ksm_scan_mode);
+static int dedup_do_stat(void);
+
+/* dedup module parameters */
+enum dedup_param {
+       DEDUP_PARAM_ENABLE = 0,
+       DEDUP_PARAM_AT_BOOT,
+       DEDUP_PARAM_AT_BOOT_DELAY,
+       DEDUP_PARAM_ON_LOWMEM,
+       DEDUP_PARAM_STAT_INTERVAL,
+       DEDUP_PARAM_FULL_SCAN_INTERVAL,
+       DEDUP_PARAM_PARTIAL_SCAN_INTERVAL,
+       DEDUP_PARAM_MAX,
+};
+
+/* ksm param types & value ranges & pathes */
+enum ksm_param {
+       KSM_PARAM_PAGES_TO_SCAN = 0,
+       KSM_PARAM_SLEEP_MSECS,
+       KSM_PARAM_FULL_SCAN_INTERVAL_MSECS,
+       KSM_PARAM_SCAN_BOOST,
+       KSM_PARAM_MAX,
+};
+
+static int ksm_param_ranges[KSM_PARAM_MAX][2] = {
+       {0, 10000},   /* KSM_PARAM_PAGES_TO_SCAN */
+       {0, 1000},    /* KSM_PARAM_SLEEP_MSECS */
+       {0, INT_MAX}, /* KSM_PARAM_FULL_SCAN_INTERVAL_MSECS */
+       {100, 10000}, /* KSM_PARAM_SCAN_BOOST */
+};
+static unsigned int ksm_params[KSM_PARAM_MAX];
+static const char *ksm_param_path[KSM_PARAM_MAX] = {
+       "/sys/kernel/mm/ksm/pages_to_scan",
+       "/sys/kernel/mm/ksm/sleep_millisecs",
+       "/sys/kernel/mm/ksm/full_scan_interval",
+       "/sys/kernel/mm/ksm/scan_boost",
+};
+
+/* ksm statistics */
+#define KSM_STAT_WINDOW_MAX 10
+static int ksm_stat_window;
+static unsigned int ksm_stats[KSM_STAT_MAX][KSM_STAT_WINDOW_MAX];
+static const char *ksm_stat_path[2] = {
+       "/sys/kernel/mm/ksm/pages_sharing",
+       "/sys/kernel/mm/ksm/pages_shared",
+};
+
+enum ksm_sysfs_state_val {
+       DEDUP_SYSFS_STOP  = 0,
+       DEDUP_SYSFS_RUN = 1,
+       DEDUP_SYSFS_ONE_SHOT = 8,
+};
+
+static inline int dedup_set_ksm_state(enum dedup_state state)
+{
+       int val;
+
+       if (state == DEDUP_ON)
+               val = DEDUP_SYSFS_RUN;
+       else if (state == DEDUP_ONE_SHOT)
+               val = DEDUP_SYSFS_ONE_SHOT;
+       else
+               val = DEDUP_SYSFS_STOP;
+       /* write value to /sys/kernel/mm/ksm/run */
+       return fwrite_int(DEDUP_SYSFS_KSM_RUN, val);
+}
+
+static inline int dedup_set_ksm_param(int param_num, unsigned int value)
+{
+       return fwrite_uint(ksm_param_path[param_num], value);
+}
+
+static void dedup_set_ksm_params(void)
+{
+       int i;
+       for (i = KSM_PARAM_PAGES_TO_SCAN; i < KSM_PARAM_MAX; i++)
+               dedup_set_ksm_param(i, ksm_params[i]);
+}
+
+static int dedup_check_and_scanning_once(enum ksm_scan_mode mode)
+{
+       int val;
+       fread_int(DEDUP_SYSFS_KSM_ONESHOT, &val);
+       if (val == KSM_SCAN_NONE)
+               return fwrite_int(DEDUP_SYSFS_KSM_ONESHOT, mode);
+       return 0;
+}
+
+static int dedup_scanning_once(enum ksm_scan_mode mode)
+{
+       int ret;
+       _D("[DEDUP] Invoke scanning once to KSM (mode: %d)", mode);
+       ret = dedup_check_and_scanning_once(mode);
+
+       return ret;
+}
+
+unsigned int dedup_get_ksm_stat(enum ksm_stat stat_type)
+{
+       int last;
+       if (stat_type < KSM_STAT_PAGES_SHARING || stat_type >= KSM_STAT_MAX)
+               return 0;
+       last = (ksm_stat_window == 0) ? KSM_STAT_WINDOW_MAX - 1 : ksm_stat_window - 1;
+       return ksm_stats[stat_type][last];
+}
+
+static int dedup_record_stat(void)
+{
+       int val, ret;
+
+       ret = fread_int(ksm_stat_path[KSM_STAT_PAGES_SHARING], &val);
+       if (!ret)
+               ksm_stats[KSM_STAT_PAGES_SHARING][ksm_stat_window] = val;
+       ret = fread_int(ksm_stat_path[KSM_STAT_PAGES_SHARED], &val);
+       if (!ret)
+               ksm_stats[KSM_STAT_PAGES_SHARED][ksm_stat_window] = val;
+
+       _I("read ksm stat: pages_sharing: %d pages_shared: %d",
+               ksm_stats[KSM_STAT_PAGES_SHARING][ksm_stat_window],
+               ksm_stats[KSM_STAT_PAGES_SHARED][ksm_stat_window]);
+       ksm_stat_window = (ksm_stat_window + 1) % KSM_STAT_WINDOW_MAX;
+       return RESOURCED_ERROR_NONE;
+}
+
+static gboolean dedup_scanning_timer_cb(gpointer data)
+{
+       dedup_scanning_timer = NULL;
+       if (dedup_get_state() == DEDUP_ONE_SHOT)
+               dedup_do_scan(KSM_SCAN_FULL);
+       return false;
+}
+
+static gboolean dedup_stat_timer_cb(gpointer data)
+{
+       dedup_stat_timer = NULL;
+       dedup_do_stat();
+       return false;
+}
+
+static void dedup_reset_scanning_timer(void)
+{
+       _D("reset scan-timer %d seconds", dedup_full_scan_interval_sec);
+       dedup_scanning_timer =
+               g_timeout_source_new_seconds(dedup_full_scan_interval_sec);
+       g_source_set_callback(dedup_scanning_timer,
+                       dedup_scanning_timer_cb, NULL, NULL);
+       g_source_attach(dedup_scanning_timer, NULL);
+}
+
+static void dedup_reset_stat_timer(void)
+{
+       _D("reset stat-timer %d seconds", dedup_stat_interval_sec);
+       dedup_stat_timer =
+               g_timeout_source_new_seconds(dedup_stat_interval_sec);
+       g_source_set_callback(dedup_stat_timer,
+                       dedup_stat_timer_cb, NULL, NULL);
+       g_source_attach(dedup_stat_timer, NULL);
+}
+
+static void dedup_deactivate_in_module(void)
+{
+       if (dedup_activating_timer) {
+               g_source_destroy(dedup_activating_timer);
+               dedup_activating_timer = NULL;
+       }
+
+       if (dedup_scanning_timer) {
+               g_source_destroy(dedup_scanning_timer);
+               dedup_scanning_timer = NULL;
+       }
+
+       if (dedup_stat_timer) {
+               g_source_destroy(dedup_stat_timer);
+               dedup_stat_timer = NULL;
+       }
+
+       _D("stop KSM thread");
+
+       dedup_set_ksm_state(DEDUP_OFF);
+}
+
+static enum dedup_state parse_dedup_state(enum dedup_mode mode)
+{
+       if (mode == DEDUP_MODE_PERIODIC)
+               return DEDUP_ON;
+       else if (mode == DEDUP_MODE_ONESHOT)
+               return DEDUP_ONE_SHOT;
+       else
+               return DEDUP_OFF;
+}
+
+static void dedup_activate_in_module(void)
+{
+       enum dedup_state state;
+
+       if (dedup_get_state() == DEDUP_ON
+                       || dedup_get_state() == DEDUP_ONE_SHOT)
+               return;
+
+       if (dedup_activated)
+               return;
+
+       /* make ksm activate */
+       state = parse_dedup_state(dedup_mode);
+       dedup_set_state(state);
+       dedup_set_ksm_params();
+       dedup_set_ksm_state(state);
+       _I("kernel deduplication thread is enabled");
+
+       if (dedup_activating_timer) {
+               g_source_destroy(dedup_activating_timer);
+               dedup_activating_timer = NULL;
+       }
+
+       if (!dedup_on_lowmem) {
+               dedup_scanning_timer = g_timeout_source_new_seconds(dedup_full_scan_interval_sec);
+               g_source_set_callback(dedup_scanning_timer, dedup_scanning_timer_cb, NULL, NULL);
+               g_source_attach(dedup_scanning_timer, NULL);
+       }
+
+       dedup_stat_timer = g_timeout_source_new_seconds(dedup_stat_interval_sec);
+       g_source_set_callback(dedup_stat_timer, dedup_stat_timer_cb, NULL, NULL);
+       g_source_attach(dedup_stat_timer, NULL);
+
+       dedup_activated = true;
+}
+
+#define DEDUP_ACT_MSTOS  1000
+#define DEDUP_ACT_NSTOMS 1000000
+
+static bool dedup_check_scan_interval
+(struct timespec *now, struct timespec *old, unsigned long interval_ms)
+{
+       unsigned long diff_ms;
+       diff_ms = (now->tv_sec - old->tv_sec) * DEDUP_ACT_MSTOS;
+       diff_ms += (now->tv_nsec - old->tv_nsec) / DEDUP_ACT_NSTOMS;
+       return (diff_ms >= (interval_ms * DEDUP_ACT_MSTOS));
+}
+
+/* used in dedup_do_scan */
+static struct timespec now, partial_begin, full_begin;
+static int nr_dedup;
+
+static int dedup_do_scan(enum ksm_scan_mode scan_mode)
+{
+       enum ksm_scan_mode mode = KSM_SCAN_NONE;
+
+       clock_gettime(CLOCK_MONOTONIC, &now);
+       if (scan_mode == KSM_SCAN_FULL) {
+               /* if full scan is requested frequently, it can be
+                * substituted by partial scan
+                */
+               if (dedup_check_scan_interval(&now, &full_begin,
+                               dedup_full_scan_interval_sec))
+                       mode = KSM_SCAN_FULL;
+               else if (dedup_on_lowmem &&
+                               dedup_check_scan_interval(&now, &partial_begin,
+                               dedup_partial_scan_interval_sec))
+                       mode = KSM_SCAN_PARTIAL;
+       } else if (scan_mode == KSM_SCAN_PARTIAL) {
+               if (dedup_check_scan_interval(&now, &partial_begin,
+                               dedup_partial_scan_interval_sec))
+                       mode = KSM_SCAN_PARTIAL;
+       }
+
+       if (mode != KSM_SCAN_NONE) {
+               _I("[DEDUP] dedup: %d-th %s deduplication triggering", nr_dedup++,
+                               (mode == KSM_SCAN_FULL ? "FULL" : "PARTIAL"));
+               if (!dedup_on_lowmem) {
+                       dedup_scanning_once(KSM_SCAN_FULL);
+                       dedup_reset_scanning_timer();
+               } else
+                       dedup_scanning_once(mode);
+
+               if (mode == KSM_SCAN_FULL)
+                       full_begin = now;
+               else
+                       partial_begin = now;
+       }
+
+       return RESOURCED_ERROR_NONE;
+}
+
+static int dedup_do_stat(void)
+{
+       dedup_record_stat();
+       dedup_reset_stat_timer();
+       return RESOURCED_ERROR_NONE;
+}
+
+static int dedup_start_handler(void *data)
+{
+       if (!data)
+               return RESOURCED_ERROR_NO_DATA;
+
+       dedup_activate_in_module();
+
+       return RESOURCED_ERROR_NONE;
+}
+
+static int dedup_scan_handler(void *data)
+{
+       int *scan_mode;
+
+       if (dedup_get_state() != DEDUP_ONE_SHOT)
+               return 0;
+
+       if (dedup_scanning_timer) {
+               g_source_destroy(dedup_scanning_timer);
+               dedup_scanning_timer = NULL;
+       }
+
+       scan_mode = data;
+       return dedup_do_scan(*scan_mode);
+}
+
+static int dedup_stop_handler(void *data)
+{
+       if (!data)
+               return RESOURCED_ERROR_NO_DATA;
+
+       dedup_deactivate_in_module();
+
+       return RESOURCED_ERROR_NONE;
+}
+
+static gboolean dedup_activate_timer_cb(gpointer data)
+{
+       dedup_activating_timer = NULL;
+       _D("[DEDUP] dedup activating callback called");
+       dedup_activate_in_module();
+       return false;
+}
+
+static int dedup_booting_done(void *data)
+{
+       if (dedup_activated)
+               return RESOURCED_ERROR_NONE;
+
+       if (dedup_at_boot_enable) {
+               /* if dedup_at_boot_enable is disabled,
+                * other daemon should activate dedup */
+               _D("[DEDUP] dedup booting done is called");
+               if (dedup_at_boot_delay_sec > 0)
+                       dedup_activating_timer =
+                               g_timeout_source_new_seconds(dedup_at_boot_delay_sec);
+               else
+                       dedup_activating_timer =
+                               g_timeout_source_new_seconds(DEDUP_ON_BOOT_TIME);
+               g_source_set_callback(dedup_activating_timer,
+                       dedup_activate_timer_cb, NULL, NULL);
+               g_source_attach(dedup_activating_timer, NULL);
+       }
+
+       return RESOURCED_ERROR_NONE;
+}
+
+static int dedup_parse_config_file(void)
+{
+       int arg_ksm_pages_to_scan = 100;
+       int arg_ksm_sleep_ms = 20;      // 20 msecs
+       int arg_ksm_full_scan_interval_ms = 60000;      // 60 seconds
+       int arg_ksm_scan_boost = 1000;
+
+       struct dedup_conf *dedup_conf = get_dedup_conf();
+       if (!dedup_conf) {
+               _E("Dedup configuration should not be NULL");
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       dedup_enable = dedup_conf->enable;
+       if (!dedup_enable)
+               goto free_dedup_conf;
+
+       if (!strncmp(dedup_conf->ksm.mode, "oneshot", 8))
+               dedup_mode = DEDUP_MODE_ONESHOT;
+       else if(!strncmp(dedup_conf->ksm.mode, "periodic", 9))
+               dedup_mode = DEDUP_MODE_PERIODIC;
+       else {
+               dedup_enable =  false;
+               goto free_dedup_conf;
+       }
+
+       dedup_at_boot_enable = dedup_conf->boot_dedup_enable;
+       dedup_on_lowmem = dedup_conf->scan_on_lowmem;
+
+       if (dedup_conf->ksm.pages > ksm_param_ranges[KSM_PARAM_PAGES_TO_SCAN][0] &&
+               dedup_conf->ksm.pages <= ksm_param_ranges[KSM_PARAM_PAGES_TO_SCAN][1])
+               ksm_params[KSM_PARAM_PAGES_TO_SCAN] = dedup_conf->ksm.pages;
+       else
+               ksm_params[KSM_PARAM_PAGES_TO_SCAN] = arg_ksm_pages_to_scan;
+
+       if (dedup_conf->ksm.boost_pages > ksm_param_ranges[KSM_PARAM_SCAN_BOOST][0] &&
+           dedup_conf->ksm.boost_pages <= ksm_param_ranges[KSM_PARAM_SCAN_BOOST][1])
+               ksm_params[KSM_PARAM_SCAN_BOOST] = dedup_conf->ksm.boost_pages;
+       else
+               ksm_params[KSM_PARAM_SCAN_BOOST] = arg_ksm_scan_boost;
+
+       ksm_params[KSM_PARAM_SLEEP_MSECS] = arg_ksm_sleep_ms;
+       ksm_params[KSM_PARAM_FULL_SCAN_INTERVAL_MSECS] = arg_ksm_full_scan_interval_ms;
+
+       _I("[DEDUP] deduplication mode: %s", dedup_mode == DEDUP_MODE_PERIODIC ?
+                       "kernel-managed" : "resourced-triggered");
+       _I("[DEDUP] deduplication on boot: %s", dedup_at_boot_enable ? "true" : "false");
+       _I("[DEDUP] scanning is invoked by %s", dedup_on_lowmem ?
+                       "LOWMEM event" : "periodic timer");
+       _I("[DEDUP] full scan interval: %d sec", dedup_full_scan_interval_sec);
+       _I("[DEDUP] stat monitoring interval: %d sec", dedup_stat_interval_sec);
+
+       _I("[DEDUP] ksm pages to scan: %d", ksm_params[KSM_PARAM_PAGES_TO_SCAN]);
+       _I("[DEDUP] ksm sleep time: %d ms", ksm_params[KSM_PARAM_SLEEP_MSECS]);
+       _I("[DEDUP] ksm full scan interval: %d ms", ksm_params[KSM_PARAM_FULL_SCAN_INTERVAL_MSECS]);
+       _I("[DEDUP] ksm scan boost: %d", ksm_params[KSM_PARAM_SCAN_BOOST]);
+
+free_dedup_conf:
+       free_dedup_conf();
+
+       return RESOURCED_ERROR_NONE;
+}
+
+static inline void init_dedup_stat(void)
+{
+       int i, j;
+       for (i = KSM_STAT_PAGES_SHARING; i < KSM_STAT_MAX; i++)
+               for (j = 0; j < KSM_STAT_WINDOW_MAX; j++)
+                       ksm_stats[i][j] = 0;
+       ksm_stat_window = 0;
+}
+
+static int dedup_init(void)
+{
+       int ret;
+
+       init_dedup_stat();
+       ret = dedup_parse_config_file();
+       if (ret < 0)
+               return ret;
+
+       if (!dedup_enable)
+               return -ENODEV;
+
+       /* initialize time variables */
+       if (!clock_gettime(CLOCK_MONOTONIC, &now)) {
+               partial_begin = now;
+               full_begin = now;
+       } else {
+               _I("Time initialization failed");
+               memset(&partial_begin, 0, sizeof(struct timespec));
+               memset(&full_begin, 0, sizeof(struct timespec));
+       }
+
+       return ret;
+}
+
+static int resourced_dedup_check_runtime_support(void *data)
+{
+       /*
+        * Check whether CONFIG_LKSM is enabled in kernel.
+        */
+       if (access("/sys/kernel/mm/ksm/run", R_OK) != 0) {
+               _I("the kernel doesn't support KSM, please check kernel configuration");
+               return -ENOENT;
+       }
+       if (access("/sys/kernel/mm/ksm/one_shot_scanning", R_OK) != 0) {
+               _I("the kernel support KSM but not LKSM, please check kernel configuration");
+               return -ENOENT;
+       }
+
+       return 0;
+}
+
+static int resourced_dedup_init(void *data)
+{
+       int ret;
+
+       dedup_set_state(DEDUP_OFF);
+
+       ret = dedup_init();
+       if (ret != RESOURCED_ERROR_NONE)
+               return ret;
+       _I("resourced dedup module is initialized");
+       register_notifier(RESOURCED_NOTIFIER_DEDUP_START, dedup_start_handler);
+       register_notifier(RESOURCED_NOTIFIER_DEDUP_SCAN, dedup_scan_handler);
+       register_notifier(RESOURCED_NOTIFIER_DEDUP_STOP, dedup_stop_handler);
+       register_notifier(RESOURCED_NOTIFIER_BOOTING_DONE, dedup_booting_done);
+
+       return ret;
+}
+
+static int resourced_dedup_finalize(void *data)
+{
+       unregister_notifier(RESOURCED_NOTIFIER_DEDUP_START, dedup_start_handler);
+       unregister_notifier(RESOURCED_NOTIFIER_DEDUP_SCAN, dedup_scan_handler);
+       unregister_notifier(RESOURCED_NOTIFIER_DEDUP_STOP, dedup_stop_handler);
+       unregister_notifier(RESOURCED_NOTIFIER_BOOTING_DONE, dedup_booting_done);
+
+       dedup_deactivate_in_module();
+
+       _I("dedup module will be finalized");
+
+       return RESOURCED_ERROR_NONE;
+}
+
+static struct module_ops dedup_module_ops = {
+       .priority = MODULE_PRIORITY_NORMAL,
+       .name = "dedup",
+       .init = resourced_dedup_init,
+       .exit = resourced_dedup_finalize,
+       .check_runtime_support = resourced_dedup_check_runtime_support,
+};
+
+MODULE_REGISTER(&dedup_module_ops)
diff --git a/src/resource-optimizer/memory/dedup/dedup.c b/src/resource-optimizer/memory/dedup/dedup.c
deleted file mode 100644 (file)
index fba82c5..0000000
+++ /dev/null
@@ -1,601 +0,0 @@
-/*
- * resourced
- *
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
-*/
-
-/*
- * @file dedup.c
- * @desc dedup process
- */
-#include <trace.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/vfs.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <pthread.h>
-#include <sys/sysinfo.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <memory-cgroup.h>
-#include <linux/loop.h>
-#include <fcntl.h>
-#include <string.h>
-#include <time.h>
-
-#include "macro.h"
-#include "util.h"
-#include "module.h"
-#include "module-data.h"
-#include "dedup-common.h"
-#include "config-parser.h"
-#include "lowmem-handler.h"
-#include "notifier.h"
-#include "const.h"
-#include "file-helper.h"
-
-#define DEDUP_PRIORITY              20
-#define DEDUP_ON_BOOT_TIME          60
-#define DEDUP_FULL_SCAN_INTERVAL    60
-#define DEDUP_INIT_SCAN_INTERVAL    300
-#define DEDUP_STAT_INTERVAL         60
-
-enum dedup_thread_op {
-       DEDUP_OP_ACTIVATE,
-       DEDUP_OP_SCANONCE,
-       DEDUP_OP_STAT,
-       DEDUP_OP_DEACTIVATE,
-       DEDUP_OP_MAX,
-};
-
-struct dedup_thread_bundle {
-       enum dedup_thread_op op;
-       enum ksm_scan_mode mode;
-};
-
-static struct module_ops dedup_module_ops;
-
-//static enum dedup_state dedup_state; /* see src/common/dedup-common.h */
-static bool dedup_activated = false;
-
-static bool dedup_enable = false;
-static bool dedup_at_boot_enable = false;
-static enum dedup_mode dedup_mode = DEDUP_MODE_PERIODIC;
-static bool dedup_on_lowmem = false;
-
-static int dedup_at_boot_delay_sec = 60;
-static int dedup_full_scan_interval_sec = 600;
-static int dedup_stat_interval_sec = 60;
-static int dedup_partial_scan_interval_sec = 10;
-
-static GSource *dedup_activating_timer = NULL;
-static GSource *dedup_scanning_timer = NULL;
-static GSource *dedup_stat_timer = NULL;
-
-static int dedup_do_scan(enum ksm_scan_mode);
-static int dedup_do_stat(void);
-
-/* dedup module parameters */
-enum dedup_param {
-       DEDUP_PARAM_ENABLE = 0,
-       DEDUP_PARAM_AT_BOOT,
-       DEDUP_PARAM_AT_BOOT_DELAY,
-       DEDUP_PARAM_ON_LOWMEM,
-       DEDUP_PARAM_STAT_INTERVAL,
-       DEDUP_PARAM_FULL_SCAN_INTERVAL,
-       DEDUP_PARAM_PARTIAL_SCAN_INTERVAL,
-       DEDUP_PARAM_MAX,
-};
-
-/* ksm param types & value ranges & pathes */
-enum ksm_param {
-       KSM_PARAM_PAGES_TO_SCAN = 0,
-       KSM_PARAM_SLEEP_MSECS,
-       KSM_PARAM_FULL_SCAN_INTERVAL_MSECS,
-       KSM_PARAM_SCAN_BOOST,
-       KSM_PARAM_MAX,
-};
-
-static int ksm_param_ranges[KSM_PARAM_MAX][2] = {
-       {0, 10000},   /* KSM_PARAM_PAGES_TO_SCAN */
-       {0, 1000},    /* KSM_PARAM_SLEEP_MSECS */
-       {0, INT_MAX}, /* KSM_PARAM_FULL_SCAN_INTERVAL_MSECS */
-       {100, 10000}, /* KSM_PARAM_SCAN_BOOST */
-};
-static unsigned int ksm_params[KSM_PARAM_MAX];
-static const char *ksm_param_path[KSM_PARAM_MAX] = {
-       "/sys/kernel/mm/ksm/pages_to_scan",
-       "/sys/kernel/mm/ksm/sleep_millisecs",
-       "/sys/kernel/mm/ksm/full_scan_interval",
-       "/sys/kernel/mm/ksm/scan_boost",
-};
-
-/* ksm statistics */
-#define KSM_STAT_WINDOW_MAX 10
-static int ksm_stat_window;
-static unsigned int ksm_stats[KSM_STAT_MAX][KSM_STAT_WINDOW_MAX];
-static const char *ksm_stat_path[2] = {
-       "/sys/kernel/mm/ksm/pages_sharing",
-       "/sys/kernel/mm/ksm/pages_shared",
-};
-
-enum ksm_sysfs_state_val {
-       DEDUP_SYSFS_STOP  = 0,
-       DEDUP_SYSFS_RUN = 1,
-       DEDUP_SYSFS_ONE_SHOT = 8,
-};
-
-static inline int dedup_set_ksm_state(enum dedup_state state)
-{
-       int val;
-
-       if (state == DEDUP_ON)
-               val = DEDUP_SYSFS_RUN;
-       else if (state == DEDUP_ONE_SHOT)
-               val = DEDUP_SYSFS_ONE_SHOT;
-       else
-               val = DEDUP_SYSFS_STOP;
-       /* write value to /sys/kernel/mm/ksm/run */
-       return fwrite_int(DEDUP_SYSFS_KSM_RUN, val);
-}
-
-static inline int dedup_set_ksm_param(int param_num, unsigned int value)
-{
-       return fwrite_uint(ksm_param_path[param_num], value);
-}
-
-static void dedup_set_ksm_params(void)
-{
-       int i;
-       for (i = KSM_PARAM_PAGES_TO_SCAN; i < KSM_PARAM_MAX; i++)
-               dedup_set_ksm_param(i, ksm_params[i]);
-}
-
-static int dedup_check_and_scanning_once(enum ksm_scan_mode mode)
-{
-       int val;
-       fread_int(DEDUP_SYSFS_KSM_ONESHOT, &val);
-       if (val == KSM_SCAN_NONE)
-               return fwrite_int(DEDUP_SYSFS_KSM_ONESHOT, mode);
-       return 0;
-}
-
-static int dedup_scanning_once(enum ksm_scan_mode mode)
-{
-       int ret;
-       _D("[DEDUP] Invoke scanning once to KSM (mode: %d)", mode);
-       ret = dedup_check_and_scanning_once(mode);
-
-       return ret;
-}
-
-unsigned int dedup_get_ksm_stat(enum ksm_stat stat_type)
-{
-       int last;
-       if (stat_type < KSM_STAT_PAGES_SHARING || stat_type >= KSM_STAT_MAX)
-               return 0;
-       last = (ksm_stat_window == 0) ? KSM_STAT_WINDOW_MAX - 1 : ksm_stat_window - 1;
-       return ksm_stats[stat_type][last];
-}
-
-static int dedup_record_stat(void)
-{
-       int val, ret;
-
-       ret = fread_int(ksm_stat_path[KSM_STAT_PAGES_SHARING], &val);
-       if (!ret)
-               ksm_stats[KSM_STAT_PAGES_SHARING][ksm_stat_window] = val;
-       ret = fread_int(ksm_stat_path[KSM_STAT_PAGES_SHARED], &val);
-       if (!ret)
-               ksm_stats[KSM_STAT_PAGES_SHARED][ksm_stat_window] = val;
-
-       _I("read ksm stat: pages_sharing: %d pages_shared: %d",
-               ksm_stats[KSM_STAT_PAGES_SHARING][ksm_stat_window],
-               ksm_stats[KSM_STAT_PAGES_SHARED][ksm_stat_window]);
-       ksm_stat_window = (ksm_stat_window + 1) % KSM_STAT_WINDOW_MAX;
-       return RESOURCED_ERROR_NONE;
-}
-
-static gboolean dedup_scanning_timer_cb(gpointer data)
-{
-       dedup_scanning_timer = NULL;
-       if (dedup_get_state() == DEDUP_ONE_SHOT)
-               dedup_do_scan(KSM_SCAN_FULL);
-       return false;
-}
-
-static gboolean dedup_stat_timer_cb(gpointer data)
-{
-       dedup_stat_timer = NULL;
-       dedup_do_stat();
-       return false;
-}
-
-static void dedup_reset_scanning_timer(void)
-{
-       _D("reset scan-timer %d seconds", dedup_full_scan_interval_sec);
-       dedup_scanning_timer =
-               g_timeout_source_new_seconds(dedup_full_scan_interval_sec);
-       g_source_set_callback(dedup_scanning_timer,
-                       dedup_scanning_timer_cb, NULL, NULL);
-       g_source_attach(dedup_scanning_timer, NULL);
-}
-
-static void dedup_reset_stat_timer(void)
-{
-       _D("reset stat-timer %d seconds", dedup_stat_interval_sec);
-       dedup_stat_timer =
-               g_timeout_source_new_seconds(dedup_stat_interval_sec);
-       g_source_set_callback(dedup_stat_timer,
-                       dedup_stat_timer_cb, NULL, NULL);
-       g_source_attach(dedup_stat_timer, NULL);
-}
-
-static void dedup_deactivate_in_module(void)
-{
-       if (dedup_activating_timer) {
-               g_source_destroy(dedup_activating_timer);
-               dedup_activating_timer = NULL;
-       }
-
-       if (dedup_scanning_timer) {
-               g_source_destroy(dedup_scanning_timer);
-               dedup_scanning_timer = NULL;
-       }
-
-       if (dedup_stat_timer) {
-               g_source_destroy(dedup_stat_timer);
-               dedup_stat_timer = NULL;
-       }
-
-       _D("stop KSM thread");
-
-       dedup_set_ksm_state(DEDUP_OFF);
-}
-
-static enum dedup_state parse_dedup_state(enum dedup_mode mode)
-{
-       if (mode == DEDUP_MODE_PERIODIC)
-               return DEDUP_ON;
-       else if (mode == DEDUP_MODE_ONESHOT)
-               return DEDUP_ONE_SHOT;
-       else
-               return DEDUP_OFF;
-}
-
-static void dedup_activate_in_module(void)
-{
-       enum dedup_state state;
-
-       if (dedup_get_state() == DEDUP_ON
-                       || dedup_get_state() == DEDUP_ONE_SHOT)
-               return;
-
-       if (dedup_activated)
-               return;
-
-       /* make ksm activate */
-       state = parse_dedup_state(dedup_mode);
-       dedup_set_state(state);
-       dedup_set_ksm_params();
-       dedup_set_ksm_state(state);
-       _I("kernel deduplication thread is enabled");
-
-       if (dedup_activating_timer) {
-               g_source_destroy(dedup_activating_timer);
-               dedup_activating_timer = NULL;
-       }
-
-       if (!dedup_on_lowmem) {
-               dedup_scanning_timer = g_timeout_source_new_seconds(dedup_full_scan_interval_sec);
-               g_source_set_callback(dedup_scanning_timer, dedup_scanning_timer_cb, NULL, NULL);
-               g_source_attach(dedup_scanning_timer, NULL);
-       }
-
-       dedup_stat_timer = g_timeout_source_new_seconds(dedup_stat_interval_sec);
-       g_source_set_callback(dedup_stat_timer, dedup_stat_timer_cb, NULL, NULL);
-       g_source_attach(dedup_stat_timer, NULL);
-
-       dedup_activated = true;
-}
-
-#define DEDUP_ACT_MSTOS  1000
-#define DEDUP_ACT_NSTOMS 1000000
-
-static bool dedup_check_scan_interval
-(struct timespec *now, struct timespec *old, unsigned long interval_ms)
-{
-       unsigned long diff_ms;
-       diff_ms = (now->tv_sec - old->tv_sec) * DEDUP_ACT_MSTOS;
-       diff_ms += (now->tv_nsec - old->tv_nsec) / DEDUP_ACT_NSTOMS;
-       return (diff_ms >= (interval_ms * DEDUP_ACT_MSTOS));
-}
-
-/* used in dedup_do_scan */
-static struct timespec now, partial_begin, full_begin;
-static int nr_dedup;
-
-static int dedup_do_scan(enum ksm_scan_mode scan_mode)
-{
-       enum ksm_scan_mode mode = KSM_SCAN_NONE;
-
-       clock_gettime(CLOCK_MONOTONIC, &now);
-       if (scan_mode == KSM_SCAN_FULL) {
-               /* if full scan is requested frequently, it can be
-                * substituted by partial scan
-                */
-               if (dedup_check_scan_interval(&now, &full_begin,
-                               dedup_full_scan_interval_sec))
-                       mode = KSM_SCAN_FULL;
-               else if (dedup_on_lowmem &&
-                               dedup_check_scan_interval(&now, &partial_begin,
-                               dedup_partial_scan_interval_sec))
-                       mode = KSM_SCAN_PARTIAL;
-       } else if (scan_mode == KSM_SCAN_PARTIAL) {
-               if (dedup_check_scan_interval(&now, &partial_begin,
-                               dedup_partial_scan_interval_sec))
-                       mode = KSM_SCAN_PARTIAL;
-       }
-
-       if (mode != KSM_SCAN_NONE) {
-               _I("[DEDUP] dedup: %d-th %s deduplication triggering", nr_dedup++,
-                               (mode == KSM_SCAN_FULL ? "FULL" : "PARTIAL"));
-               if (!dedup_on_lowmem) {
-                       dedup_scanning_once(KSM_SCAN_FULL);
-                       dedup_reset_scanning_timer();
-               } else
-                       dedup_scanning_once(mode);
-
-               if (mode == KSM_SCAN_FULL)
-                       full_begin = now;
-               else
-                       partial_begin = now;
-       }
-
-       return RESOURCED_ERROR_NONE;
-}
-
-static int dedup_do_stat(void)
-{
-       dedup_record_stat();
-       dedup_reset_stat_timer();
-       return RESOURCED_ERROR_NONE;
-}
-
-static int dedup_start_handler(void *data)
-{
-       if (!data)
-               return RESOURCED_ERROR_NO_DATA;
-
-       dedup_activate_in_module();
-
-       return RESOURCED_ERROR_NONE;
-}
-
-static int dedup_scan_handler(void *data)
-{
-       int *scan_mode;
-
-       if (dedup_get_state() != DEDUP_ONE_SHOT)
-               return 0;
-
-       if (dedup_scanning_timer) {
-               g_source_destroy(dedup_scanning_timer);
-               dedup_scanning_timer = NULL;
-       }
-
-       scan_mode = data;
-       return dedup_do_scan(*scan_mode);
-}
-
-static int dedup_stop_handler(void *data)
-{
-       if (!data)
-               return RESOURCED_ERROR_NO_DATA;
-
-       dedup_deactivate_in_module();
-
-       return RESOURCED_ERROR_NONE;
-}
-
-static gboolean dedup_activate_timer_cb(gpointer data)
-{
-       dedup_activating_timer = NULL;
-       _D("[DEDUP] dedup activating callback called");
-       dedup_activate_in_module();
-       return false;
-}
-
-static int dedup_booting_done(void *data)
-{
-       if (dedup_activated)
-               return RESOURCED_ERROR_NONE;
-
-       if (dedup_at_boot_enable) {
-               /* if dedup_at_boot_enable is disabled,
-                * other daemon should activate dedup */
-               _D("[DEDUP] dedup booting done is called");
-               if (dedup_at_boot_delay_sec > 0)
-                       dedup_activating_timer =
-                               g_timeout_source_new_seconds(dedup_at_boot_delay_sec);
-               else
-                       dedup_activating_timer =
-                               g_timeout_source_new_seconds(DEDUP_ON_BOOT_TIME);
-               g_source_set_callback(dedup_activating_timer,
-                       dedup_activate_timer_cb, NULL, NULL);
-               g_source_attach(dedup_activating_timer, NULL);
-       }
-
-       return RESOURCED_ERROR_NONE;
-}
-
-static int dedup_parse_config_file(void)
-{
-       int arg_ksm_pages_to_scan = 100;
-       int arg_ksm_sleep_ms = 20;      // 20 msecs
-       int arg_ksm_full_scan_interval_ms = 60000;      // 60 seconds
-       int arg_ksm_scan_boost = 1000;
-
-       struct dedup_conf *dedup_conf = get_dedup_conf();
-       if (!dedup_conf) {
-               _E("Dedup configuration should not be NULL");
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       dedup_enable = dedup_conf->enable;
-       if (!dedup_enable)
-               goto free_dedup_conf;
-
-       if (!strncmp(dedup_conf->ksm.mode, "oneshot", 8))
-               dedup_mode = DEDUP_MODE_ONESHOT;
-       else if(!strncmp(dedup_conf->ksm.mode, "periodic", 9))
-               dedup_mode = DEDUP_MODE_PERIODIC;
-       else {
-               dedup_enable =  false;
-               goto free_dedup_conf;
-       }
-
-       dedup_at_boot_enable = dedup_conf->boot_dedup_enable;
-       dedup_on_lowmem = dedup_conf->scan_on_lowmem;
-
-       if (dedup_conf->ksm.pages > ksm_param_ranges[KSM_PARAM_PAGES_TO_SCAN][0] &&
-               dedup_conf->ksm.pages <= ksm_param_ranges[KSM_PARAM_PAGES_TO_SCAN][1])
-               ksm_params[KSM_PARAM_PAGES_TO_SCAN] = dedup_conf->ksm.pages;
-       else
-               ksm_params[KSM_PARAM_PAGES_TO_SCAN] = arg_ksm_pages_to_scan;
-
-       if (dedup_conf->ksm.boost_pages > ksm_param_ranges[KSM_PARAM_SCAN_BOOST][0] &&
-           dedup_conf->ksm.boost_pages <= ksm_param_ranges[KSM_PARAM_SCAN_BOOST][1])
-               ksm_params[KSM_PARAM_SCAN_BOOST] = dedup_conf->ksm.boost_pages;
-       else
-               ksm_params[KSM_PARAM_SCAN_BOOST] = arg_ksm_scan_boost;
-
-       ksm_params[KSM_PARAM_SLEEP_MSECS] = arg_ksm_sleep_ms;
-       ksm_params[KSM_PARAM_FULL_SCAN_INTERVAL_MSECS] = arg_ksm_full_scan_interval_ms;
-
-       _I("[DEDUP] deduplication mode: %s", dedup_mode == DEDUP_MODE_PERIODIC ?
-                       "kernel-managed" : "resourced-triggered");
-       _I("[DEDUP] deduplication on boot: %s", dedup_at_boot_enable ? "true" : "false");
-       _I("[DEDUP] scanning is invoked by %s", dedup_on_lowmem ?
-                       "LOWMEM event" : "periodic timer");
-       _I("[DEDUP] full scan interval: %d sec", dedup_full_scan_interval_sec);
-       _I("[DEDUP] stat monitoring interval: %d sec", dedup_stat_interval_sec);
-
-       _I("[DEDUP] ksm pages to scan: %d", ksm_params[KSM_PARAM_PAGES_TO_SCAN]);
-       _I("[DEDUP] ksm sleep time: %d ms", ksm_params[KSM_PARAM_SLEEP_MSECS]);
-       _I("[DEDUP] ksm full scan interval: %d ms", ksm_params[KSM_PARAM_FULL_SCAN_INTERVAL_MSECS]);
-       _I("[DEDUP] ksm scan boost: %d", ksm_params[KSM_PARAM_SCAN_BOOST]);
-
-free_dedup_conf:
-       free_dedup_conf();
-
-       return RESOURCED_ERROR_NONE;
-}
-
-static inline void init_dedup_stat(void)
-{
-       int i, j;
-       for (i = KSM_STAT_PAGES_SHARING; i < KSM_STAT_MAX; i++)
-               for (j = 0; j < KSM_STAT_WINDOW_MAX; j++)
-                       ksm_stats[i][j] = 0;
-       ksm_stat_window = 0;
-}
-
-static int dedup_init(void)
-{
-       int ret;
-
-       init_dedup_stat();
-       ret = dedup_parse_config_file();
-       if (ret < 0)
-               return ret;
-
-       if (!dedup_enable)
-               return -ENODEV;
-
-       /* initialize time variables */
-       if (!clock_gettime(CLOCK_MONOTONIC, &now)) {
-               partial_begin = now;
-               full_begin = now;
-       } else {
-               _I("Time initialization failed");
-               memset(&partial_begin, 0, sizeof(struct timespec));
-               memset(&full_begin, 0, sizeof(struct timespec));
-       }
-
-       return ret;
-}
-
-static int resourced_dedup_check_runtime_support(void *data)
-{
-       /*
-        * Check whether CONFIG_LKSM is enabled in kernel.
-        */
-       if (access("/sys/kernel/mm/ksm/run", R_OK) != 0) {
-               _I("the kernel doesn't support KSM, please check kernel configuration");
-               return -ENOENT;
-       }
-       if (access("/sys/kernel/mm/ksm/one_shot_scanning", R_OK) != 0) {
-               _I("the kernel support KSM but not LKSM, please check kernel configuration");
-               return -ENOENT;
-       }
-
-       return 0;
-}
-
-static int resourced_dedup_init(void *data)
-{
-       int ret;
-
-       dedup_set_state(DEDUP_OFF);
-
-       ret = dedup_init();
-       if (ret != RESOURCED_ERROR_NONE)
-               return ret;
-       _I("resourced dedup module is initialized");
-       register_notifier(RESOURCED_NOTIFIER_DEDUP_START, dedup_start_handler);
-       register_notifier(RESOURCED_NOTIFIER_DEDUP_SCAN, dedup_scan_handler);
-       register_notifier(RESOURCED_NOTIFIER_DEDUP_STOP, dedup_stop_handler);
-       register_notifier(RESOURCED_NOTIFIER_BOOTING_DONE, dedup_booting_done);
-
-       return ret;
-}
-
-static int resourced_dedup_finalize(void *data)
-{
-       unregister_notifier(RESOURCED_NOTIFIER_DEDUP_START, dedup_start_handler);
-       unregister_notifier(RESOURCED_NOTIFIER_DEDUP_SCAN, dedup_scan_handler);
-       unregister_notifier(RESOURCED_NOTIFIER_DEDUP_STOP, dedup_stop_handler);
-       unregister_notifier(RESOURCED_NOTIFIER_BOOTING_DONE, dedup_booting_done);
-
-       dedup_deactivate_in_module();
-
-       _I("dedup module will be finalized");
-
-       return RESOURCED_ERROR_NONE;
-}
-
-static struct module_ops dedup_module_ops = {
-       .priority = MODULE_PRIORITY_NORMAL,
-       .name = "dedup",
-       .init = resourced_dedup_init,
-       .exit = resourced_dedup_finalize,
-       .check_runtime_support = resourced_dedup_check_runtime_support,
-};
-
-MODULE_REGISTER(&dedup_module_ops)