Merge branch 'devel/tizen_2.4' into tizen 27/53127/2
authorPrajwal A N <an.prajwal@samsung.com>
Tue, 1 Dec 2015 23:46:00 +0000 (08:46 +0900)
committerPrajwal A N <an.prajwal@samsung.com>
Wed, 2 Dec 2015 04:57:31 +0000 (13:57 +0900)
Signed-off-by: Prajwal A N <an.prajwal@samsung.com>
Change-Id: Ib4e8153b78c98d926d8f32ac2c3a47deee67b567

25 files changed:
1  2 
CMakeLists.txt
data/resourced_proc_exclude.ini
packaging/resourced.spec
src/CMakeLists.txt
src/block/block-monitor.c
src/freezer/freezer.c
src/freezer/libsystem-freezer.so.arm64
src/freezer/libsystem-freezer.so.armv7l
src/heart/decision.c
src/heart/heart.c
src/heart/logging.c
src/mem-stress/mem-stress.c
src/memory/vmpressure-lowmem-handler.c
src/memps/CMakeLists.txt
src/network/CMakeLists.txt
src/network/datausage-common.c
src/proc-stat/CMakeLists.txt
src/proc-stat/proc-appusage.c
src/proc-stat/proc-info.c
src/proc-stat/proc-main.c
src/resourced-dbus/resourced-dbus.c
src/resourced/resourced.service
src/sluggish/sluggish.c
src/swap/swap.c
src/timer-slack/timer-slack.c

diff --cc CMakeLists.txt
@@@ -80,19 -73,12 +72,11 @@@ SET(NETWORK_SOURCE_DIR          ${SOURC
  SET(COMMON_SOURCE_DIR           ${SOURCE_DIR}/common)
  SET(CPU_SOURCE_DIR              ${SOURCE_DIR}/cpu)
  SET(VIP_SOURCE_DIR              ${SOURCE_DIR}/vip-agent)
- SET(TIMER_SOURCE_DIR              ${SOURCE_DIR}/timer-slack)
+ SET(TIMER_SOURCE_DIR            ${SOURCE_DIR}/timer-slack)
+ SET(BLOCK_SOURCE_DIR            ${SOURCE_DIR}/block)
+ SET(RESOURCED_DBUS_SOURCE_DIR   ${SOURCE_DIR}/resourced-dbus)
  
 -INSTALL(FILES ${CMAKE_SOURCE_DIR}/lib${RESOURCED}.pc DESTINATION lib/pkgconfig)
 +INSTALL(FILES ${CMAKE_SOURCE_DIR}/lib${RESOURCED}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
  INSTALL(FILES ${CMAKE_SOURCE_DIR}/resourced.conf DESTINATION /etc/dbus-1/system.d)
 -INSTALL(FILES ${CMAKE_SOURCE_DIR}/resourced.rule DESTINATION /etc/smack/accesses2.d)
  
- FILE(MAKE_DIRECTORY ${RESOURCED}-cmake)
- CONFIGURE_FILE(${CMAKELISTS_DIR}/${RESOURCED}.txt ${RESOURCED}-cmake/CMakeLists.txt COPYONLY)
- ADD_SUBDIRECTORY(${PROC-STAT_SOURCE_DIR})
- ADD_SUBDIRECTORY(${CMAKE_SOURCE_DIR}/${RESOURCED}-cmake)
- IF("${POWERTOP_MODULE}" STREQUAL "ON")
- ADD_SUBDIRECTORY(${POWERTOP-WRAPPER_SOURCE_DIR})
- ENDIF()
- ADD_SUBDIRECTORY(${MEMPS_SOURCE_DIR})
- ADD_SUBDIRECTORY(${NETWORK_SOURCE_DIR})
+ ADD_SUBDIRECTORY(src)
@@@ -11,4 -11,4 +11,5 @@@ nas9xepmna.context-servic
  popup
  testmode
  wakeup-service
+ admin-data
 +w-home
@@@ -5,48 -5,47 +5,52 @@@ Release:    
  Group:      System/Libraries
  License:    Apache-2.0
  Source0:    %{name}-%{version}.tar.gz
+ Source2:    resourced-cpucgroup.service
  
- %define powertop_state OFF
  %define cpu_module ON
- %define timer_slack OFF
  %define vip_agent_module ON
+ %define timer_slack OFF
  
- %define logging_module ON
- %define logging_memory OFF
- %define logging_cpu ON
+ %define heart_module ON
  
  %define memory_module ON
- %define swap_module OFF
- %define memory_vmpressure ON
+ %define block_module ON
+ %define wearable_noti OFF
  %define network_state OFF
- %if "%{?tizen_profile_name}" == "mobile"
-       %define swap_module OFF
-       %define memory_vmpressure OFF
-       %define network_state OFF
-       %define tethering_feature OFF
- %endif
+ %define memory_eng ON
++%define swap_module ON
++%define freezer_module OFF
 +%define tethering_feature OFF
++%define telephony_feature OFF
 +
+ %define slp_tests OFF
  
- %if "%{?tizen_profile_name}" == "wearable"
 -%if "%{?tizen_profile_name}" == "mobile"
++%if "%{?profile}" == "mobile"
        %define swap_module ON
-       %define memory_vmpressure ON
+       %define freezer_module ON
        %define network_state OFF
+       %define tethering_feature OFF
+       %define wearable_noti OFF
+       %define telephony_feature OFF
  %endif
  
- %if "%{?tizen_profile_name}" == "tv"
 -%if "%{?tizen_profile_name}" == "wearable"
++%if "%{?profile}" == "wearable"
+       %define freezer_module ON
        %define swap_module ON
-       %define memory_vmpressure ON
        %define network_state OFF
        %define tethering_feature OFF
+       %define wearable_noti ON
+       %define telephony_feature OFF
  %endif
  
- %if 0%{?tizen_build_binary_release_type_eng}
-       %define memory_eng ON
- %else
-       %define memory_eng OFF
 -%if "%{?tizen_profile_name}" == "tv"
++%if "%{?profile}" == "tv"
+       %define freezer_module OFF
+       %define swap_module OFF
+       %define network_state OFF
+       %define tethering_feature OFF
+       %define wearable_noti OFF
+       %define telephony_feature OFF
  %endif
  
  %define exclude_list_file_name resourced_proc_exclude.ini
@@@ -123,29 -133,35 +138,38 @@@ export CFLAGS="$CFLAGS -DTIZEN_DEBUG_EN
  export CXXFLAGS="$CXXFLAGS -DTIZEN_DEBUG_ENABLE"
  export FFLAGS="$FFLAGS -DTIZEN_DEBUG_ENABLE"
  
- %cmake . \
-       -DFULLVER=%{version} \
-       -DMAJORVER=${MAJORVER} \
-       -DCMAKE_BUILD_TYPE=Release \
-       -DEXCLUDE_LIST_FILE_NAME=%{exclude_list_file_name} \
-       -DEXCLUDE_LIST_FULL_PATH=%{exclude_list_full_path} \
-       -DEXCLUDE_LIST_OPT_FULL_PATH=%{exclude_list_opt_full_path} \
-       -DVIP_AGENT=%{vip_agent_module} \
-       -DSWAP_MODULE=%{swap_module} \
-       -DMEMORY_ENG=%{memory_eng} \
-       -DMEMORY_VMPRESSURE=%{memory_vmpressure} \
-       -DMEMORY_MODULE=%{memory_module} \
-       -DMEMORY_VMPRESSURE=%{memory_vmpressure} \
-       -DDATABASE_FULL_PATH=%{database_full_path} \
-       -DNETWORK_MODULE=%{network_state} \
-       -DTELEPHONY_FEATURE=%{telephony_feature} \
-       -DDATAUSAGE_TYPE=NFACCT \
-       -DLOGGING_MODULE=%{logging_module} \
-       -DLOGGING_MEMORY=%{logging_memory} \
-       -DLOGGING_CPU=%{logging_cpu} \
-       -DPOWERTOP_MODULE=%{powertop_state} \
-       -DCPU_MODULE=%{cpu_module} \
-       -DTIMER_SLACK=%{timer_slack}
+ %ifarch %{arm}
 -%define ARCH arm
++      %define ARCH armv7l
+ %else
 -%define ARCH i586
++      %ifarch aarch64
++              %define ARCH arm64
++      %else
++              %define ARCH i586
++      %endif
+ %endif
 -%cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} \
 -       -DFULLVER=%{version} \
++%cmake . -DFULLVER=%{version} \
+        -DMAJORVER=${MAJORVER} \
+        -DARCH=%{ARCH} \
+        -DCMAKE_BUILD_TYPE=Release \
+        -DEXCLUDE_LIST_FILE_NAME=%{exclude_list_file_name} \
+        -DEXCLUDE_LIST_FULL_PATH=%{exclude_list_full_path} \
+        -DDATABASE_FULL_PATH=%{database_full_path} \
+        -DEXCLUDE_LIST_OPT_FULL_PATH=%{exclude_list_opt_full_path} \
+        -DNETWORK_MODULE=%{network_state} \
+        -DSWAP_MODULE=%{swap_module} \
+        -DFREEZER_MODULE=%{freezer_module} \
+        -DCPU_MODULE=%{cpu_module} \
+        -DMEMORY_ENG=%{memory_eng} \
+        -DVIP_AGENT=%{vip_agent_module} \
+        -DTELEPHONY_FEATURE=%{telephony_feature} \
+        -DTIMER_SLACK=%{timer_slack} \
+        -DHEART_MODULE=%{heart_module} \
+        -DDATAUSAGE_TYPE=NFACCT \
+        -DMEMORY_MODULE=%{memory_module} \
+        -DWEARABLE_NOTI=%{wearable_noti} \
+        -DBLOCK_MODULE=%{block_module} \
+        -DSLP_TESTS=%{slp_tests}
  
  make %{?jobs:-j%jobs}
  
@@@ -166,14 -185,16 +193,13 @@@ cp -f LICENSE %{buildroot}/usr/share/li
        mkdir -p %{buildroot}/opt/usr/dbspace
        sqlite3 %{buildroot}%{database_full_path} < %{buildroot}/usr/share/traffic_db.sql
        rm %{buildroot}/usr/share/traffic_db.sql
+       sqlite3 %{buildroot}%{database_full_path} < %{buildroot}/usr/share/exception_db.sql
+       rm %{buildroot}/usr/share/exception_db.sql
  %endif
  
--mkdir -p %{buildroot}%{_libdir}/systemd/system/multi-user.target.wants
  
- #powertop-wrapper part
- %if %{?powertop_state} == ON
- mkdir -p %{buildroot}/usr/share/powertop-wrapper/
- cp -p %_builddir/%name-%version/src/powertop-wrapper/header.html %{buildroot}/usr/share/powertop-wrapper
+ %if %{?cpu_module} == OFF
 -mkdir -p %{buildroot}%{_libdir}/systemd/system/graphical.target.wants
 -install -m 0644 %SOURCE6 %{buildroot}%{_libdir}/systemd/system/resourced-cpucgroup.service
 -ln -s ../resourced-cpucgroup.service %{buildroot}%{_libdir}/systemd/system/graphical.target.wants/resourced-cpucgroup.service
++      %install_service graphical.target.wants resourced-cpucgroup.service
  %endif
  
  %pre resourced
@@@ -181,24 -202,13 +207,13 @@@ if [ "$1" = "2" ]; then # upgrade begin
        systemctl stop resourced.service
  fi
  
- %post -p /sbin/ldconfig
+ %post
  
- %post resourced
+ /sbin/ldconfig
  
- init_vconf()
- {
-       vconftool set -t bool db/private/resourced/wifi_statistics 1 -i -f -s tizen::vconf::platform::rw
-       vconftool set -t bool db/private/resourced/datacall 1 -i -f -s tizen::vconf::platform::rw
-       vconftool set -t bool db/private/resourced/datacall_logging 1 -i -f -s tizen::vconf::platform::rw
-       vconftool set -t int db/private/resourced/datausage_timer 60 -i -f -s tizen::vconf::platform::rw
-       vconftool set -t string db/private/resourced/new_limit "" -u 5000 -f -s tizen::vconf::platform::rw
-       vconftool set -t string db/private/resourced/delete_limit "" -u 5000 -f -s tizen::vconf::platform::rw
-       vconftool set -t int db/private/resourced/network_db_entries 0 -i -f -s tizen::vconf::platform::rw
- }
+ mkdir -p %{_sysconfdir}/systemd/default-extra-dependencies/ignore-units.d/
 -ln -sf %{_libdir}/systemd/system/resourced.service %{_sysconfdir}/systemd/default-extra-dependencies/ignore-units.d/
++ln -sf %{_unitdir}/resourced.service %{_sysconfdir}/systemd/default-extra-dependencies/ignore-units.d/
  
- %if %{?network_state} == ON
-       init_vconf
- %endif
  #install init.d script
  mkdir -p /opt/usr/etc
  #make empty dynamic exclude list for first installation
@@@ -208,11 -218,11 +223,12 @@@ if [ "$1" = "2" ]; then # upgrade begin
        systemctl start resourced.service
  fi
  
 +%postun -p /sbin/ldconfig
 +
  %files -n resourced
  /usr/share/license/%{name}
 -/etc/smack/accesses2.d/resourced.rule
  %attr(-,root, root) %{_bindir}/resourced
+ %manifest resourced.manifest
  %if %{?network_state} == ON
        %config(noreplace) %attr(660,root,app) %{database_full_path}
        %config(noreplace) %attr(660,root,app) %{database_full_path}-journal
        %config /etc/resourced/network.conf
        /etc/opt/upgrade/500.resourced-datausage.patch.sh
        %attr(700,root,root) /etc/opt/upgrade/500.resourced-datausage.patch.sh
+       %{_bindir}/net-cls-release
  %endif
- %manifest resourced.manifest
  %config %{_sysconfdir}/dbus-1/system.d/resourced.conf
 -%{_libdir}/systemd/system/resourced.service
 -%{_libdir}/systemd/system/multi-user.target.wants/resourced.service
 -%{_libdir}/systemd/system/resourced.socket
 -%{_libdir}/systemd/system/sockets.target.wants/resourced.socket
 +%{_unitdir}/resourced.service
 +%{_unitdir}/multi-user.target.wants/resourced.service
++%{_unitdir}/resourced.socket
++%{_unitdir}/sockets.target.wants/resourced.socket
  %config /etc/resourced/memory.conf
- %config /etc/resourced/cpu.conf
+ %config /etc/resourced/proc.conf
+ %if %{?cpu_module} == ON
+       %config /etc/resourced/cpu.conf
+ %else
+       %{_bindir}/resourced-cpucgroup.sh
 -      %{_libdir}/systemd/system/resourced-cpucgroup.service
 -      %{_libdir}/systemd/system/graphical.target.wants/resourced-cpucgroup.service
++      %{_unitdir}/resourced-cpucgroup.service
++      %{_unitdir}/graphical.target.wants/resourced-cpucgroup.service
+ %endif
  %if %{?swap_module} == ON
- %config /etc/resourced/swap.conf
- %{_unitdir}/resourced-zram.service
- %{_unitdir}/graphical.target.wants/resourced-zram.service
- %{_bindir}/resourced-zram.sh
+       %config /etc/resourced/swap.conf
  %endif
  %if %{?vip_agent_module} == ON
- %config /etc/resourced/vip-process.conf
- %attr(-,root, root) %{_bindir}/vip-release-agent
      %config /etc/resourced/vip-process.conf
      %attr(-,root, root) %{_bindir}/vip-release-agent
  %endif
  %if %{?timer_slack} == ON
- %config /etc/resourced/timer-slack.conf
+       %config /etc/resourced/timer-slack.conf
+ %endif
+ %if %{?block_module} == ON
+       %config /etc/resourced/block.conf
+ %endif
+ %if %{?freezer_module} == ON
+       %{_libdir}/libsystem-freezer.so*
+       %config /etc/resourced/freezer.conf
  %endif
  %{exclude_list_full_path}
- %if %{?powertop_state} == ON
- /usr/share/powertop-wrapper/header.html
+ %if %{?heart_module} == ON
+       %config /etc/resourced/heart.conf
+       %attr(700, root, root) /opt/etc/dump.d/module.d/dump_heart_data.sh
+       %attr(700, app, app) %{logging_storage_db_full_path}
+       %attr(700, app, app) %{logging_storage_db_full_path}-shm
+       %attr(700, app, app) %{logging_storage_db_full_path}-wal
+ %endif
+ %if %{?slp_tests} == ON
+       /usr/bin/resourced-test
+       /usr/lib/systemd/system/resourced-test.service
+       /usr/share/dbus-1/system-services/org.tizen.system.resourced-test.service
  %endif
  #memps
- %attr(-,root, root) %{_bindir}/memps
+ %attr(-,root, system) %{_bindir}/memps
+ #mem-stress
+ %attr(-,root, root) %{_bindir}/mem-stress
 -%{_libdir}/systemd/system/mem-stress.service
 -%{_libdir}/systemd/system/graphical.target.wants/mem-stress.service
++%{_unitdir}/mem-stress.service
++%{_unitdir}/graphical.target.wants/mem-stress.service
  
  %files -n libresourced
  %manifest libresourced.manifest
index 0000000,2dbf339..2691798
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,343 +1,344 @@@
 -SET(SOURCES ${SOURCES}
 -  ${RESOURCED_DBUS_SOURCE_DIR}/resourced-dbus.c
 -  )
+ CMAKE_MINIMUM_REQUIRED (VERSION 2.6)
+ #CMake doesnt' support same project name for several TARGETS
+ # libresourced uses it
+ PROJECT(resource_d)
+ INCLUDE(${CMAKE_SOURCE_DIR}/cmake/InstallSymlink.cmake)
+ INCLUDE(${CMAKE_SOURCE_DIR}/cmake/ProcessGPERF.cmake)
+ PROCESS_GPERF(${COMMON_SOURCE_DIR}/smaps-lookup.gperf ${COMMON_SOURCE_DIR}/smaps-lookup.c)
+ PROCESS_GPERF(${COMMON_SOURCE_DIR}/meminfo-lookup.gperf ${COMMON_SOURCE_DIR}/meminfo-lookup.c)
+ SET(RESOURCED_SHARED_SOURCES ${RESOURCED_SHARED_SOURCES}
+   ${COMMON_SOURCE_DIR}/smaps-lookup.c
+   ${COMMON_SOURCE_DIR}/meminfo-lookup.c
+   )
+ SET(CMAKE_EXTRA_INCLUDE_FILES unistd.h)
+ INCLUDE_DIRECTORIES(${RESOURCED_INCLUDEDIR}
+   ${RESOURCED_SOURCE_DIR}
+   ${HEART_SOURCE_DIR}/include
+   ${MEMORY_SOURCE_DIR}
+   ${PROC-STAT_SOURCE_DIR}/include
+   ${APP-STAT_SOURCE_DIR}/include
+   ${NETWORK_SOURCE_DIR}/include
+   ${BLOCK_SOURCE_DIR}/include
+   ${RESOURCED_DBUS_SOURCE_DIR}/include
+   ${FREEZER_SOURCE_DIR}/include
+ )
+ SET(SOURCES
+   ${PROC-STAT_SOURCE_DIR}/proc-handler.c
+   ${PROC-STAT_SOURCE_DIR}/proc-main.c
+   ${PROC-STAT_SOURCE_DIR}/proc-noti.c
+   ${PROC-STAT_SOURCE_DIR}/proc-process.c
+   ${PROC-STAT_SOURCE_DIR}/proc-monitor.c
+   ${PROC-STAT_SOURCE_DIR}/proc-usage-stats.c
+   ${PROC-STAT_SOURCE_DIR}/proc-usage-stats-helper.c
+   ${PROC-STAT_SOURCE_DIR}/proc-appusage.c
+   ${PROC-STAT_SOURCE_DIR}/proc-info.c
+   ${SLUGGISH_SOURCE_DIR}/sluggish.c
+   ${RESOURCED_SOURCE_DIR}/init.c
+   ${RESOURCED_SOURCE_DIR}/main.c
+   ${COMMON_SOURCE_DIR}/procfs.c
+   )
+ INSTALL(FILES ${DATA_DIR}/${EXCLUDE_LIST_FILE_NAME} DESTINATION /usr/etc)
+ #network module
+ IF("${NETWORK_MODULE}" STREQUAL "ON")
+   SET(SOURCES ${SOURCES}
+     ${NETWORK_SOURCE_DIR}/counter.c
+     )
+   IF("${DATAUSAGE_TYPE}" STREQUAL "NFACCT")
+     SET(CONFIG_DATAUSAGE_NFACCT 1)
+     SET(SOURCES ${SOURCES}
+       ${NETWORK_SOURCE_DIR}/nfacct-rule.c
+       ${NETWORK_SOURCE_DIR}/nf-restriction.c
+       )
+   ELSE()
+     SET(SOURCES ${SOURCES}
+       ${NETWORK_SOURCE_DIR}/generic-netlink.c
+       ${NETWORK_SOURCE_DIR}/ktgrabber-restriction.c
+       ${NETWORK_SOURCE_DIR}/ktgrabber-parser.c
+       )
+   ENDIF()
+   IF("${WEARABLE_NOTI}" STREQUAL "ON")
+     SET(SOURCES ${SOURCES}
+       ${NETWORK_SOURCE_DIR}/notification-wearable.c
+       )
+   ELSE()
+     SET(SOURCES ${SOURCES}
+       ${NETWORK_SOURCE_DIR}/notification-mobile.c
+       )
+   ENDIF()
+   SET(SOURCES ${SOURCES}
+     ${NETWORK_SOURCE_DIR}/counter-process.c
+     ${NETWORK_SOURCE_DIR}/options-private.c
+     ${NETWORK_SOURCE_DIR}/datausage-quota-processing.c
+     ${NETWORK_SOURCE_DIR}/datausage-vconf-callbacks.c
+     ${NETWORK_SOURCE_DIR}/datausage-vconf-common.c
+     ${NETWORK_SOURCE_DIR}/specific-trace.c
+     ${NETWORK_SOURCE_DIR}/datausage-common.c
+     ${NETWORK_SOURCE_DIR}/iface-cb.c
+     ${NETWORK_SOURCE_DIR}/nl-helper.c
+     ${NETWORK_SOURCE_DIR}/restriction-handler.c
+     ${NETWORK_SOURCE_DIR}/restriction-helper.c
+     ${NETWORK_SOURCE_DIR}/restriction-local.c
+     ${NETWORK_SOURCE_DIR}/tethering-restriction.c
+     ${NETWORK_SOURCE_DIR}/db-guard.c
+     )
+   INSTALL(FILES ${NETWORK_SOURCE_DIR}/network.conf
+     DESTINATION /etc/resourced)
+   INSTALL(FILES ${NETWORK_SOURCE_DIR}/500.resourced-datausage.patch.sh
+     DESTINATION /etc/opt/upgrade)
+   SET(REQUIRES_LIST ${REQUIRES_LIST}
+     openssl
+     tapi
+     )
+ ENDIF()
+ #freezer module
+ IF("${FREEZER_MODULE}" STREQUAL "ON")
+    SET(SOURCES ${SOURCES} ${FREEZER_SOURCE_DIR}/freezer.c)
++   ADD_DEFINITIONS("-DSYSTEM_LIB_PATH=\"${LIB_INSTALL_DIR}\"")
+ ELSE()
+    SET(SOURCES ${SOURCES} ${FREEZER_SOURCE_DIR}/freezer-common.c)
+ ENDIF()
+ #resourced DBus module
 -  INSTALL(FILES ${FREEZER_SOURCE_DIR}/libsystem-freezer.so.${ARCH} DESTINATION lib
++#SET(SOURCES ${SOURCES}
++#  ${RESOURCED_DBUS_SOURCE_DIR}/resourced-dbus.c
++#  )
+ IF("${VIP_AGENT}" STREQUAL "ON")
+   SET(SOURCES ${SOURCES}
+     ${VIP_SOURCE_DIR}/vip-process.c
+     )
+ ENDIF()
+ #heart module
+ IF("${HEART_MODULE}" STREQUAL "ON")
+   SET(SOURCES ${SOURCES}
+     ${HEART_SOURCE_DIR}/logging.c
+     ${HEART_SOURCE_DIR}/heart.c
+     ${HEART_SOURCE_DIR}/heart-abnormal.c
+     ${HEART_SOURCE_DIR}/heart-appopt.c
+     ${HEART_SOURCE_DIR}/heart-cpu.c
+     ${HEART_SOURCE_DIR}/heart-memory.c
+     ${HEART_SOURCE_DIR}/heart-battery.c
+     ${HEART_SOURCE_DIR}/heart-storage.c
+     ${HEART_SOURCE_DIR}/decision.c
+     ${HEART_SOURCE_DIR}/decision-memory.c
+     )
+   ADD_DEFINITIONS("-DHEART_SUPPORT")
+ ENDIF()
+ #memory module
+ IF("${MEMORY_MODULE}" STREQUAL "ON")
+   SET(SOURCES ${SOURCES}
+     ${MEMORY_SOURCE_DIR}/lowmem-dbus.c
+     ${MEMORY_SOURCE_DIR}/memcontrol.c
+     ${MEMORY_SOURCE_DIR}/vmpressure-lowmem-handler.c
+     )
+   ADD_DEFINITIONS("-DMEMORY_SUPPORT")
+ ENDIF()
+ #swap module
+ IF("${SWAP_MODULE}" STREQUAL "ON")
+   SET(SOURCES ${SOURCES}
+     ${SWAP_SOURCE_DIR}/swap.c
+     )
+   ADD_DEFINITIONS("-DSWAP_SUPPORT")
+ ENDIF()
+ IF("${CPU_MODULE}" STREQUAL "ON")
+   SET(SOURCES ${SOURCES}
+     ${CPU_SOURCE_DIR}/cpu.c
+     )
+ ENDIF()
+ IF("${TIMER_SLACK}" STREQUAL "ON")
+   SET(SOURCES ${SOURCES}
+     ${TIMER_SOURCE_DIR}/timer-slack.c
+     )
+ ENDIF()
+ IF("${BLOCK_MODULE}" STREQUAL "ON")
+   SET(SOURCES ${SOURCES}
+     ${BLOCK_SOURCE_DIR}/block.c
+     ${BLOCK_SOURCE_DIR}/block-monitor.c
+     )
+ ENDIF()
+ SET(REQUIRES_LIST ${REQUIRES_LIST}
+       ecore
+       dlog
+       glib-2.0
+       sqlite3
+       vconf
+       vconf-internal-keys
+       ecore-file
+       eina
+       edbus
+       eina
+       libsystemd
+       leveldb
+       eventsystem
+   )
+ INCLUDE(FindPkgConfig)
+ PKG_CHECK_MODULES(RESOURCED_REQUIRE_PKGS REQUIRED ${REQUIRES_LIST})
+ FOREACH(flag ${RESOURCED_REQUIRE_PKGS_CFLAGS})
+   SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ ENDFOREACH(flag)
+ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -pthread -fPIE")
+ CONFIGURE_FILE(${INCLUDE_COMMON_DIR}/config.h.in
+   ${INCLUDE_COMMON_DIR}/config.h)
+ # resourced shared static lib
+ FILE(GLOB FILES "${INCLUDE_COMMON_DIR}/*.h")
+ FOREACH(FILE ${FILES})
+   SET(RESOURCED_INCLUDE_HEADERS ${RESOURCED_INCLUDE_HEADERS} ${FILE})
+ ENDFOREACH()
+ SET(RESOURCED_INCLUDE_HEADERS ${RESOURCED_INCLUDE_HEADERS}
+   ${NETWORK_SOURCE_DIR}/include/datausage-vconf-callbacks.h
+   ${NETWORK_SOURCE_DIR}/include/iface-cb.h
+   )
+ FILE(GLOB FILES "${COMMON_SOURCE_DIR}/*.c")
+ FOREACH(FILE ${FILES})
+   SET(RESOURCED_SHARED_SOURCES ${RESOURCED_SHARED_SOURCES} ${FILE})
+ ENDFOREACH()
+ FILE(GLOB FILES "${COMMON_SOURCE_DIR}/*.h")
+ FOREACH(FILE ${FILES})
+   SET(RESOURCED_SHARED_HEADERS ${RESOURCED_SHARED_HEADERS} ${FILE})
+ ENDFOREACH()
+ ADD_LIBRARY(resourced_shared STATIC
+   ${RESOURCED_INCLUDE_HEADERS}
+   ${RESOURCED_SHARED_SOURCES}
+   ${RESOURCED_SHARED_HEADERS}
+   )
+ TARGET_LINK_LIBRARIES(resourced_shared ${RESOURCED_REQUIRE_PKGS_LDFLAGS})
+ ADD_EXECUTABLE(${PROJECT_NAME} ${SOURCES})
+ TARGET_LINK_LIBRARIES(${PROJECT_NAME}
+   resourced_shared ${RESOURCED_REQUIRE_PKGS_LDFLAGS} "-pie -lrt -lm -ldl"
+   )
+ INSTALL(FILES
+   ${RESOURCED_SOURCE_DIR}/${RESOURCED}.socket
+   ${RESOURCED_SOURCE_DIR}/${RESOURCED}.service
+   DESTINATION lib/systemd/system)
+ INSTALL_SYMLINK(../${RESOURCED}.socket lib/systemd/system/sockets.target.wants/${RESOURCED}.socket)
+ INSTALL_SYMLINK(../${RESOURCED}.service lib/systemd/system/multi-user.target.wants/${RESOURCED}.service)
+ IF("${NETWORK_MODULE}" STREQUAL "ON")
+   TARGET_LINK_LIBRARIES(${PROJECT_NAME}
+     resourced
+     app-stat
+     storage
+     settings
+     net-cls
+     telephony
+     net-iface
+     )
+   IF("${CMAKE_BUILD_TYPE}" STREQUAL  "DEBUG")
+     ADD_EXECUTABLE(test-udp-server ${UTILS_SOURCE_DIR}/udp-server.c ${UTILS_SOURCE_DIR}/udp-common.c)
+     ADD_EXECUTABLE(test-udp-client ${UTILS_SOURCE_DIR}/udp-client.c ${UTILS_SOURCE_DIR}/udp-common.c)
+     ADD_EXECUTABLE(iface-test ${UTILS_SOURCE_DIR}/iface-test.c)
+     TARGET_LINK_LIBRARIES(iface-test net-iface ${RESOURCED_REQUIRE_PKGS_LDFLAGS})
+   ENDIF()
+   INSTALL(FILES ${DATA_DIR}/traffic_db.sql
+     DESTINATION /usr/share)
+   INSTALL(FILES ${DATA_DIR}/exception_db.sql
+     DESTINATION /usr/share)
+ ENDIF()
+ INSTALL(FILES ${INCLUDE_PUBLIC_DIR}/resourced.h DESTINATION include/system)
+ SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SKIP_BUILD_RPATH true)
+ INSTALL(FILES ${PROJECT_NAME}
+   DESTINATION ${MAKE_INSTALL_PREFIX}/usr/bin RENAME resourced
+   PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE WORLD_EXECUTE)
+ IF("${MEMORY_ENG}" STREQUAL "ON")
+   INSTALL(FILES ${MEMORY_SOURCE_DIR}/memory_eng.conf
+     DESTINATION /etc/resourced RENAME memory.conf)
+ ELSE()
+   INSTALL(FILES ${MEMORY_SOURCE_DIR}/memory_user.conf
+     DESTINATION /etc/resourced RENAME memory.conf)
+ ENDIF()
+ IF("${SWAP_MODULE}" STREQUAL "ON")
+   INSTALL(FILES ${SWAP_SOURCE_DIR}/swap.conf DESTINATION /etc/resourced)
+ ENDIF()
+ IF("${HEART_MODULE}" STREQUAL "ON")
+   INSTALL(FILES ${HEART_SOURCE_DIR}/heart.conf
+     DESTINATION /etc/resourced RENAME heart.conf)
+   INSTALL(FILES ${HEART_SOURCE_DIR}/dump_heart_data.sh
+     DESTINATION /opt/etc/dump.d/module.d)
+ ENDIF()
+ IF("${CPU_MODULE}" STREQUAL "ON")
+   INSTALL(FILES ${CPU_SOURCE_DIR}/cpu.conf
+     DESTINATION /etc/resourced RENAME cpu.conf)
+ ELSE()
+   INSTALL(PROGRAMS ${CMAKE_BINARY_DIR}/scripts/resourced-cpucgroup.sh DESTINATION bin)
+ ENDIF()
+ IF("${TIMER_SLACK}" STREQUAL "ON")
+   INSTALL(FILES ${TIMER_SOURCE_DIR}/timer-slack.conf
+     DESTINATION /etc/resourced RENAME timer-slack.conf)
+ ENDIF()
+ IF("${VIP_AGENT}" STREQUAL "ON")
+   ADD_EXECUTABLE(vip-release-agent ${VIP_SOURCE_DIR}/vip-release-agent.c)
+   TARGET_LINK_LIBRARIES(vip-release-agent resourced_shared dlog)
+   INSTALL(TARGETS vip-release-agent DESTINATION bin)
+   INSTALL(FILES ${VIP_SOURCE_DIR}/vip-process.conf
+     DESTINATION
+     /etc/resourced RENAME vip-process.conf)
+ ENDIF()
+ IF("${BLOCK_MODULE}" STREQUAL "ON")
+   INSTALL(FILES ${BLOCK_SOURCE_DIR}/block.conf
+     DESTINATION /etc/resourced RENAME block.conf)
+ ENDIF()
+ IF("${FREEZER_MODULE}" STREQUAL "ON")
+   INSTALL(FILES ${FREEZER_SOURCE_DIR}/freezer.conf
+     DESTINATION /etc/resourced RENAME freezer.conf)
++  INSTALL(FILES ${FREEZER_SOURCE_DIR}/libsystem-freezer.so.${ARCH} DESTINATION ${LIB_INSTALL_DIR}
+     RENAME libsystem-freezer.so)
+ ENDIF()
+ INSTALL(FILES ${PROC-STAT_SOURCE_DIR}/proc.conf
+   DESTINATION /etc/resourced RENAME proc.conf)
+ ADD_EXECUTABLE(hashtest ${UTILS_SOURCE_DIR}/hashtest.c)
+ TARGET_LINK_LIBRARIES(hashtest ${RESOURCED_REQUIRE_PKGS_LDFLAGS})
+ ADD_SUBDIRECTORY(mem-stress)
+ ADD_SUBDIRECTORY(${PROC-STAT_SOURCE_DIR})
+ ADD_SUBDIRECTORY(${MEMPS_SOURCE_DIR})
+ ADD_SUBDIRECTORY(${NETWORK_SOURCE_DIR})
+ IF("${SLP_TESTS}" STREQUAL "ON")
+   ADD_SUBDIRECTORY(${TEST_DIR})
+ ENDIF()
index 0000000,1257d90..bc85c93
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,319 +1,322 @@@
 -      return (gboolean)strstr((char *)user_data, (char *)key);
+ /*
+  * 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 block-monitor.c
+  *
+  * @desc monitor file system using fanotify
+  *
+  * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+  *
+  */
+ #include <dirent.h>
+ #include <stdbool.h>
+ #include <errno.h>
+ #include <ctype.h>
+ #include <fcntl.h>
+ #include <sys/types.h>
+ #include <sys/time.h>
+ #include <sys/stat.h>
+ #include <sys/resource.h>
+ #include <sys/syscall.h>
+ #include <sys/fanotify.h>
+ #include <sys/mount.h>
+ #include <mntent.h>
+ #include <Ecore.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 "config-parser.h"
+ #include "const.h"
+ #include "file-helper.h"
+ #include "block.h"
+ #include "logging.h"
+ #define FAN_MODE_ACCESS               "ACCESS"
+ #define FAN_MODE_READ         "READ"
+ #define FAN_MODE_WRITE                "WRITE"
+ #define FAN_MODE_DISALBE      "DISALBE"
+ #define MAX_LOGGING_LIMIT     0x20000
+ enum block_mount_type {
+       BLOCK_MOUNT_ORIGINAL,
+       BLOCK_MOUNT_BIND,
+ };
+ enum block_logging_type {
+       BLOCK_LOGGING_NONE = 0x0,
+       BLOCK_LOGGING_DLOG = 0x1,
+       BLOCK_LOGGING_FILE = 0x2,
+       BLOCK_LOGGING_DB = 0x4,
+ };
+ static gboolean find_hash(gpointer key, gpointer value, gpointer user_data)
+ {
++      if (!user_data || !key)
++              return FALSE;
++
++      return (strstr((char *)user_data, (char *)key) ? TRUE : FALSE);
+ }
+ int convert_fanotify_mode(const char *mode)
+ {
+       int famode = FAN_EVENT_ON_CHILD;
+       if (!strncmp(mode, FAN_MODE_ACCESS, sizeof(FAN_MODE_ACCESS)))
+               famode |= FAN_OPEN;
+       else if (!strncmp(mode, FAN_MODE_READ, sizeof(FAN_MODE_READ)))
+               famode |= FAN_CLOSE_NOWRITE;
+       else if (!strncmp(mode, FAN_MODE_WRITE, sizeof(FAN_MODE_WRITE)))
+               famode |= FAN_CLOSE_WRITE;
+       else if (!strncmp(mode, FAN_MODE_DISALBE, sizeof(FAN_MODE_DISALBE)))
+               famode = 0;
+       return famode;
+ }
+ static bool check_mount_dest(const char *path)
+ {
+       bool ret = false;
+       struct mntent *mnt;
+       const char *table = "/etc/mtab";
+       FILE *fp;
+       int len = strlen(path);
+       fp = setmntent(table, "r");
+       if (!fp)
+               return ret;
+       do {
+               mnt = getmntent(fp);
+               if (mnt && !strncmp(mnt->mnt_dir, path, len)) {
+                       ret = true;
+                       break;
+               }
+       } while (mnt != NULL);
+       endmntent(fp);
+       return ret;
+ }
+ static void block_logging(struct block_monitor_info *bmi, pid_t pid,
+                                                   char *label, char *filename)
+ {
+       int type = bmi->logging;
+       if (type & BLOCK_LOGGING_DLOG)
+               _E("pid %d(%s) accessed %s", pid, label, filename);
+       if (type & BLOCK_LOGGING_FILE) {
+               FILE *f;
+               if (bmi->logpath == NULL) {
+                       bmi->logpath = malloc(MAX_PATH_LENGTH);
+                       if (!bmi->logpath) {
+                               _E("not enough memory");
+                               return;
+                       }
+                       snprintf(bmi->logpath, MAX_PATH_LENGTH-1, "/var/log/%s.log", strrchr(bmi->path, '/'));
+               }
+               f = fopen(bmi->logpath, "a+");
+               if (!f)
+                       return;
+               bmi->total_loglen += fprintf(f, "pid %d(%s) accessed %s\n", pid, label, filename);
+               fclose(f);
+               if (bmi->total_loglen > MAX_LOGGING_LIMIT) {
+                       if (unlink(bmi->logpath) < 0)
+                               _E("fail to remove %s file\n", bmi->logpath);
+                       else
+                               _I("clear previous log files");
+               }
+       }
+       if (type & BLOCK_LOGGING_DB) {
+               struct logging_data ld;
+               /*
+                * label in the xattr meant owner package name.
+                * block logging needed only package name.
+                * For removing overhead, block reqeusted to write label instead of appid or pkgid.
+                */
+               ld.appid = ld.pkgid = label;
+               ld.data = filename;
+               resourced_notify(RESOURCED_NOTIFIER_LOGGING_WRITE, &ld);
+       }
+ }
+ static Eina_Bool block_monitor_cb(void *user_data, Ecore_Fd_Handler *fd_handler)
+ {
+       int fd, n, ret;
+       struct fanotify_event_metadata *m;
+       union {
+               struct fanotify_event_metadata metadata;
+               char buffer[4096];
+       } data;
+       pid_t currentpid = getpid();
+       struct block_monitor_info *bmi = (struct block_monitor_info *)user_data;
+       gpointer hash = 0;
+       if (!ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ)) {
+               _E("ecore_main_fd_handler_active_get error , return\n");
+               return ECORE_CALLBACK_CANCEL;
+       }
+       fd = ecore_main_fd_handler_fd_get(fd_handler);
+       if (fd < 0) {
+               _E("ecore_main_fd_handler_fd_get error, return\n");
+               return ECORE_CALLBACK_CANCEL;
+       }
+       n = read(fd, &data, sizeof(data));
+       if (n < 0) {
+               _E("Failed to read fanotify event\n");
+               if (errno == EINTR || errno == EAGAIN || errno == EACCES)
+                       return ECORE_CALLBACK_RENEW;
+               else
+                       return ECORE_CALLBACK_CANCEL;
+       }
+       for (m = &data.metadata; FAN_EVENT_OK(m, n); m = FAN_EVENT_NEXT(m, n)) {
+               char fn[sizeof("/proc/self/fd/") + MAX_DEC_SIZE(int)];
+               char buf[MAX_PATH_LENGTH] = {0,};
+               char label[PROC_NAME_MAX];
+               if (m->fd < 0)
+                       goto next;
+               if (m->pid == currentpid)
+                       goto next;
+               snprintf(fn, sizeof(fn), "/proc/self/fd/%d", m->fd);
+               ret = readlink(fn, buf, sizeof(buf)-1);
+               if (ret < 0)
+                       goto next;
+               if (bmi->last_skip_pid == m->pid)
+                       goto next;
+               if (bmi->last_monitor_pid == m->pid)
+                       goto logging;
+               hash = bmi->block_exclude_path
+                    ? g_hash_table_find(bmi->block_exclude_path,
+                       find_hash, (gpointer)buf)
+                    : NULL;
+               if (hash) {
+                       bmi->last_skip_pid = m->pid;
+                       goto next;
+               }
+               ret = proc_get_label(m->pid, label);
+               if (ret < 0)
+                       goto next;
+               if (bmi->block_include_proc) {
+                       hash = g_hash_table_find(bmi->block_include_proc,
+                                   find_hash, (gpointer)label);
+                       if (!hash) {
+                               bmi->last_skip_pid = m->pid;
+                               goto next;
+                       }
+               }
+       logging:
+               bmi->last_monitor_pid = m->pid;
+               block_logging(bmi, m->pid, label, buf);
+       next:
+               close(m->fd);
+       }
+       return ECORE_CALLBACK_RENEW;
+ }
+ static void block_logging_init(struct block_monitor_info *bmi)
+ {
+       if (bmi->logging & BLOCK_LOGGING_DB) {
+               static const struct module_ops *heart;
+               heart = find_module("HEART");
+               if (!heart)
+                       bmi->logging &= (~BLOCK_LOGGING_DB);
+       }
+ }
+ int register_fanotify(struct block_monitor_info *bmi)
+ {
+       int ret;
+       if (!bmi || !strlen(bmi->path))
+               return RESOURCED_ERROR_NO_DATA;
+       _D("monitor register : path %s, mode %d", bmi->path, bmi->mode);
+       bmi->mfd = fanotify_init(FAN_CLOEXEC|FAN_NONBLOCK | FAN_CLASS_CONTENT,
+                           O_RDONLY | O_LARGEFILE | O_CLOEXEC | O_NOATIME);
+       if (bmi->mfd< 0)  {
+               _E("Failed to create fanotify fd");
+               goto error;
+         }
+       if (!check_mount_dest(bmi->path)) {
+               ret = mount(bmi->path, bmi->path, 0, MS_BIND, 0);
+               if (ret) {
+                       _E("Failed to mount monitor dir");
+                       goto error;
+               }
+               bmi->mount = BLOCK_MOUNT_BIND;
+       }
+       if (fanotify_mark(bmi->mfd, FAN_MARK_ADD | FAN_MARK_MOUNT,
+                           bmi->mode, AT_FDCWD, bmi->path) < 0) {
+               _E("Failed to mark fsnotify for %s", bmi->path);
+                 goto error;
+         }
+       bmi->fd_handler = ecore_main_fd_handler_add(
+               bmi->mfd, ECORE_FD_READ, block_monitor_cb, bmi, NULL, NULL);
+       block_logging_init(bmi);
+       return RESOURCED_ERROR_NONE;
+ error:
+       if (bmi->mfd) {
+               close(bmi->mfd);
+               bmi->mfd = 0;
+       }
+       if (bmi->logpath) {
+               free(bmi->logpath);
+               bmi->logpath = NULL;
+       }
+       return RESOURCED_ERROR_FAIL;
+ }
+ void unregister_fanotify(struct block_monitor_info *bmi)
+ {
+       int ret;
+       if (bmi) {
+               if (bmi->logpath)
+                       free(bmi->logpath);
+               if (bmi->mount == BLOCK_MOUNT_BIND) {
+                       ret = umount(bmi->path);
+                       if (ret)
+                               _E("Failed to umount partition : %s", bmi->path);
+                       bmi->mount = BLOCK_MOUNT_ORIGINAL;
+               }
+               close(bmi->mfd);
+               ecore_main_fd_handler_del(bmi->fd_handler);
+       }
+ }
index 0000000,7d2c377..ed7290e
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,333 +1,332 @@@
 -
+ /*
+  * 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 freezer.c
+  *
+  * @desc Freezer module
+  *
+  * Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved.
+  *
+  */
+ #include <dlfcn.h>
+ #include "macro.h"
+ #include "util.h"
+ #include "module.h"
+ #include "module-data.h"
+ #include "notifier.h"
+ #include "edbus-handler.h"
+ #include "resourced.h"
+ #include "trace.h"
+ #include "vconf.h"
+ #include "config-parser.h"
+ #include "procfs.h"
+ #include "proc-common.h"
 -#define FREEZER_MODULE_PATH "/usr/lib/libsystem-freezer.so"
+ #include "freezer.h"
 -static const struct module_ops freezer_modules_ops = {
++#define FREEZER_MODULE_PATH SYSTEM_LIB_PATH"/libsystem-freezer.so"
+ static int freezer_init_check;
+ /******************************************** Freezer symbols *************************************************/
+ /* Freezer cgroup late control setting retrieval */
+ int (*resourced_freezer_get_proc_late_control)(void) = NULL;
+ /* Freezer suspend status retrieval */
+ static bool (*resourced_freezer_is_suspended)(void) = NULL;
+ /* Freezer cgroup operation state */
+ static enum freezer_state (*resourced_freezer_get_operation_state)(void) = NULL;
+ /* Freezer module initialization and finalization functions */
+ static int (*resourced_freezer_initialize)(void *data) = NULL;
+ static int (*resourced_freezer_deinitialize)(void) = NULL;
+ /* Freezer module dbus method calls and signal handlers */
+ static DBusMessage *(*resourced_freezer_dbus_method_handler)(E_DBus_Object *obj, DBusMessage *msg) = NULL;
+ static void (*resourced_freezer_dbus_signal_handler)(void *data, DBusMessage *msg) = NULL;
+ /* Resourced notifier handlers */
+ static int (*resourced_freezer_change_state_cb)(void *data) = NULL;
+ static int (*resourced_freezer_service_launch)(void *data) = NULL;
+ static int (*resourced_freezer_wakeup)(void *data) = NULL;
+ static int (*resourced_freezer_service_wakeup)(void *data) = NULL;
+ static int (*resourced_freezer_app_suspend)(void *data) = NULL;
+ static int (*resourced_freezer_power_off)(void *data) = NULL;
+ /* dlopen handle for libfreezer */
+ static void *dlopen_handle;
+ /****************************************** Freezer symbols end ***********************************************/
+ /* freezer_proc_get_late_control function defined for freezer module on case */
+ int resourced_freezer_proc_late_control(void)
+ {
+       if (resourced_freezer_get_proc_late_control)
+               return resourced_freezer_get_proc_late_control();
+       _E("freezer_get_proc_late_control is not loaded!");
+       return 0;
+ }
+ /****************************************** Internal symbols **************************************************/
+ static DBusMessage *resourced_freezer_dbus_method_handler_generic(E_DBus_Object *obj, DBusMessage *msg)
+ {
+       DBusMessageIter iter;
+       DBusMessage *reply;
+       int ret;
+       if (resourced_freezer_dbus_method_handler)
+               return resourced_freezer_dbus_method_handler(obj, msg);
+       ret = 0;
+       reply = dbus_message_new_method_return(msg);
+       dbus_message_iter_init_append(reply, &iter);
+       dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
+       return reply;
+ }
+ static struct edbus_method edbus_methods[] = {
+       { METHOD_GET_FREEZER_STATE,     NULL,   "i", resourced_freezer_dbus_method_handler_generic },
+       { METHOD_GET_FREEZER_SERVICE,   NULL,   "i", resourced_freezer_dbus_method_handler_generic },
+       /* Add methods here */
+ };
+ static struct edbus_method edbus_suspend_methods[] = {
+       { METHOD_SET_FREEZER_SUSPEND,   "s", "i", resourced_freezer_dbus_method_handler_generic },
+       /* Add methods here */
+ };
+ static void freezer_dbus_init(bool is_suspend)
+ {
+       resourced_ret_c ret;
+       register_edbus_signal_handler(RESOURCED_PATH_FREEZER,
+                                     RESOURCED_INTERFACE_FREEZER,
+                                     SIGNAL_FREEZER_STATUS,
+                                     (void *)resourced_freezer_dbus_signal_handler,
+                                     NULL);
+       register_edbus_signal_handler(RESOURCED_PATH_FREEZER,
+                                     RESOURCED_INTERFACE_FREEZER,
+                                     SIGNAL_FREEZER_SERVICE,
+                                     (void *)resourced_freezer_dbus_signal_handler,
+                                     NULL);
+       ret = edbus_add_methods(RESOURCED_PATH_FREEZER,
+                               edbus_methods,
+                               ARRAY_SIZE(edbus_methods));
+       ret_msg_if(ret != RESOURCED_ERROR_NONE,
+                  "DBus method registration for %s is failed",
+                  RESOURCED_PATH_FREEZER);
+       if (!is_suspend)
+               return;
+       register_edbus_signal_handler(DEVICED_PATH_DISPLAY,
+                                     DEVICED_INTERFACE_DISPLAY,
+                                     SIGNAL_DEVICED_LCDONCOMPLETE,
+                                     (void *)resourced_freezer_dbus_signal_handler,
+                                     NULL);
+       ret = edbus_add_methods(RESOURCED_PATH_FREEZER,
+                               edbus_suspend_methods,
+                               ARRAY_SIZE(edbus_suspend_methods));
+       ret_msg_if(ret != RESOURCED_ERROR_NONE,
+                  "DBus method registration for %s is failed",
+                  RESOURCED_PATH_FREEZER);
+ }
+ static bool freezer_is_present(void)
+ {
+       struct stat buf;
+       /* Check if libfreezer.so is present or not */
+       if (stat(FREEZER_MODULE_PATH, &buf)) {
+               _E("Freezer library is not present @ %s", FREEZER_MODULE_PATH);
+               return false;
+       }
+       return true;
+ }
+ static void freezer_unload_symbols(void)
+ {
+ #define FREEZER_UNLOAD_SYMBOL(sym) \
+       sym = NULL;
+       FREEZER_UNLOAD_SYMBOL(resourced_freezer_get_proc_late_control);
+       FREEZER_UNLOAD_SYMBOL(resourced_freezer_is_suspended);
+       FREEZER_UNLOAD_SYMBOL(resourced_freezer_get_operation_state);
+       FREEZER_UNLOAD_SYMBOL(resourced_freezer_initialize);
+       FREEZER_UNLOAD_SYMBOL(resourced_freezer_deinitialize);
+       FREEZER_UNLOAD_SYMBOL(resourced_freezer_dbus_method_handler);
+       FREEZER_UNLOAD_SYMBOL(resourced_freezer_dbus_signal_handler);
+       FREEZER_UNLOAD_SYMBOL(resourced_freezer_change_state_cb);
+       FREEZER_UNLOAD_SYMBOL(resourced_freezer_service_launch);
+       FREEZER_UNLOAD_SYMBOL(resourced_freezer_wakeup);
+       FREEZER_UNLOAD_SYMBOL(resourced_freezer_service_wakeup);
+       FREEZER_UNLOAD_SYMBOL(resourced_freezer_app_suspend);
+       FREEZER_UNLOAD_SYMBOL(resourced_freezer_power_off);
+ #undef FREEZER_UNLOAD_SYMBOL
+       if (dlopen_handle) {
+               dlclose(dlopen_handle);
+               dlopen_handle = NULL;
+       }
+ }
+ static int freezer_load_symbols(void)
+ {
+       dlopen_handle = dlopen(FREEZER_MODULE_PATH, RTLD_NOW);
+       if (!dlopen_handle) {
+               _E("freezer dlopen failed!");
+               return RESOURCED_ERROR_FAIL;
+       }
+ #define FREEZER_LOAD_SYMBOL(sym, name) \
+       sym = dlsym(dlopen_handle, name); \
+       if (!sym) { \
+               _E("failed to dlsym %s", name); \
+               goto error; \
+       } \
+       FREEZER_LOAD_SYMBOL(resourced_freezer_get_proc_late_control, "freezer_get_proc_late_control");
+       FREEZER_LOAD_SYMBOL(resourced_freezer_is_suspended, "freezer_is_suspended");
+       FREEZER_LOAD_SYMBOL(resourced_freezer_get_operation_state, "freezer_get_operation_state");
+       FREEZER_LOAD_SYMBOL(resourced_freezer_initialize, "freezer_initialize");
+       FREEZER_LOAD_SYMBOL(resourced_freezer_deinitialize, "freezer_finalize");
+       FREEZER_LOAD_SYMBOL(resourced_freezer_dbus_method_handler, "freezer_dbus_method_handler");
+       FREEZER_LOAD_SYMBOL(resourced_freezer_dbus_signal_handler, "freezer_dbus_signal_handler");
+       FREEZER_LOAD_SYMBOL(resourced_freezer_change_state_cb, "freezer_change_state_cb");
+       FREEZER_LOAD_SYMBOL(resourced_freezer_service_launch, "freezer_service_launch");
+       FREEZER_LOAD_SYMBOL(resourced_freezer_wakeup, "freezer_wakeup");
+       FREEZER_LOAD_SYMBOL(resourced_freezer_service_wakeup, "freezer_service_wakeup");
+       FREEZER_LOAD_SYMBOL(resourced_freezer_app_suspend, "freezer_app_suspend");
+       FREEZER_LOAD_SYMBOL(resourced_freezer_power_off, "freezer_power_off");
+ #undef FREEZER_LOAD_SYMBOL
+       return RESOURCED_ERROR_NONE;
+ error:
+       freezer_unload_symbols();
+       return RESOURCED_ERROR_FAIL;
+ }
+ static int resourced_freezer_init(void *data)
+ {
+       int ret_code;
+       bool is_suspend;
+       bool is_present;
+       struct freezer_init_data init_data = { .resourced_app_list = &proc_app_list };
+       is_present = freezer_is_present();
+       if (!is_present) {
+               _E("Freezer library not present. Not enabling freezer");
+               return RESOURCED_ERROR_FAIL;
+       }
+       ret_code = freezer_load_symbols();
+       if (ret_code != RESOURCED_ERROR_NONE) {
+               _E("Not able to load symbols. Will use default definitions");
+               return RESOURCED_ERROR_FAIL;
+       }
+       ret_code = resourced_freezer_initialize(&init_data);
+       ret_value_msg_if(ret_code < 0, ret_code, "failed to initialize freezer module\n");
+       is_suspend = resourced_freezer_is_suspended();
+       freezer_dbus_init(is_suspend);
+       if (is_suspend)
+               register_notifier(RESOURCED_NOTIFIER_SERVICE_LAUNCH,
+                           resourced_freezer_service_launch);
+       register_notifier(RESOURCED_NOTIFIER_FREEZER_CGROUP_STATE,
+               resourced_freezer_change_state_cb);
+       register_notifier(RESOURCED_NOTIFIER_APP_WAKEUP,
+               resourced_freezer_wakeup);
+       register_notifier(RESOURCED_NOTIFIER_SERVICE_WAKEUP,
+               resourced_freezer_service_wakeup);
+       register_notifier(RESOURCED_NOTIFIER_APP_SUSPEND,
+               resourced_freezer_app_suspend);
+       register_notifier(RESOURCED_NOTIFIER_POWER_OFF,
+               resourced_freezer_power_off);
+       freezer_init_check = 1;
+       return RESOURCED_ERROR_NONE;
+ }
+ static int resourced_freezer_finalize(void *data)
+ {
+       if (freezer_init_check == 0)
+               return RESOURCED_ERROR_NONE;
+       freezer_init_check = 0;
+       resourced_freezer_deinitialize();
+       unregister_notifier(RESOURCED_NOTIFIER_FREEZER_CGROUP_STATE,
+               resourced_freezer_change_state_cb);
+       unregister_notifier(RESOURCED_NOTIFIER_SERVICE_LAUNCH,
+               resourced_freezer_service_launch);
+       unregister_notifier(RESOURCED_NOTIFIER_APP_WAKEUP,
+               resourced_freezer_wakeup);
+       unregister_notifier(RESOURCED_NOTIFIER_SERVICE_WAKEUP,
+               resourced_freezer_service_wakeup);
+       unregister_notifier(RESOURCED_NOTIFIER_APP_SUSPEND,
+               resourced_freezer_app_suspend);
+       unregister_notifier(RESOURCED_NOTIFIER_POWER_OFF,
+               resourced_freezer_power_off);
+       freezer_unload_symbols();
+       return RESOURCED_ERROR_NONE;
+ }
+ static int resourced_freezer_status(void *data)
+ {
+       struct freezer_status_data *f_data;
+       int ret = RESOURCED_ERROR_NONE;
+       if (!freezer_init_check)
+               return RESOURCED_ERROR_NONE;
+       f_data = (struct freezer_status_data *)data;
+       switch (f_data->type) {
+       case GET_STATUS:
+               ret = resourced_freezer_get_operation_state();
+               break;
+       default:
+               _E("Unsupported command: %d; status", f_data->type);
+       }
+       return ret;
+ }
++static struct module_ops freezer_modules_ops = {
+       .priority = MODULE_PRIORITY_NORMAL,
+       .name = "freezer",
+       .init = resourced_freezer_init,
+       .exit = resourced_freezer_finalize,
+       .status = resourced_freezer_status,
+ };
+ MODULE_REGISTER(&freezer_modules_ops)
index 0000000,0000000..15f325d
new file mode 100755 (executable)
Binary files differ
index 0000000,0000000..71e2e77
new file mode 100755 (executable)
Binary files differ
index 0000000,4a38ddf..3a66277
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,698 +1,698 @@@
 -      decisions[DECISION_THREAD_UPDATE].thread = (int)NULL;
+ /*
+  * 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 decision.c
+  *
+  * @desc decision for resourced
+  *
+  * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+  *
+  */
+ #include <Ecore.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <time.h>
+ #include <glib.h>
+ #include <sys/resource.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 "edbus-handler.h"
+ #include "decision.h"
+ #include "filemap.h"
+ #define DECISION_FILE_PATH    HEART_FILE_PATH"/.decision.dat"
+ #define DECISION_FILE_SIZE    (512 * 1024)
+ /* To Do: make configurable */
+ #define DECISION_WRITE_INTERVAL       60 * 30         /* 30 minute */
+ #define DECISION_PRIORITY     20
+ enum {
+       DECISION_THREAD_UPDATE,
+       DECISION_THREAD_WRITE,
+       DECISION_THREAD_MAX,
+ };
+ static pthread_mutex_t decision_list_mutex = PTHREAD_MUTEX_INITIALIZER;
+ static GHashTable *decision_app_list;
+ static pthread_mutex_t decision_queue_mutex = PTHREAD_MUTEX_INITIALIZER;
+ static GQueue *decision_queue;
+ static struct filemap *fm;
+ static const struct decision_module *decision_modules[DECISION_MAX];
+ static int num_decisions;
+ struct decision_thread {
+       pthread_t thread;
+       pthread_mutex_t mutex;
+       pthread_cond_t cond;
+ };
+ static struct decision_thread decisions[DECISION_THREAD_MAX];
+ static Ecore_Timer *decision_write_timer = NULL;
+ static const struct decision_module *decision_module_find(int type)
+ {
+       if (type < 0 || type >= DECISION_MAX)
+               return NULL;
+       return decision_modules[type];
+ }
+ static void* decision_info_find(struct decision_table *dt, int type)
+ {
+       if (!dt || type < 0 || type >= DECISION_MAX)
+               return NULL;
+       return dt->infos[type];
+ }
+ static int decision_table_init(struct decision_table *dt, const char *appid,
+       const char *pkgname)
+ {
+       int i;
+       if (!dt) {
+               _E("parameter dt is null");
+               return RESOURCED_ERROR_FAIL;
+       }
+       dt->ai = resourced_appinfo_get(dt->ai, appid, pkgname);
+       assert(dt->ai);
+       dt->updated = 0;
+       for (i = 0; i < DECISION_MAX; i++) {
+               const struct decision_module *dm;
+               void *info;
+               dm = decision_module_find(i);
+               if (!dm) {
+                       _E("cannot find decision module");
+                       return RESOURCED_ERROR_FAIL;
+               }
+               info = dm->create();
+               if (!info) {
+                       _E("cannot create info for type %d", i);
+                       return RESOURCED_ERROR_FAIL;
+               }
+               dt->infos[i] = info;
+       }
+       return RESOURCED_ERROR_NONE;
+ }
+ static struct decision_table *decision_table_new(const char *appid,
+       const char *pkgname)
+ {
+       struct decision_table *dt;
+       int ret;
+       dt = calloc(1, sizeof(struct decision_table));
+       if (!dt) {
+               _E("fail to allocate decision_table");
+               return NULL;
+       }
+       ret = decision_table_init(dt, appid, pkgname);
+       if (ret < 0) {
+               _E("fail to init decision table for appid = %s", appid);
+               free(dt);
+               return NULL;
+       }
+       g_hash_table_insert(decision_app_list, (gpointer)dt->ai->appid,
+               (gpointer)dt);
+       return dt;
+ }
+ static void decision_table_free(gpointer value)
+ {
+       struct decision_table *dt = (struct decision_table *)value;
+       int i;
+       if (!dt)
+               return;
+       for (i = 0; i < DECISION_MAX; i++) {
+               const struct decision_module *dm;
+               void * info;
+               dm = decision_module_find(i);
+               info = decision_info_find(dt, i);
+               if (dm && info)
+                       dm->free(info);
+       }
+       resourced_appinfo_put(dt->ai);
+       free(dt);
+ }
+ static struct decision_table *decision_table_find(const char *appid,
+       const char *pkgname)
+ {
+       struct decision_table *dt;
+       if (!decision_app_list) {
+               _E("decision app list was not created");
+               return NULL;
+       }
+       dt = g_hash_table_lookup(decision_app_list, (gconstpointer)appid);
+       if (!dt) {
+               dt = decision_table_new(appid, pkgname);
+               if (!dt) {
+                       _E("cannot create decision table for %s", appid);
+                       return NULL;
+               }
+       }
+       return dt;
+ }
+ struct decision_item *decision_item_new(int type, const char *appid, const char *pkgname)
+ {
+       struct decision_item *di;
+       di = malloc(sizeof(struct decision_item));
+       if (!di) {
+               _E("fail to allocate decision_item");
+               return NULL;
+       }
+       memset(di, 0, sizeof(struct decision_item));
+       di->type = type;
+       di->ai = resourced_appinfo_get(di->ai, appid, pkgname);
+       if (!di->ai) {
+               _E("fail to get appinfo for appid = %s, pkgname = %s",
+                       appid, pkgname);
+               free(di);
+               return NULL;
+       }
+       return di;
+ }
+ static void decision_item_free(struct decision_item *di)
+ {
+       if (!di)
+               return;
+       resourced_appinfo_put(di->ai);
+       free(di);
+ }
+ static int decision_item_update(struct decision_item *di)
+ {
+       const struct decision_module *dm;
+       struct decision_table *dt;
+       void *info;
+       if (!di || !di->ai) {
+               _E("invalid parameter decision item or null appinfo");
+               return RESOURCED_ERROR_FAIL;
+       }
+       pthread_mutex_lock(&decision_list_mutex);
+       dt = decision_table_find(di->ai->appid, di->ai->pkgname);
+       if (!dt) {
+               _E("there is no decision table for %s", di->ai->appid);
+               pthread_mutex_unlock(&decision_list_mutex);
+               return RESOURCED_ERROR_FAIL;
+       }
+       pthread_mutex_unlock(&decision_list_mutex);
+       info = decision_info_find(dt, di->type);
+       if (!info) {
+               _E("there is no info for type = %d", di->type);
+               return RESOURCED_ERROR_FAIL;
+       }
+       /* call sub module's update function */
+       dm = decision_module_find(di->type);
+       if (!dm) {
+               _E("invalid module index = %d", di->type);
+               return RESOURCED_ERROR_FAIL;
+       }
+       dm->update(di, info);
+       dt->updated = 1;
+       _D("update item for module %d for appid %s", dm->type, dt->ai->appid);
+       decision_item_free(di);
+       return RESOURCED_ERROR_NONE;
+ }
+ int decision_queue_item_insert(struct decision_item *di)
+ {
+       if (!di)
+               return RESOURCED_ERROR_FAIL;
+       pthread_mutex_lock(&decision_queue_mutex);
+       g_queue_push_tail(decision_queue, (gpointer)di);
+       pthread_mutex_unlock(&decision_queue_mutex);
+       return RESOURCED_ERROR_NONE;
+ }
+ static int decision_update(void)
+ {
+       struct decision_item *di;
+       int ret;
+       pthread_mutex_lock(&decision_queue_mutex);
+       while (!g_queue_is_empty(decision_queue)) {
+               di = g_queue_pop_head(decision_queue);
+               ret = decision_item_update(di);
+               if (ret < 0) {
+                       _E("fail to update item");
+                       pthread_mutex_unlock(&decision_queue_mutex);
+                       return RESOURCED_ERROR_FAIL;
+               }
+       }
+       pthread_mutex_unlock(&decision_queue_mutex);
+       _D("finish update deicion item");
+       return RESOURCED_ERROR_NONE;
+ }
+ static void decision_entry_read(const struct filemap_info *fi)
+ {
+       if (!fi)
+               return;
+       _D("read: name = %s, value = %s", fi->key, fi->value);
+ }
+ static int decision_table_write(struct decision_table *dt)
+ {
+       int i, size = 0;
+       /* buffer includes '\n' and null */
+       char buf[DECISION_BUF_MAX] = {0, };
+       char result_buf[DECISION_BUF_MAX] = {0, };
+       int ret = RESOURCED_ERROR_NONE;
+       if (!dt) {
+               _E("decision table is null or appinfo is null");
+               return RESOURCED_ERROR_FAIL;
+       }
+       assert(dt->ai);
+       if (!dt->updated)
+               return ret;
+       for (i = 0; i < DECISION_MAX; i++) {
+               const struct decision_module *dm = decision_module_find(i);
+               void *info = decision_info_find(dt, i);
+               if (!dm || !info) {
+                       _E("invalid decision module or decision info");
+                       continue;
+               }
+               dm->write(info, result_buf, DECISION_BUF_MAX);
+               size += snprintf(buf + size, DECISION_BUF_MAX - size, "\t%s",
+                               result_buf);
+               if (size >= DECISION_BUF_MAX) {
+                       _E("write buffer size exceeded size = %d", size);
+                       break;
+               }
+       }
+       ret = filemap_write(fm, dt->ai->appid, buf, &(dt->offset));
+       if (ret < 0)
+               _E("cannot write buf %s for %s", buf, dt->ai->appid);
+       _I("decision write buf: %s", buf);
+       dt->updated = 0;
+       return ret;
+ }
+ static int decision_write(void)
+ {
+       GHashTableIter iter;
+       gpointer key;
+       gpointer value;
+       struct decision_table *dt;
+       int ret;
+       g_hash_table_iter_init(&iter, decision_app_list);
+       pthread_mutex_lock(&decision_list_mutex);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               dt = (struct decision_table *)value;
+               ret = decision_table_write(dt);
+               if (ret < 0)
+                       _E("decision table write failed for %s", key);
+       }
+       pthread_mutex_unlock(&decision_list_mutex);
+       filemap_foreach_read(fm, filemap_root_node(fm), decision_entry_read);
+       return ret;
+ }
+ static int decision_app_terminated_cb(void *data)
+ {
+       struct proc_status *ps = (struct proc_status *)data;
+       struct decision_table *dt;
+       int ret;
+       if (!ps || !ps->pai || !ps->pai->program)
+               return RESOURCED_ERROR_FAIL;
+       pthread_mutex_lock(&decision_list_mutex);
+       dt = decision_table_find(ps->appid, ps->pai->program->pkgname);
+       if (!dt) {
+               pthread_mutex_unlock(&decision_list_mutex);
+               return RESOURCED_ERROR_FAIL;
+       }
+       ret = decision_table_write(dt);
+       if (ret < 0)
+               _D("decision table write failed for %s", ps->appid);
+       g_hash_table_remove(decision_app_list, (gconstpointer)ps->appid);
+       pthread_mutex_unlock(&decision_list_mutex);
+       _I("%s table is removed from decision table", ps->appid);
+       return RESOURCED_ERROR_NONE;
+ }
+ static void *decision_update_thread(void *arg)
+ {
+       int ret;
+       setpriority(PRIO_PROCESS, 0, DECISION_PRIORITY);
+       while (1) {
+               /*
+                * it starts fuction of writing decision result.
+                */
+               ret = pthread_mutex_lock(&decisions[DECISION_THREAD_UPDATE].mutex);
+               if (ret) {
+                       _E("decision write thread::pthread_mutex_lock() failed, %d", ret);
+                       break;
+               }
+               ret = pthread_cond_wait(&decisions[DECISION_THREAD_UPDATE].cond,
+                       &decisions[DECISION_THREAD_UPDATE].mutex);
+               if (ret) {
+                       _E("decision update thread::pthread_cond_wait() failed, %d", ret);
+                       ret = pthread_mutex_unlock(&decisions[DECISION_THREAD_UPDATE].mutex);
+                       if (ret)
+                               _E("decision update thread::pthread_mutex_lock() failed, %d", ret);
+                       break;
+               }
+               decision_update();
+               ret = pthread_mutex_unlock(&decisions[DECISION_THREAD_UPDATE].mutex);
+               if (ret) {
+                       _E("decision update thread::pthread_mutex_unlock() failed, %d", ret);
+                       break;
+               }
+       }
+       /* now our thread finishes - cleanup tid */
 -      decisions[DECISION_THREAD_WRITE].thread = (int)NULL;
++      decisions[DECISION_THREAD_UPDATE].thread = (long)NULL;
+       return NULL;
+ }
+ static void *decision_write_thread_main(void *arg)
+ {
+       int ret;
+       setpriority(PRIO_PROCESS, 0, DECISION_PRIORITY);
+       while (1) {
+               /*
+                * it starts fuction of writing decision result.
+                */
+               ret = pthread_mutex_lock(&decisions[DECISION_THREAD_WRITE].mutex);
+               if (ret) {
+                       _E("decision write thread::pthread_mutex_lock() failed, %d", ret);
+                       break;
+               }
+               ret = pthread_cond_wait(&decisions[DECISION_THREAD_WRITE].cond,
+                       &decisions[DECISION_THREAD_WRITE].mutex);
+               if (ret) {
+                       _E("decision write thread::pthread_cond_wait() failed, %d", ret);
+                       ret = pthread_mutex_unlock(&decisions[DECISION_THREAD_WRITE].mutex);
+                       if (ret)
+                               _E("decision write thread::pthread_mutex_lock() failed, %d", ret);
+                       break;
+               }
+               decision_write();
+               ret = pthread_mutex_unlock(&decisions[DECISION_THREAD_WRITE].mutex);
+               if (ret) {
+                       _E("decision write thread::pthread_mutex_unlock() failed, %d", ret);
+                       break;
+               }
+       }
+       /* now our thread finishes - cleanup tid */
 -                      decisions[DECISION_THREAD_UPDATE].thread = (int)NULL;
++      decisions[DECISION_THREAD_WRITE].thread = (long)NULL;
+       return NULL;
+ }
+ static int decision_thread_create(void)
+ {
+       int ret = RESOURCED_ERROR_NONE;
+       pthread_mutex_init(&decisions[DECISION_THREAD_UPDATE].mutex, NULL);
+       pthread_cond_init(&decisions[DECISION_THREAD_UPDATE].cond, NULL);
+       /* initialize decision_update_thread */
+        if (!decisions[DECISION_THREAD_UPDATE].thread) {
+               ret = pthread_create(&decisions[DECISION_THREAD_UPDATE].thread, NULL,
+                       (void *)decision_update_thread, (void *)NULL);
+               if (ret) {
+                       _E("pthread creation for decision_update_thread_main failed, %d\n", ret);
 -                      decisions[DECISION_THREAD_WRITE].thread = (int)NULL;
++                      decisions[DECISION_THREAD_UPDATE].thread = (long)NULL;
+                       return RESOURCED_ERROR_FAIL;
+               }
+               _D("pthread creation for decision update success");
+               pthread_detach(decisions[DECISION_THREAD_UPDATE].thread);
+       }
+        _I("decision update thread %u is running",
+                decisions[DECISION_THREAD_UPDATE].thread);
+       pthread_mutex_init(&decisions[DECISION_THREAD_WRITE].mutex, NULL);
+       pthread_cond_init(&decisions[DECISION_THREAD_WRITE].cond, NULL);
+       /* initialize decision_write_thread */
+       if (!decisions[DECISION_THREAD_WRITE].thread) {
+               ret = pthread_create(&decisions[DECISION_THREAD_WRITE].thread, NULL,
+                       (void *)decision_write_thread_main, (void *)NULL);
+               if (ret) {
+                       _E("pthread creation for decision_write_thread failed, %d\n", ret);
++                      decisions[DECISION_THREAD_WRITE].thread = (long)NULL;
+                       return RESOURCED_ERROR_FAIL;
+               }
+               _D("pthread creation for decision write success");
+               pthread_detach(decisions[DECISION_THREAD_WRITE].thread);
+       }
+        _I("decision update thread %u is running",
+                decisions[DECISION_THREAD_WRITE].thread);
+       return RESOURCED_ERROR_NONE;
+ }
+ int decision_update_start(void)
+ {
+       int ret;
+       _D("decision update callback function start");
+       /* signal to decision update thread */
+       ret = pthread_mutex_trylock(&decisions[DECISION_THREAD_UPDATE].mutex);
+       if (ret) {
+               _E("pthread_mutex_trylock fail : %d, errno : %d", ret, errno);
+               return RESOURCED_ERROR_FAIL;
+       }
+       pthread_cond_signal(&decisions[DECISION_THREAD_UPDATE].cond);
+       _I("send signal to decision update thread");
+       pthread_mutex_unlock(&decisions[DECISION_THREAD_UPDATE].mutex);
+       return RESOURCED_ERROR_NONE;
+ }
+ static Eina_Bool decision_send_signal_to_write(void *data)
+ {
+       int ret;
+       _D("decision write callback function start");
+       /* signal to decision write thread */
+       ret = pthread_mutex_trylock(&decisions[DECISION_THREAD_WRITE].mutex);
+       if (ret) {
+               _E("pthread_mutex_trylock fail : %d, errno : %d", ret, errno);
+               return ECORE_CALLBACK_RENEW;
+       }
+       pthread_cond_signal(&decisions[DECISION_THREAD_WRITE].cond);
+       _I("send signal to decision write thread");
+       pthread_mutex_unlock(&decisions[DECISION_THREAD_WRITE].mutex);
+       return ECORE_CALLBACK_RENEW;
+ }
+ static int decision_init(void)
+ {
+       int ret = RESOURCED_ERROR_NONE;
+       decision_app_list = g_hash_table_new_full(
+                       g_str_hash,
+                       g_str_equal,
+                       NULL,
+                       decision_table_free);
+       if (!decision_app_list) {
+               _E("fail to allocate decision app list");
+               return RESOURCED_ERROR_FAIL;
+       }
+       decision_queue = g_queue_new();
+       if (!decision_queue) {
+               g_hash_table_destroy(decision_app_list);
+               decision_app_list = NULL;
+               return RESOURCED_ERROR_FAIL;
+       }
+       g_queue_init(decision_queue);
+       ret = filemap_new(&fm, DECISION_FILE_PATH, DECISION_FILE_SIZE, 1);
+       if (ret < 0) {
+               _E("fail filemap_init");
+               g_hash_table_destroy(decision_app_list);
+               decision_app_list = NULL;
+               g_queue_free(decision_queue);
+               decision_queue = NULL;
+               return RESOURCED_ERROR_FAIL;
+       }
+       register_notifier(RESOURCED_NOTIFIER_APP_TERMINATED,
+               decision_app_terminated_cb);
+       if (decision_write_timer == NULL) {
+               _E("decision write timer start");
+               decision_write_timer = ecore_timer_add(DECISION_WRITE_INTERVAL,
+                       decision_send_signal_to_write, (void *)NULL);
+       }
+       ret = decision_thread_create();
+       return ret;
+ }
+ static int decision_exit(void)
+ {
+       if (decision_app_list) {
+               g_hash_table_destroy(decision_app_list);
+               decision_app_list = NULL;
+       }
+       if (decision_queue) {
+               g_queue_free(decision_queue);
+               decision_queue = NULL;
+       }
+       ecore_timer_del(decision_write_timer);
+       decision_write_timer = NULL;
+       unregister_notifier(RESOURCED_NOTIFIER_APP_TERMINATED,
+               decision_app_terminated_cb);
+       filemap_destroy(fm);
+       return RESOURCED_ERROR_NONE;
+ }
+ int decision_module_register(const struct decision_module *dm)
+ {
+       if (!dm) {
+               _E("parameter decision module is NULL");
+               return RESOURCED_ERROR_INVALID_PARAMETER;
+       }
+       if (num_decisions == 0)
+               decision_init();
+       if (decision_module_find(dm->type)) {
+               _E("%d is already exist", dm->type);
+               return RESOURCED_ERROR_INVALID_PARAMETER;
+       }
+       decision_modules[dm->type] = dm;
+       return RESOURCED_ERROR_NONE;
+ }
+ int decision_module_unregister(const struct decision_module *dm)
+ {
+       if (!dm) {
+               _E("parameter decision module is NULL");
+               return RESOURCED_ERROR_INVALID_PARAMETER;
+       }
+       decision_modules[dm->type] = NULL;
+       num_decisions--;
+       if (num_decisions == 0)
+               decision_exit();
+       return RESOURCED_ERROR_NONE;
+ }
index 0000000,ba4d4ac..be36c02
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,220 +1,220 @@@
 -static const struct module_ops heart_modules_ops = {
+ /*
+  * resourced
+  *
+  * Copyright (c) 2012 - 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.c
+  *
+  * @desc start heart for resourced
+  *
+  * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+  *
+  */
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <glib.h>
+ #include "notifier.h"
+ #include "trace.h"
+ #include "module.h"
+ #include "macro.h"
+ #include "heart.h"
+ #include "logging.h"
+ #include "resourced.h"
+ #include "config-parser.h"
+ #include "edbus-handler.h"
+ static GSList *heart_module;  /* module list */
+ void heart_module_add(const struct heart_module_ops *ops)
+ {
+       heart_module = g_slist_append(heart_module, (gpointer)ops);
+ }
+ void heart_module_remove(const struct heart_module_ops *ops)
+ {
+       heart_module = g_slist_remove(heart_module, (gpointer)ops);
+ }
+ static const struct heart_module_ops *heart_module_find(const char *name)
+ {
+       GSList *iter;
+       struct heart_module_ops *module;
+       gslist_for_each_item(iter, heart_module) {
+               module = (struct heart_module_ops *)iter->data;
+               if (!strcmp(module->name, name))
+                       return module;
+       }
+       return NULL;
+ }
+ static void heart_module_init(void *data)
+ {
+       GSList *iter;
+       const struct heart_module_ops *module;
+       int ret = RESOURCED_ERROR_NONE;
+       gslist_for_each_item(iter, heart_module) {
+               module = (struct heart_module_ops *)iter->data;
+               _D("Initialize [%s] module\n", module->name);
+               if (module->init)
+                       ret = module->init(data);
+               if (ret != RESOURCED_ERROR_NONE)
+                       _E("Fail to initialize [%s] module\n", module->name);
+       }
+ }
+ static void heart_module_exit(void *data)
+ {
+       GSList *iter;
+       const struct heart_module_ops *module;
+       int ret = RESOURCED_ERROR_NONE;
+       gslist_for_each_item(iter, heart_module) {
+               module = (struct heart_module_ops *)iter->data;
+               _D("Deinitialize [%s] module\n", module->name);
+               if (module->exit)
+                       ret = module->exit(data);
+               if (ret != RESOURCED_ERROR_NONE)
+                       _E("Fail to deinitialize [%s] module\n", module->name);
+       }
+ }
+ static int heart_load_config(struct parse_result *result, void *user_data)
+ {
+       const struct heart_module_ops *ops;
+       int *count = (int *)user_data;
+       if (!result)
+               return -EINVAL;
+       if (strcmp(result->section, HEART_CONF_SECTION))
+               return RESOURCED_ERROR_FAIL;
+       ops = heart_module_find(result->name);
+       if (!ops)
+               return RESOURCED_ERROR_FAIL;
+       if (!strcmp(result->value, "ON"))
+               *count = *count + 1;
+       else
+               heart_module_remove(ops);
+       return RESOURCED_ERROR_NONE;
+ }
+ static DBusMessage *edbus_update_data_list(E_DBus_Object *obj, DBusMessage *msg)
+ {
+       int ret;
+       DBusMessage *reply = NULL;
+       ret = dbus_message_get_args(msg, NULL, DBUS_TYPE_INVALID);
+       reply = dbus_message_new_method_return(msg);
+       if (!ret) {
+               _E("Wrong message arguments!");
+               return reply;
+       }
+       resourced_notify(RESOURCED_NOTIFIER_DATA_UPDATE, NULL);
+       logging_save_to_storage(true);
+       /* update data list from db */
+       logging_update(true);
+       return reply;
+ }
+ static DBusMessage *edbus_flush_cache(E_DBus_Object *obj, DBusMessage *msg)
+ {
+       int ret;
+       DBusMessage *reply = NULL;
+       ret = dbus_message_get_args(msg, NULL, DBUS_TYPE_INVALID);
+       reply = dbus_message_new_method_return(msg);
+       if (!ret) {
+               _E("Wrong message arguments!");
+               return reply;
+       }
+       /* flush module cache */
+       logging_save_to_storage(true);
+       return reply;
+ }
+ static const struct edbus_method edbus_methods[] = {
+       { "UpdateDataList", NULL, NULL, edbus_update_data_list },
+       { "Flush", NULL, NULL, edbus_flush_cache }
+ };
+ static int resourced_heart_init(void *data)
+ {
+       int ret, module_num = 0;
+       config_parse(HEART_CONF_FILE_PATH, heart_load_config, &module_num);
+       if (!module_num) {
+               _E("all heart modules have been disabled");
+               return RESOURCED_ERROR_NONE;
+       }
+       ret = edbus_add_methods(RESOURCED_PATH_LOGGING, edbus_methods, ARRAY_SIZE(edbus_methods));
+       if (ret != RESOURCED_ERROR_NONE) {
+               _E("DBus method registration for %s is failed", RESOURCED_PATH_LOGGING);
+       }
+       heart_module_init(data);
+       return RESOURCED_ERROR_NONE;
+ }
+ static int resourced_heart_dump(FILE *fp, int mode, void *data)
+ {
+       GSList *iter;
+       const struct heart_module_ops *module;
+       int ret = RESOURCED_ERROR_NONE;
+       logging_save_to_storage(true);
+       gslist_for_each_item(iter, heart_module) {
+               module = (struct heart_module_ops *)iter->data;
+               _D("Dump [%s] module\n", module->name);
+               if (module->dump)
+                       ret = module->dump(fp, mode, data);
+               if (ret != RESOURCED_ERROR_NONE)
+                       _E("Fail to dump [%s] module\n", module->name);
+       }
+       return RESOURCED_ERROR_NONE;
+ }
+ static int resourced_heart_exit(void *data)
+ {
+       heart_module_exit(data);
+       return RESOURCED_ERROR_NONE;
+ }
++static struct module_ops heart_modules_ops = {
+       .priority       = MODULE_PRIORITY_HIGH,
+       .name           = "HEART",
+       .init           = resourced_heart_init,
+       .dump           = resourced_heart_dump,
+       .exit           = resourced_heart_exit,
+ };
+ MODULE_REGISTER(&heart_modules_ops)
index 0000000,88bb34d..47497f4
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,1325 +1,1325 @@@
 -      unsigned int read_len;
+ /*
+  * resourced
+  *
+  * Copyright (c) 2012 - 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 logging.c
+  *
+  * @desc start logging system for resourced
+  *
+  * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+  *
+  */
+ #include <leveldb/c.h>
+ #include <Ecore.h>
+ #include <sqlite3.h>
+ #include <unistd.h>
+ #include <pthread.h>
+ #include <glib.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <time.h>
+ #include <string.h>
+ #include <stdarg.h>
+ #include <dirent.h>
+ #include <sys/stat.h>
+ #include <sys/types.h>
+ #include <sys/time.h>
+ #include <sys/resource.h>
+ #include <assert.h>
+ #include "trace.h"
+ #include "heart.h"
+ #include "logging.h"
+ #include "resourced.h"
+ #include "macro.h"
+ #include "module.h"
+ #include "config-parser.h"
+ #include "notifier.h"
+ #define LOGGING_BUF_MAX                       1024
+ #define LOGGING_PTIORITY              20
+ #define DB_SIZE_THRESHOLD             (50<<20)
+ #define LOGGING_FILE_PATH             HEART_FILE_PATH
+ #define CREATE_QUERY                  "CREATE TABLE IF NOT EXISTS %s (appid TEXT, pkgid TEXT, time INT, data TEXT, idx INT, PRIMARY KEY(time, idx));"
+ #define DELETE_QUERY_WITH_TIME        "DELETE from %s where time < %d;"
+ #define DELETE_QUERY_WITH_DATA        "DELETE from %s where data = ?;"
+ #define INSERT_QUERY                  "INSERT INTO %s values (?, ?, ?, ?, ?);"
+ #define SELECT_QUERY                  "SELECT * FROM %s WHERE time > %d AND time < %d;"
+ #define SELECT_BEGIN_QUERY            "SELECT * FROM %s "
+ #define SELECT_WHERE_QUERY            "WHERE"
+ #define SELECT_AND_QUERY              " AND"
+ #define SELECT_APPID_QUERY            " appid = \'%s\'"
+ #define SELECT_PKGID_QUERY            " pkgid = \'%s\'"
+ #define SELECT_START_QUERY            " time > %d"
+ #define SELECT_END_QUERY              " time < %d"
+ #define SELECT_FINISH_QUERY           ";"
+ #define FINALIZE_AND_RETURN_IF(cond, func, format, arg...) do \
+       { if (CONDITION(cond)) { \
+               func(format, ##arg); \
+               pthread_mutex_unlock(&(module->cache_mutex)); \
+               sqlite3_finalize(insert_stmt); \
+               sqlite3_finalize(delete_stmt); \
+               return; \
+       } } while (0)
+ enum { read_until_null = -1 };
+ struct logging_module {
+       char *name;
+       char *db_path;
+       sqlite3 *db;
+       enum logging_period max_period;
+       pthread_mutex_t cache_mutex;
+       logging_info_cb func;
+       time_t latest_update_time;
+       int saved_interval;
+       int updated_interval;
+       enum logging_interval save_interval;
+       enum logging_interval update_interval;
+       GQueue *cache;
+       GSList *listener;
+ };
+ struct logging_search {
+       char *appid;
+       char *pkgid;
+       time_t start;
+       time_t end;
+       void *user_data;
+       logging_info_cb func;
+ };
+ struct logging_listerner {
+       void (*func)(char *data);
+ };
+ static const struct module_ops logging_modules_ops;
+ static pthread_t logging_data_thread = 0;
+ static pthread_mutex_t logging_data_mutex = PTHREAD_MUTEX_INITIALIZER;
+ static pthread_cond_t logging_data_cond = PTHREAD_COND_INITIALIZER;
+ static Ecore_Timer *logging_data_timer = NULL;
+ static pthread_t logging_update_thread = 0;
+ static pthread_mutex_t logging_update_mutex = PTHREAD_MUTEX_INITIALIZER;
+ static pthread_cond_t logging_update_cond = PTHREAD_COND_INITIALIZER;
+ static Ecore_Timer *logging_update_timer = NULL;
+ static GArray *logging_modules;
+ static sqlite3 *logging_db;
+ static leveldb_t *logging_leveldb;
+ static leveldb_options_t *options;
+ static leveldb_readoptions_t *roptions;
+ static leveldb_writeoptions_t *woptions;
+ static struct logging_object *logging_instance = NULL;
+ time_t logging_get_time(int clk_id)
+ {
+       struct timespec ts;
+       if (clock_gettime(clk_id, &ts) == -1) {
+               _E("clock_gettime failed");
+               clock_gettime(CLOCK_MONOTONIC, &ts);
+       }
+       return ts.tv_sec;
+ }
+ long logging_get_time_ms(void)
+ {
+       struct timeval tv;
+       gettimeofday(&tv, NULL);
+       return (tv.tv_sec * 1000 + tv.tv_usec / 1000);
+ }
+ static struct logging_module *logging_find_module(char *name)
+ {
+       int i;
+       if (!logging_modules)
+               return NULL;
+       for (i = 0; i < logging_modules->len; i++) {
+               struct logging_module *module = g_array_index(logging_modules,
+                               struct logging_module *, i);
+               if (!strcmp(name, module->name)) {
+                       return module;
+               }
+       }
+       return NULL;
+ }
+ static int logging_db_busy(void * UNUSED user, int attempts)
+ {
+       struct timespec req, rem;
+       _E("DB locked by another process, attempts number %d", attempts);
+       req.tv_sec = 0;
+       req.tv_nsec = 500000000;
+       nanosleep(&req, &rem);
+       return 1;
+ }
+ int logging_module_init_with_db_path(char *name, enum logging_period max_period,
+               enum logging_interval save_interval, logging_info_cb func, enum logging_interval update_interval, const char *db_path)
+ {
+       int ret;
+       sqlite3 *db = NULL;
+       const char *path = NULL;
+       sqlite3_stmt *stmt = NULL;
+       char buf[LOGGING_BUF_MAX] = {0, };
+       struct logging_module *module;
+       if (!logging_instance) {
+               logging_instance = (struct logging_object *)malloc(sizeof(struct logging_object));
+               if (!logging_instance) {
+                       _E("Failed to malloc logging_instance");
+                       return RESOURCED_ERROR_OUT_OF_MEMORY;
+               }
+               logging_instance->ref = 0;
+               logging_init(NULL);
+       }
+       logging_instance->ref++;
+       /* check*/
+       if (logging_find_module(name)) {
+               _E("%s is already exist", name);
+               return RESOURCED_ERROR_INVALID_PARAMETER;
+       }
+       if (db_path) {
+               /* DB create */
+               if (sqlite3_open(db_path, &db) != SQLITE_OK) {
+                       _E("%s DB open failed (%s)", db_path, sqlite3_errmsg(db));
+                       return RESOURCED_ERROR_FAIL;
+               }
+               ret = sqlite3_exec(db, "PRAGMA locking_mode = NORMAL", 0, 0, 0);
+               if (ret != SQLITE_OK) {
+                       _E("Can't set locking mode %s", sqlite3_errmsg(db));
+                       _E("Skip set busy handler.");
+               } else {
+                       /* Set how many times we'll repeat our attempts for sqlite_step */
+                       if (sqlite3_busy_handler(db, logging_db_busy, NULL) != SQLITE_OK) {
+                               _E("Couldn't set busy handler!");
+                       }
+               }
+               path = db_path;
+       } else {
+               db = logging_db;
+               path = LOGGING_DB_FILE_NAME;
+       }
+       /* create table using module name and field_forms */
+       snprintf(buf, LOGGING_BUF_MAX, CREATE_QUERY, name);
+       ret = sqlite3_prepare_v2(db, buf, read_until_null, &stmt, NULL);
+       if (ret != SQLITE_OK) {
+               _E("create %s table failed %s", name, sqlite3_errmsg(db));
+               sqlite3_finalize(stmt);
+               return RESOURCED_ERROR_DB_FAILED;
+       }
+       if (sqlite3_step(stmt) != SQLITE_DONE) {
+               _E("create %s table failed %s", name, sqlite3_errmsg(db));
+               sqlite3_finalize(stmt);
+               return RESOURCED_ERROR_DB_FAILED;
+       }
+       sqlite3_finalize(stmt);
+       module = malloc(sizeof(struct logging_module));
+       if (!module) {
+               _E("malloc failed");
+               return RESOURCED_ERROR_OUT_OF_MEMORY;
+       }
+       /* make logging_module_inform and set module_inform */
+       module->db = db;
+       module->func = func;
+       module->latest_update_time = time(NULL);
+       module->save_interval = save_interval;
+       module->saved_interval = save_interval;
+       module->update_interval = update_interval;
+       module->updated_interval = update_interval;
+       module->listener = NULL;
+       if (asprintf(&(module->name), "%s", name) < 0) {
+               _E("asprintf failed");
+               free(module);
+               return RESOURCED_ERROR_OUT_OF_MEMORY;
+       }
+       if (asprintf(&(module->db_path), "%s", path) < 0) {
+               _E("asprintf failed");
+               free(module);
+               return RESOURCED_ERROR_OUT_OF_MEMORY;
+       }
+       module->max_period = max_period;
+       if (pthread_mutex_init(&module->cache_mutex, NULL) < 0) {
+               _E("%s module mutex_init failed %d", name, errno);
+               free(module->name);
+               free(module);
+               return RESOURCED_ERROR_FAIL;
+       }
+       module->cache = g_queue_new();
+       if (!module->cache) {
+               _E("g_queue_new failed");
+               free(module->name);
+               free(module);
+               return RESOURCED_ERROR_OUT_OF_MEMORY;
+       }
+       g_queue_init(module->cache);
+       g_array_append_val(logging_modules, module);
+       return RESOURCED_ERROR_NONE;
+ }
+ int logging_module_init(char *name, enum logging_period max_period,
+               enum logging_interval save_interval, logging_info_cb func, enum logging_interval update_interval)
+ {
+       return logging_module_init_with_db_path(name, max_period, save_interval, func, update_interval, NULL);
+ }
+ int logging_module_exit(void)
+ {
+       if (!logging_instance)
+               return RESOURCED_ERROR_NONE;
+       logging_instance->ref--;
+       if (logging_instance->ref == 0) {
+               free(logging_instance);
+               logging_instance = NULL;
+               logging_exit(NULL);
+       }
+       return RESOURCED_ERROR_NONE;
+ }
+ int logging_register_listener(char *name, logging_listener_cb listener_cb)
+ {
+       GSList *registerd;
+       struct logging_listerner *listener;
+       struct logging_module *module;
+       if (!listener_cb) {
+               _E("invalid listern func");
+               return RESOURCED_ERROR_INVALID_PARAMETER;
+       }
+       module = logging_find_module(name);
+       if (!module) {
+               _E("There is no %s module", name);
+               return RESOURCED_ERROR_INVALID_PARAMETER;
+       }
+       registerd = g_slist_find(module->listener, listener_cb);
+       if (registerd) {
+               _E("already registerd listener %x", listener_cb);
+               return RESOURCED_ERROR_INVALID_PARAMETER;
+       }
+       listener = malloc(sizeof(struct logging_listerner));
+       if (!listener) {
+               _E("Fail to malloc for notifier!");
+               return RESOURCED_ERROR_OUT_OF_MEMORY;
+       }
+       listener->func = listener_cb;
+       module->listener = g_slist_append(module->listener, listener);
+       return RESOURCED_ERROR_NONE;
+ }
+ int logging_unregister_listener(char *name, logging_listener_cb listener_cb)
+ {
+       GSList *registerd;
+       struct logging_module *module;
+       if (!listener_cb) {
+               _E("invalid listern func");
+               return RESOURCED_ERROR_INVALID_PARAMETER;
+       }
+       module = logging_find_module(name);
+       if (!module) {
+               _E("There is no %s module", name);
+               return RESOURCED_ERROR_INVALID_PARAMETER;
+       }
+       registerd = g_slist_find(module->listener, listener_cb);
+       if (!registerd) {
+               _E("It is not registered listerner %x", listener_cb);
+               return RESOURCED_ERROR_INVALID_PARAMETER;
+       }
+       module->listener = g_slist_remove(module->listener, registerd->data);
+       free(registerd->data);
+       return RESOURCED_ERROR_NONE;
+ }
+ int logging_operate(char *name, char *appid, char *pkgid, time_t time, char *data, int operation)
+ {
+       /* Save data to cache  */
+       struct logging_module *module;
+       struct logging_table_form *table;
+       module = logging_find_module(name);
+       if (!module) {
+               _E("There is no %s module", name);
+               return RESOURCED_ERROR_INVALID_PARAMETER;
+       }
+       table = malloc(sizeof(struct logging_table_form));
+       if (!table) {
+               _E("malloc failed");
+               return RESOURCED_ERROR_OUT_OF_MEMORY;
+       }
+       if (operation == INSERT) {
+               if (snprintf(table->appid, MAX_APPID_LENGTH, "%s", appid) < 0) {
+                       _E("snprintf failed");
+                       free(table);
+                       return RESOURCED_ERROR_OUT_OF_MEMORY;
+               }
+               if (snprintf(table->pkgid, MAX_PKGNAME_LENGTH, "%s", pkgid) < 0) {
+                       _E("snprintf failed");
+                       free(table);
+                       return RESOURCED_ERROR_OUT_OF_MEMORY;
+               }
+       }
+       table->time = time;
+       if (asprintf(&(table->data), "%s", data) < 0) {
+               _E("asprintf failed");
+               free(table);
+               return RESOURCED_ERROR_OUT_OF_MEMORY;
+       }
+       table->operation = operation;
+       pthread_mutex_lock(&(module->cache_mutex));
+       g_queue_push_tail(module->cache, (gpointer)table);
+       pthread_mutex_unlock(&(module->cache_mutex));
+       /* call listners */
+       if (module->listener) {
+               GSList *iter;
+               struct logging_listerner *listener;
+               char buf[LOGGING_BUF_MAX];
+               gslist_for_each_item(iter, module->listener) {
+                       listener = (struct logging_listerner *)iter->data;
+                       snprintf(buf, LOGGING_BUF_MAX, "%s %s %d %s", appid, pkgid, (int)time, data);
+                       listener->func(buf);
+               }
+       }
+       return RESOURCED_ERROR_NONE;
+ }
+ int logging_write(char *name, char *appid, char *pkgid, time_t time, char *data)
+ {
+       return logging_operate(name, appid, pkgid, time, data, INSERT);
+ }
+ int logging_delete(char *name, char *data)
+ {
+       time_t time = 0;
+       return logging_operate(name, NULL, NULL, time, data, DELETE);
+ }
+ int logging_leveldb_put(char *key, unsigned int key_len, char *value, unsigned int value_len)
+ {
+       char *err =  NULL;
+       if (!key || !key_len || !value || !value_len)
+               return RESOURCED_ERROR_INVALID_PARAMETER;
+       if (!logging_leveldb) {
+               _E("leveldb is not initialized");
+               return RESOURCED_ERROR_DB_FAILED;
+       }
+       leveldb_put(logging_leveldb, woptions, key, key_len, value, value_len, &err);
+       if (err != NULL) {
+               _E("Failed to put to leveldb");
+               return RESOURCED_ERROR_DB_FAILED;
+       }
+       free(err);
+       err = NULL;
+       _D("%s:%s", key, value);
+       return RESOURCED_ERROR_NONE;
+ }
+ int logging_leveldb_putv(char *key, unsigned int key_len, const char *fmt, ...)
+ {
+       char *err =  NULL;
+       va_list ap;
+       char value[LOGGING_BUF_MAX];
+       unsigned int value_len;
+       if (!key || !key_len || !fmt)
+               return RESOURCED_ERROR_INVALID_PARAMETER;
+       if (!logging_leveldb) {
+               _E("leveldb is not initialized");
+               return RESOURCED_ERROR_DB_FAILED;
+       }
+       va_start(ap, fmt);
+       vsnprintf(value, LOGGING_BUF_MAX, fmt, ap);
+       va_end(ap);
+       value_len = strlen(value);
+       if (!value_len) {
+               _E("Failed to get length of string");
+               return RESOURCED_ERROR_DB_FAILED;
+       }
+       leveldb_put(logging_leveldb, woptions, key, key_len, value, value_len, &err);
+       if (err != NULL) {
+               _E("Failed to put to leveldb");
+               return RESOURCED_ERROR_DB_FAILED;
+       }
+       free(err);
+       err = NULL;
+       _D("%s:%s", key, value);
+       return RESOURCED_ERROR_NONE;
+ }
+ int logging_leveldb_read(char *key, unsigned int key_len, char *value, unsigned int value_len)
+ {
++      size_t read_len;
+       char *err =  NULL;
+       char *result = NULL;
+       if (!key || !key_len || !value || !value_len)
+               return RESOURCED_ERROR_INVALID_PARAMETER;
+       if (!logging_leveldb) {
+               _E("leveldb is not initialized");
+               return RESOURCED_ERROR_DB_FAILED;
+       }
+       result = leveldb_get(logging_leveldb, roptions, key, key_len, &read_len, &err);
+       if (err != NULL) {
+               _E("Failed to get from leveldb");
+               return RESOURCED_ERROR_DB_FAILED;
+       }
+       free(err);
+       err = NULL;
+       if (value_len < read_len)
+               snprintf(value, value_len, "%s", result);
+       else
+               snprintf(value, read_len + 1, "%s", result);
+       free(result);
+       _D("%s:%s", key, value);
+       return RESOURCED_ERROR_NONE;
+ }
+ int logging_leveldb_delete(char *key, unsigned int key_len)
+ {
+       char *err =  NULL;
+       if (!key || !key_len)
+               return RESOURCED_ERROR_INVALID_PARAMETER;
+       if (!logging_leveldb) {
+               _E("leveldb is not initialized");
+               return RESOURCED_ERROR_DB_FAILED;
+       }
+       leveldb_delete(logging_leveldb, woptions, key, key_len, &err);
+       if (err != NULL) {
+               _E("Failed to delete from leveldb");
+               return RESOURCED_ERROR_DB_FAILED;
+       }
+       free(err);
+       err = NULL;
+       return RESOURCED_ERROR_NONE;
+ }
+ int logging_get_latest_in_cache(char *name, char *appid, char **data)
+ {
+       int i, len;
+       struct logging_module *module;
+       struct logging_table_form *table;
+       module = logging_find_module(name);
+       if (!module) {
+               _E("There is no %s module", name);
+               return RESOURCED_ERROR_INVALID_PARAMETER;
+       }
+       if (!appid) {
+               _E("appid parameter should be valid");
+               return RESOURCED_ERROR_INVALID_PARAMETER;
+       }
+       pthread_mutex_lock(&(module->cache_mutex));
+       len = g_queue_get_length(module->cache);
+       if (!len) {
+               _I("%s cache is empty", module->name);
+               pthread_mutex_unlock(&(module->cache_mutex));
+               return RESOURCED_ERROR_NO_DATA;
+       }
+       *data = NULL;
+       for (i = 0; i < len; i++) {
+               table = g_queue_peek_nth(module->cache, i);
+               if (table &&
+                       !strcmp(appid, table->appid))
+                       *data = table->data;
+       }
+       pthread_mutex_unlock(&(module->cache_mutex));
+       if (!*data) {
+               _E("NOT found in cache %s", appid);
+               return RESOURCED_ERROR_NO_DATA;
+       }
+       return RESOURCED_ERROR_NONE;
+ }
+ static void logging_cache_search(struct logging_table_form *data, struct logging_search *search)
+ {
+       /* search in cache */
+       /* true condition, call function */
+       if (search->appid) {
+               if (strcmp(search->appid, data->appid))
+                       return;
+               if (search->start && search->start < data->time)
+                       return;
+               if (search->end && search->end > data->time)
+                       return;
+       } else if (search->pkgid) {
+               if (strcmp(search->pkgid, data->pkgid))
+                       return;
+               if (search->start && search->start < data->time)
+                       return;
+               if (search->end && search->end > data->time)
+                       return;
+       } else if (search->start) {
+               if (search->start < data->time)
+                       return;
+               if (search->end && search->end > data->time)
+                       return;
+       } else if (search->end) {
+               if (search->end > data->time)
+                       return;
+       }
+       search->func(data, search->user_data);
+ }
+ int logging_read_foreach(char *name, char *appid, char *pkgid,
+               time_t start_time, time_t end_time, logging_info_cb callback, void *user_data)
+ {
+       /* Read from storage (cache & db) */
+       int result;
+       int len;
+       time_t cur_time;
+       sqlite3_stmt *stmt = NULL;
+       struct logging_table_form table;
+       struct logging_module *module;
+       struct logging_search search;
+       char buf[LOGGING_BUF_MAX] = {0, };
+       module = logging_find_module(name);
+       if (!module) {
+               _E("There is no %s module", name);
+               return RESOURCED_ERROR_INVALID_PARAMETER;
+       }
+       cur_time = time(NULL);
+       search.appid = NULL;
+       search.pkgid = NULL;
+       search.start = 0;
+       search.end = cur_time;
+       search.func = callback;
+       search.user_data = user_data;
+       len = snprintf(buf, LOGGING_BUF_MAX, SELECT_BEGIN_QUERY, name);
+       if (appid) {
+               len += snprintf(buf+len, LOGGING_BUF_MAX - len, SELECT_WHERE_QUERY);
+               search.appid = appid;
+               len += snprintf(buf+len, LOGGING_BUF_MAX - len, SELECT_APPID_QUERY, appid);
+               if (start_time) {
+                       search.start = start_time;
+                       len += snprintf(buf+len, LOGGING_BUF_MAX - len, SELECT_AND_QUERY);
+                       len += snprintf(buf+len, LOGGING_BUF_MAX - len, SELECT_START_QUERY, (int)start_time);
+               }
+       } else if (pkgid) {
+               len += snprintf(buf+len, LOGGING_BUF_MAX - len, SELECT_WHERE_QUERY);
+               search.pkgid = pkgid;
+               len += snprintf(buf+len, LOGGING_BUF_MAX - len, SELECT_PKGID_QUERY, pkgid);
+               if (start_time) {
+                       search.start = start_time;
+                       len += snprintf(buf+len, LOGGING_BUF_MAX - len, SELECT_AND_QUERY);
+                       len += snprintf(buf+len, LOGGING_BUF_MAX - len, SELECT_START_QUERY, (int)start_time);
+               }
+       } else if (start_time) {
+               len += snprintf(buf+len, LOGGING_BUF_MAX - len, SELECT_WHERE_QUERY);
+               search.start = start_time;
+               len += snprintf(buf+len, LOGGING_BUF_MAX - len, SELECT_START_QUERY, (int)start_time);
+       }
+       if (end_time && cur_time > end_time)
+               search.end = end_time;
+       len += snprintf(buf+len, LOGGING_BUF_MAX - len, SELECT_AND_QUERY);
+       len += snprintf(buf+len, LOGGING_BUF_MAX - len, SELECT_END_QUERY, (int)search.end);
+       len += snprintf(buf+len, LOGGING_BUF_MAX - len, SELECT_FINISH_QUERY);
+       /* search from db */
+       if (sqlite3_prepare_v2(module->db, buf, read_until_null, &stmt, NULL) != SQLITE_OK) {
+               _E("select failed");
+               sqlite3_finalize(stmt);
+               return RESOURCED_ERROR_DB_FAILED;
+       }
+       do {
+               result = sqlite3_step(stmt);
+               switch (result) {
+               case SQLITE_ROW:
+                       snprintf(table.appid, MAX_APPID_LENGTH, "%s", (char *)sqlite3_column_text(stmt, 0));
+                       snprintf(table.pkgid, MAX_PKGNAME_LENGTH, "%s", (char *)sqlite3_column_text(stmt, 1));
+                       table.time = sqlite3_column_int(stmt, 2);
+                       if (module->latest_update_time < table.time)
+                               module->latest_update_time = table.time;
+                       table.data = (char *)sqlite3_column_text(stmt, 3);
+                       callback(&table, user_data);
+                       break;
+               case SQLITE_DONE:
+                       break;
+               case SQLITE_ERROR:
+                       _E("select %s table failed %s", name, sqlite3_errmsg(module->db));
+                       /* FALLTHROUGH */
+               default:
+                       sqlite3_finalize(stmt);
+                       return RESOURCED_ERROR_DB_FAILED;
+               }
+       } while (result == SQLITE_ROW);
+       sqlite3_finalize(stmt);
+       /* search from cache */
+       if (!g_queue_is_empty(module->cache)) {
+               pthread_mutex_lock(&(module->cache_mutex));
+               g_queue_foreach(module->cache, (GFunc)logging_cache_search, (gpointer)&search);
+               pthread_mutex_unlock(&(module->cache_mutex));
+       }
+       return RESOURCED_ERROR_NONE;
+ }
+ static int logging_reset(char *name)
+ {
+       /* Table cut using max period */
+       time_t curr_time, del_time;
+       sqlite3_stmt *stmt = NULL;
+       struct logging_module *module;
+       char buf[LOGGING_BUF_MAX] = {0, };
+       module = logging_find_module(name);
+       if (!module) {
+               _E("There is no %s module", name);
+               return RESOURCED_ERROR_INVALID_PARAMETER;
+       }
+       time(&curr_time);
+       switch (module->max_period) {
+       case ONE_HOUR:
+               del_time = curr_time - HOUR_TO_SEC(1);
+               break;
+       case THREE_HOUR:
+               del_time = curr_time - HOUR_TO_SEC(3);
+               break;
+       case SIX_HOUR:
+               del_time = curr_time - HOUR_TO_SEC(6);
+               break;
+       case TWELVE_HOUR:
+               del_time = curr_time - HOUR_TO_SEC(12);
+               break;
+       case ONE_DAY:
+               del_time = curr_time - HOUR_TO_SEC(24);
+               break;
+       case ONE_WEEK:
+               del_time = curr_time - DAY_TO_SEC(7);
+               break;
+       case ONE_MONTH:
+               del_time = curr_time - MONTH_TO_SEC(1);
+               break;
+       case FOUR_MONTH:
+               del_time = curr_time - MONTH_TO_SEC(4);
+               break;
+       default:
+               _E("%s invalid max period", module->name);
+               return RESOURCED_ERROR_INVALID_PARAMETER;
+       }
+       snprintf(buf, LOGGING_BUF_MAX, DELETE_QUERY_WITH_TIME, name, (int)del_time);
+       if (sqlite3_prepare_v2(module->db, buf, read_until_null, &stmt, NULL) != SQLITE_OK) {
+               _E("delete %s table failed %s", name, sqlite3_errmsg(module->db));
+               sqlite3_finalize(stmt);
+               return RESOURCED_ERROR_DB_FAILED;
+       }
+       if (sqlite3_step(stmt) != SQLITE_DONE) {
+               _E("delete %s table failed %s", name, sqlite3_errmsg(module->db));
+               sqlite3_finalize(stmt);
+               return RESOURCED_ERROR_DB_FAILED;
+       }
+       sqlite3_finalize(stmt);
+       return RESOURCED_ERROR_NONE;
+ }
+ static int logging_check_storage_size(const char *db_path)
+ {
+       int ret;
+       struct stat db_stat = {0};
+       if (!db_path)
+               return RESOURCED_ERROR_INVALID_PARAMETER;
+       ret = stat(db_path, &db_stat);
+       if (ret) {
+               _E("Failed to get statistics for %s errno %d",
+                               db_path, errno);
+               return RESOURCED_ERROR_DB_FAILED;
+       }
+       if (db_stat.st_size >= DB_SIZE_THRESHOLD)
+               return RESOURCED_ERROR_FAIL;
+       return RESOURCED_ERROR_NONE;
+ }
+ void logging_update(int force)
+ {
+       int i, ret;
+       sqlite3_stmt *stmt = NULL;
+       struct logging_table_form table;
+       struct logging_module *module;
+       char buf[LOGGING_BUF_MAX] = {0, };
+       if (!logging_modules)
+               return;
+       for (i = 0; i < logging_modules->len; i++) {
+               module = g_array_index(logging_modules,
+                               struct logging_module *, i);
+               /* no update when module update func is not registered */
+               if (module->func == NULL)
+                       continue;
+               if (!force && module->updated_interval > 0) {
+                       module->updated_interval -= ONE_MINUTE;
+                       continue;
+               }
+               module->updated_interval = module->update_interval;
+               snprintf(buf, LOGGING_BUF_MAX, SELECT_QUERY, module->name,
+                               (int)module->latest_update_time, (int)time(NULL));
+               ret = sqlite3_prepare_v2(module->db, buf, read_until_null, &stmt, NULL);
+               if (ret != SQLITE_OK) {
+                       _E("select failed");
+                       sqlite3_finalize(stmt);
+                       return;
+               }
+               do {
+                       ret = sqlite3_step(stmt);
+                       switch (ret) {
+                       case SQLITE_ROW:
+                               snprintf(table.appid, MAX_APPID_LENGTH, "%s", (char *)sqlite3_column_text(stmt, 0));
+                               snprintf(table.pkgid, MAX_PKGNAME_LENGTH, "%s", (char *)sqlite3_column_text(stmt, 1));
+                               table.time = sqlite3_column_int(stmt, 2);
+                               if (module->latest_update_time < table.time)
+                                       module->latest_update_time = table.time;
+                               if (asprintf(&(table.data), "%s", (char *)sqlite3_column_text(stmt, 3)) < 0) {
+                                       _E("asprintf failed");
+                                       sqlite3_finalize(stmt);
+                                       return;
+                               }
+                               module->func(&table, NULL);
+                               free(table.data);
+                               break;
+                       case SQLITE_DONE:
+                               break;
+                       case SQLITE_ERROR:
+                               _E("select %s table failed %s", module->name, 
+                                                                       sqlite3_errmsg(module->db));
+                               /* FALLTHROUGH */
+                       default:
+                               sqlite3_finalize(stmt);
+                               return;
+                       }
+               } while (ret == SQLITE_ROW);
+               sqlite3_finalize(stmt);
+       }
+ }
+ void logging_save_to_storage(int force)
+ {
+       /* Save cache to storage */
+       static int index = 0;
+       int i, j, len, ret = 0;
+       sqlite3_stmt *insert_stmt = NULL;
+       sqlite3_stmt *delete_stmt = NULL;
+       char buf[LOGGING_BUF_MAX] = {0, };
+       struct logging_module *module;
+       struct logging_table_form *table;
+       if (!logging_modules)
+               return;
+       for (i = 0; i < logging_modules->len; i++) {
+               module = g_array_index(logging_modules, struct logging_module *, i);
+               if (!force && module->saved_interval > 0) {
+                       module->saved_interval -= ONE_MINUTE;
+                       continue;
+               }
+               module->saved_interval = module->save_interval;
+               /* find q and pop */
+               pthread_mutex_lock(&(module->cache_mutex));
+               len = g_queue_get_length(module->cache);
+               if (!len) {
+                       _I("%s cache is empty", module->name);
+                       pthread_mutex_unlock(&(module->cache_mutex));
+                       continue;
+               }
+               sqlite3_exec(module->db, "BEGIN;", NULL, NULL, NULL);
+               snprintf(buf, LOGGING_BUF_MAX, INSERT_QUERY, module->name);
+               ret = sqlite3_prepare_v2(module->db, buf, read_until_null, &insert_stmt, NULL);
+               FINALIZE_AND_RETURN_IF(ret != SQLITE_OK, _E, "insert %s table failed %s", module->name, sqlite3_errmsg(module->db));
+               snprintf(buf, LOGGING_BUF_MAX, DELETE_QUERY_WITH_DATA, module->name);
+               ret = sqlite3_prepare_v2(module->db, buf, read_until_null, &delete_stmt, NULL);
+               FINALIZE_AND_RETURN_IF(ret != SQLITE_OK, _E, "insert %s table failed %s", module->name, sqlite3_errmsg(module->db));
+               for (j = 0; j < len; j++) {
+                       table = g_queue_peek_head(module->cache);
+                       if (!table)
+                               continue;
+                       if (table->operation == DELETE) {
+                               sqlite3_reset(delete_stmt);
+                               ret = sqlite3_bind_text(delete_stmt, 1, table->data, -1, SQLITE_STATIC);
+                               FINALIZE_AND_RETURN_IF(ret != SQLITE_OK, _SE, "Can not bind data : %s for preparing statement", table->pkgid);
+                               ret = sqlite3_step(delete_stmt);
+                               FINALIZE_AND_RETURN_IF(ret != SQLITE_DONE, _E, "delete %s table failed %s", module->name, sqlite3_errmsg(module->db));
+                       } else {
+                               /* else if (table->operation == INSERT) */
+                               sqlite3_reset(insert_stmt);
+                               ret = sqlite3_bind_text(insert_stmt, 1, table->appid, -1, SQLITE_STATIC);
+                               FINALIZE_AND_RETURN_IF(ret != SQLITE_OK, _SE, "Can not bind appid : %s for preparing statement", table->appid);
+                               ret = sqlite3_bind_text(insert_stmt, 2, table->pkgid, -1, SQLITE_STATIC);
+                               FINALIZE_AND_RETURN_IF(ret != SQLITE_OK, _SE, "Can not bind pkgid : %s for preparing statement", table->pkgid);
+                               ret = sqlite3_bind_int(insert_stmt, 3, table->time);
+                               FINALIZE_AND_RETURN_IF(ret != SQLITE_OK, _SE, "Can not bind time : %d for preparing statement", table->time);
+                               ret = sqlite3_bind_text(insert_stmt, 4, table->data, -1, SQLITE_STATIC);
+                               FINALIZE_AND_RETURN_IF(ret != SQLITE_OK, _SE, "Can not bind data : %s for preparing statement", table->data);
+                               ret = sqlite3_bind_int(insert_stmt, 5, index++);
+                               FINALIZE_AND_RETURN_IF(ret != SQLITE_OK, _SE, "Can not bind index : %d for preparing statement", index);
+                               ret = sqlite3_step(insert_stmt);
+                               FINALIZE_AND_RETURN_IF(ret != SQLITE_DONE, _E, "insert %s table failed %s", module->name, sqlite3_errmsg(module->db));
+                       }
+                       table = g_queue_pop_head(module->cache);
+                       free(table);
+               }
+               pthread_mutex_unlock(&(module->cache_mutex));
+               sqlite3_exec(module->db, "COMMIT;", NULL, NULL, NULL);
+               sqlite3_finalize(insert_stmt);
+               insert_stmt = NULL;
+               sqlite3_finalize(delete_stmt);
+               delete_stmt = NULL;
+       }
+       for (i = 0; i < logging_modules->len; i++) {
+               module = g_array_index(logging_modules, struct logging_module *, i);
+               /* Check storage limitation by maximum period and storage size (50MiB) */
+               if (logging_check_storage_size(module->db_path) == RESOURCED_ERROR_FAIL) {
+                       logging_reset(module->name);
+                       sqlite3_exec(module->db, "VACUUM;", NULL, NULL, NULL);
+               }
+       }
+ }
+ static void *logging_data_thread_main(void *arg)
+ {
+       int ret = 0;
+       setpriority(PRIO_PROCESS, 0, LOGGING_PTIORITY);
+       while (1) {
+               /*
+                * When signalled by main thread,
+                * it starts logging_pthread().
+                */
+               ret = pthread_mutex_lock(&logging_data_mutex);
+               if (ret) {
+                       _E("logging data thread::pthread_mutex_lock() failed, %d", ret);
+                       break;
+               }
+               ret = pthread_cond_wait(&logging_data_cond, &logging_data_mutex);
+               if (ret) {
+                       _E("logging data thread::pthread_cond_wait() failed, %d", ret);
+                       ret = pthread_mutex_unlock(&logging_data_mutex);
+                       if (ret)
+                               _E("logging data thread::pthread_mutex_lock() failed, %d", ret);
+                       break;
+               }
+               logging_save_to_storage(false);
+               ret = pthread_mutex_unlock(&logging_data_mutex);
+               if (ret) {
+                       _E("logging data thread::pthread_mutex_unlock() failed, %d", ret);
+                       break;
+               }
+       }
+       /* Now our thread finishes - cleanup TID */
+       logging_data_thread = 0;
+       return NULL;
+ }
+ static Eina_Bool logging_send_signal_to_data(void *data)
+ {
+       int ret;
+       _D("logging timer callback function start");
+       /* signal to logging data thread for start logging */
+       ret = pthread_mutex_trylock(&logging_data_mutex);
+       if (ret)
+               _E("pthread_mutex_trylock fail : %d, errno : %d", ret, errno);
+       else {
+               pthread_cond_signal(&logging_data_cond);
+               _I("send signal to logging data thread");
+               pthread_mutex_unlock(&logging_data_mutex);
+       }
+       return ECORE_CALLBACK_RENEW;
+ }
+ static int logging_start(void *data)
+ {
+       return RESOURCED_ERROR_NONE;
+ }
+ static void *logging_update_thread_main(void *arg)
+ {
+       int ret = 0;
+       setpriority(PRIO_PROCESS, 0, LOGGING_PTIORITY);
+       while (1) {
+               /*
+                * it starts fuction of registered module.
+                */
+               ret = pthread_mutex_lock(&logging_update_mutex);
+               if (ret) {
+                       _E("logging update thread::pthread_mutex_lock() failed, %d", ret);
+                       break;
+               }
+               ret = pthread_cond_wait(&logging_update_cond, &logging_update_mutex);
+               if (ret) {
+                       _E("logging update thread::pthread_cond_wait() failed, %d", ret);
+                       ret = pthread_mutex_unlock(&logging_update_mutex);
+                       if (ret)
+                               _E("logging update thread::pthread_mutex_lock() failed, %d", ret);
+                       break;
+               }
+               logging_update(false);
+               ret = pthread_mutex_unlock(&logging_update_mutex);
+               if (ret) {
+                       _E("logging update thread::pthread_mutex_unlock() failed, %d", ret);
+                       break;
+               }
+       }
+       /* Now our thread finishes - cleanup TID */
+       logging_update_thread = 0;
+       return NULL;
+ }
+ static Eina_Bool logging_send_signal_to_update(void *data)
+ {
+       int ret;
+       DIR *dir_info;
+       dir_info = opendir(LOGGING_FILE_PATH);
+       if (dir_info)
+               closedir(dir_info);
+       else {
+               _E("There is no %s", LOGGING_FILE_PATH);
+               ret = mkdir(LOGGING_FILE_PATH, S_IRWXU | S_IRWXG | S_IROTH);
+               if (ret) {
+                       _E("mkdir failed %s", LOGGING_FILE_PATH);
+                       return ECORE_CALLBACK_RENEW;
+               }
+       }
+       _D("logging timer callback function start");
+       /* signal to logging update thread for start update */
+       ret = pthread_mutex_trylock(&logging_update_mutex);
+       if (ret)
+               _E("pthread_mutex_trylock fail : %d, errno : %d", ret, errno);
+       else {
+               pthread_cond_signal(&logging_update_cond);
+               _I("send signal to logging update thread");
+               pthread_mutex_unlock(&logging_update_mutex);
+       }
+       return ECORE_CALLBACK_RENEW;
+ }
+ static int logging_thread_create(void)
+ {
+       int ret = RESOURCED_ERROR_NONE;
+       /* initialize logging_data_thread */
+       if (logging_data_thread) {
+               _I("logging data thread %u already created", (unsigned)logging_data_thread);
+       } else {
+               ret = pthread_create(&logging_data_thread, NULL,
+                                                       (void *)logging_data_thread_main, (void *)NULL);
+               if (ret) {
+                       _E("pthread creation for logging_data_thread_main failed, %d\n", ret);
+                       logging_data_thread = 0;
+               } else {
+                       _D("pthread creation for logging data success");
+                       pthread_detach(logging_data_thread);
+               }
+       }
+       /* initialize logging_update_thread */
+       if (logging_update_thread) {
+               _I("logging update thread %u already created", (unsigned)logging_update_thread);
+       } else {
+               ret = pthread_create(&logging_update_thread, NULL,
+                                                       (void *)logging_update_thread_main, (void *)NULL);
+               if (ret) {
+                       _E("pthread creation for logging_update_thread_main failed, %d\n", ret);
+                       logging_update_thread = 0;
+               } else {
+                       _D("pthread creation for logging update success");
+                       pthread_detach(logging_update_thread);
+               }
+       }
+       return ret;
+ }
+ static int logging_poweroff(void *data)
+ {
+       /* flush module cache */
+       logging_save_to_storage(true);
+       return RESOURCED_ERROR_NONE;
+ }
+ int logging_init(void *data)
+ {
+       int ret = RESOURCED_ERROR_NONE;
+       char *err = NULL;
+       _D("logging_init start");
+       ret = logging_thread_create();
+       if (ret) {
+               _E("logging thread create failed");
+               return RESOURCED_ERROR_FAIL;
+       }
+       /* module array create */
+       logging_modules = g_array_new(false, false, sizeof(struct logging_module *));
+       if (logging_modules == NULL) {
+               _E("logging_modules_array create failed");
+               return RESOURCED_ERROR_OUT_OF_MEMORY;
+       }
+       /* DB create */
+       if (sqlite3_open(LOGGING_DB_FILE_NAME, &logging_db) != SQLITE_OK) {
+               _E("%s DB open failed (%s)", LOGGING_DB_FILE_NAME, sqlite3_errmsg(logging_db));
+               return RESOURCED_ERROR_FAIL;
+       }
+       ret = sqlite3_exec(logging_db, "PRAGMA locking_mode = NORMAL", 0, 0, 0);
+       if (ret != SQLITE_OK) {
+               _E("Can't set locking mode %s", sqlite3_errmsg(logging_db));
+               _E("Skip set busy handler.");
+               return RESOURCED_ERROR_DB_FAILED;
+       }
+       /* Set how many times we'll repeat our attempts for sqlite_step */
+       if (sqlite3_busy_handler(logging_db, logging_db_busy, NULL) != SQLITE_OK) {
+               _E("Couldn't set busy handler!");
+       }
+       options = leveldb_options_create();
+       leveldb_options_set_create_if_missing(options, 1);
+       logging_leveldb = leveldb_open(options, LOGGING_LEVEL_DB_FILE_NAME, &err);
+       if (err != NULL) {
+               _E("Failed to open leveldb");
+               free(err);
+               return RESOURCED_ERROR_DB_FAILED;
+       }
+       roptions = leveldb_readoptions_create();
+       woptions = leveldb_writeoptions_create();
+       leveldb_writeoptions_set_sync(woptions, 1);
+       register_notifier(RESOURCED_NOTIFIER_LOGGING_START, logging_start);
+       register_notifier(RESOURCED_NOTIFIER_POWER_OFF, logging_poweroff);
+       if (logging_data_timer == NULL) {
+               _D("logging data timer start");
+               logging_data_timer =
+                       ecore_timer_add(ONE_MINUTE, logging_send_signal_to_data, (void *)NULL);
+       }
+       if (logging_update_timer == NULL) {
+               _D("logging data timer start");
+               logging_update_timer =
+                       ecore_timer_add(ONE_MINUTE, logging_send_signal_to_update, (void *)NULL);
+       }
+       return RESOURCED_ERROR_NONE;
+ }
+ int logging_exit(void *data)
+ {
+       int i;
+       struct logging_module *module;
+       /* update timer delete */
+       ecore_timer_del(logging_update_timer);
+       logging_update_timer = NULL;
+       unregister_notifier(RESOURCED_NOTIFIER_LOGGING_START, logging_start);
+       unregister_notifier(RESOURCED_NOTIFIER_POWER_OFF, logging_poweroff);
+       /* flush module cache */
+       logging_save_to_storage(true);
+       /* logging_modules array deinitialize */
+       for (i = 0; i < logging_modules->len; i++) {
+               module = g_array_index(logging_modules,
+                               struct logging_module *, i);
+               free(module->name);
+               free(module->db_path);
+               g_queue_free(module->cache);
+               /* DB close */
+               sqlite3_close(module->db);
+       }
+       g_array_free(logging_modules, true);
+       /* DB close */
+       sqlite3_close(logging_db);
+       if (logging_leveldb)
+               leveldb_close(logging_leveldb);
+       _D("logging_exit");
+       return RESOURCED_ERROR_NONE;
+ }
index 0000000,df37d75..0feb70f
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,141 +1,141 @@@
 -              fprintf(stdout, "Try to allocate memory %u", len);
+ /*
+    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.
+    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 <sys/mman.h>
+ #include <stdio.h>
+ #include <stdbool.h>
+ #include <string.h>
+ #include <errno.h>
+ #include <signal.h>
+ #include "util.h"
+ #include "config-parser.h"
+ #define MEM_STRESS_CONF "/etc/mem-stress.conf"
+ static bool quite = false;
+ static size_t arg_size = 0;
+ static int parse_config_file(void)
+ {
+       const ConfigTableItem items[] = {
+               { "MemStress",  "Size", config_parse_bytes,     0,      &arg_size       },
+               { NULL,         NULL,   NULL,                   0,      NULL            }
+       };
+       return config_parse_new(MEM_STRESS_CONF, (void*) items);
+ }
+ static void mem_stress_signal_handler(int signo)
+ {
+       if (signo == SIGTERM)
+               quite = true;
+ }
+ static int mem_stress_signal_init(void)
+ {
+       if (signal(SIGTERM, &mem_stress_signal_handler) == SIG_ERR) {
+               fprintf(stdout, "Failed to catch SIGTERM signal: %m");
+               return -errno;
+       }
+       return 0;
+ }
+ static int mem_stress_allocate_memory(void **addr, size_t len)
+ {
+       void *p = NULL;
+       int r;
+       do {
 -      fprintf(stdout, "Memory stress size is: %u", arg_size);
++              fprintf(stdout, "Try to allocate memory %zu", len);
+               p = new0(void, len);
+       } while(!p);
+       r = mlock(p, len);
+       if (r < 0) {
+               free(p);
+               return r;
+       }
+       *addr = p;
+       return 0;
+ }
+ static int mem_stress_free_memory(void *addr, size_t len)
+ {
+       int r;
+       r = munlock(addr, len);
+       if (r < 0)
+               return r;
+       free(addr);
+       return 0;
+ }
+ static int mem_stress_run_loop(void)
+ {
+       void *mem = NULL;
+       int r;
+       char buf[256];
++      fprintf(stdout, "Memory stress size is: %zu", arg_size);
+       if (!arg_size)
+               return 0;
+       r = mem_stress_allocate_memory(&mem, arg_size);
+       if (r < 0) {
+               fprintf(stderr, "Failed to allocate memory: %s", strerror_r(-r, buf, sizeof(buf)));
+               return r;
+       }
+       while(!quite)
+               sleep(10);
+       r = mem_stress_free_memory(mem, arg_size);
+       if (r < 0) {
+               fprintf(stderr, "Failed to free memory: %s", strerror_r(-r, buf, sizeof(buf)));
+               return r;
+       }
+       return 0;
+ }
+ int main(int argc, char *argv[])
+ {
+       int r;
+       r = access(MEM_STRESS_CONF, F_OK);
+       if (r < 0) {
+               fprintf(stderr, "Failed to access '%s': %m", MEM_STRESS_CONF);
+               return EXIT_FAILURE;
+       }
+       r = mem_stress_signal_init();
+       if (r < 0)
+               return EXIT_FAILURE;
+       r = parse_config_file();
+       if (r < 0)
+               return EXIT_FAILURE;
+       r = mem_stress_run_loop();
+       if (r < 0)
+               return EXIT_FAILURE;
+       return EXIT_SUCCESS;
+ }
@@@ -225,12 -232,19 +232,19 @@@ static pthread_cond_t   oom_cond        = PTHREA
  
  static unsigned long totalram;
  static unsigned long ktotalram;
 -static const struct module_ops memory_modules_ops;
 -static const struct module_ops *lowmem_ops;
+ static int fg_killed;
++static struct module_ops memory_modules_ops;
++static struct module_ops *lowmem_ops;
+ static bool oom_popup_enable;
+ static bool oom_popup;
  
- static const struct module_ops memory_modules_ops;
- static const struct module_ops *lowmem_ops;
- static char *memcg_name[MEMCG_MAX] = {
+ static const char *memcg_name[MEMCG_MAX] = {
        NULL,
+       "platform",
        "foreground",
+       "previous",
+       "favorite",
        "background",
        "swap",
  };
@@@ -2004,8 -2224,8 +2224,8 @@@ int lowmem_get_memcg(enum memcg_type ty
        return RESOURCED_ERROR_NONE;
  }
  
--static const struct module_ops memory_modules_ops = {
-       .priority       = MODULE_PRIORITY_NORMAL,
++static struct module_ops memory_modules_ops = {
+       .priority       = MODULE_PRIORITY_EARLY,
        .name           = "lowmem",
        .init           = resourced_memory_init,
        .exit           = resourced_memory_finalize,
@@@ -1,3 -1,6 +1,5 @@@
 -SET(CMAKE_INSTALL_PREFIX /usr)
+ PROJECT(memps)
  SET(PREFIX ${CMAKE_INSTALL_PREFIX})
  
  SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
@@@ -17,7 -19,8 +18,8 @@@ IF("${NETWORK_MODULE}" STREQUAL "OFF"
                        CLEAN_DIRECT_OUTPUT 1
        )
  
 -      INSTALL(TARGETS ${PROJECT} DESTINATION lib)
+       INSTALL(FILES ${INCLUDE_PUBLIC_DIR}/data_usage.h DESTINATION include/system)
 +      INSTALL(TARGETS ${PROJECT} DESTINATION ${LIB_INSTALL_DIR})
  
        RETURN()
  ENDIF()
@@@ -1467,7 -1903,7 +1903,7 @@@ resourced_ret_c join_net_cls(const cha
        return RESOURCED_ERROR_NONE;
  }
  
--static const struct module_ops datausage_modules_ops = {
++static struct module_ops datausage_modules_ops = {
        .priority = MODULE_PRIORITY_NORMAL,
        .name = "datausage",
        .init = resourced_datausage_init,
Simple merge
index 0000000,c2d5aa6..5d7b9c8
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,195 +1,198 @@@
 -      return (gboolean)strstr((char *)user_data, (char *)key);
+ /*
+  * 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 proc-appusage.c
+  * @desc check history (application frequency and application execution time) based application usage
+ */
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <glib.h>
+ #include <Ecore.h>
+ #include "resourced.h"
+ #include "logging.h"
+ #include "trace.h"
+ #include "module.h"
+ #include "macro.h"
+ #include "proc-main.h"
+ #include "notifier.h"
+ #include "config-parser.h"
+ #ifdef HEART_SUPPORT
+ #include "heart-common.h"
+ #endif
+ #define UPDATE_INTERVAL       DAY_TO_SEC(1)
+ #define APPUSAGE_CONF_FILE      "/etc/resourced/proc.conf"
+ #define APPUSAGE_CONF_SECTION "APPUSAGE"
+ static int favorite_count;
+ static GHashTable *appusage_favorite_htab;
+ #ifdef HEART_SUPPORT
+ static Ecore_Timer *appusage_update_timer;
+ #endif
+ static void free_key(gpointer data)
+ {
+       if (data)
+               free(data);
+ }
+ static gboolean find_hash(gpointer key, gpointer value, gpointer user_data)
+ {
++      if (!user_data || !key)
++              return FALSE;
++
++      return (strstr((char *)user_data, (char *)key) ? TRUE: FALSE);
+ }
+ static void print_favorite_list(gpointer key, gpointer value, gpointer user_data)
+ {
+       _D("favorit app list : %s", (char*)key);
+ }
+ #ifdef HEART_SUPPORT
+ static Eina_Bool appusage_update_cb(void *data)
+ {
+       GHashTable *apps_htab = (GHashTable *)data;
+       int ret;
+       if (!data)
+               return ECORE_CALLBACK_CANCEL;
+       ret = heart_cpu_get_appusage_list(apps_htab, favorite_count);
+       if (!ret) {
+               _I("most_recently_used_list updated");
+               g_hash_table_foreach(apps_htab, print_favorite_list, NULL);
+       }
+       return ECORE_CALLBACK_RENEW;
+ }
+ #endif
+ static int load_appusage_config(struct parse_result *result, void *user_data)
+ {
+       if(!result)
+               return -EINVAL;
+       if (strcmp(result->section, APPUSAGE_CONF_SECTION))
+               return RESOURCED_ERROR_NO_DATA;
+       if (!strcmp(result->name, "APPUSAGE")) {
+               if (!strcmp(result->value, "OFF"))
+                       return RESOURCED_ERROR_UNINITIALIZED;
+               appusage_favorite_htab = g_hash_table_new_full(g_str_hash,
+                               g_str_equal, free_key, NULL);
+       } else if (!strcmp(result->name, "PREDEFINE")) {
+               g_hash_table_insert(appusage_favorite_htab,
+                               g_strndup(result->value, strlen(result->value)), GINT_TO_POINTER(1));
+       }
+       return RESOURCED_ERROR_NONE;
+ }
+ static int proc_appusage_table_init(void)
+ {
+       int ret;
+       ret = config_parse(APPUSAGE_CONF_FILE, load_appusage_config, NULL);
+       if(ret || !appusage_favorite_htab)
+               return RESOURCED_ERROR_NO_DATA;
+       favorite_count = g_hash_table_size(appusage_favorite_htab);
+ #ifdef HEART_SUPPORT
+       ret = heart_cpu_get_appusage_list(appusage_favorite_htab,
+                       favorite_count);
+       if (!ret)
+               _I("most_recently_used_list updated");
+ #endif
+       g_hash_table_foreach(appusage_favorite_htab, print_favorite_list, NULL);
+       return RESOURCED_ERROR_NONE;
+ }
+ static int booting_done(void *data)
+ {
+       static const struct module_ops *swap;
+       int ret;
+       /*
+        * When kernel enables swap feature,
+        * resourced can control favorite applications because it will
+        * apply early swap and late oom kill.
+        */
+       if (!swap) {
+               swap = find_module("swap");
+               if (!swap)
+                       return RESOURCED_ERROR_NO_DATA;
+       }
+       ret = proc_appusage_table_init();
+       if (ret)
+               return RESOURCED_ERROR_NO_DATA;
+ #ifdef HEART_SUPPORT
+       appusage_update_timer = ecore_timer_add(UPDATE_INTERVAL,
+                       appusage_update_cb, (void *)appusage_favorite_htab);
+ #endif
+       return RESOURCED_ERROR_NONE;
+ }
+ bool proc_check_favorite_app(char *appid)
+ {
+       gpointer app_ptr = NULL;
+       if (!appusage_favorite_htab)
+               return false;
+       app_ptr = g_hash_table_find(appusage_favorite_htab,
+                           find_hash, (gpointer)appid);
+       if (app_ptr)
+               return true;
+       return false;
+ }
+ static int proc_appusage_init(void *data)
+ {
+       register_notifier(RESOURCED_NOTIFIER_BOOTING_DONE, booting_done);
+       return RESOURCED_ERROR_NONE;
+ }
+ static int proc_appusage_exit(void *data)
+ {
+       if (appusage_favorite_htab)
+               g_hash_table_destroy(appusage_favorite_htab);
+       unregister_notifier(RESOURCED_NOTIFIER_BOOTING_DONE, booting_done);
+       return RESOURCED_ERROR_NONE;
+ }
+ static const struct proc_module_ops proc_appusage_ops = {
+       .name           = "PROC_APPUSAGE",
+       .init           = proc_appusage_init,
+       .exit           = proc_appusage_exit,
+ };
+ PROC_MODULE_REGISTER(&proc_appusage_ops)
index 0000000,527641d..01526e3
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,202 +1,203 @@@
 -      int server_fd, client_fd, client_len;
+ /*
+  * 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 proc_info.c
+  * @desc It's main thread to get system & process information
+  *       to provide runtime api
+ */
+ #include <stdio.h>
+ #include <limits.h>
+ #include <unistd.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <sys/un.h>
+ #include <sys/stat.h>
+ #include <sys/stat.h>
+ #include <sys/xattr.h>
+ #include <pthread.h>
+ #include <Ecore.h>
+ #include "macro.h"
+ #include "proc-main.h"
+ #include "proc-info.h"
+ #include "proc-process.h"
+ #include "proc-noti.h"
+ #include "resourced.h"
+ #include "module.h"
+ #include "trace.h"
+ #define MAX_CONNECTION 5
+ static pthread_t proc_info_thread;
+ static void *resourced_proc_info_func(void *data)
+ {
+       struct sockaddr_un client_address;
+       struct resourced_noti *msg;
+       char *send_buffer = NULL;
+       int ret, send_len = 0;
 -      server_fd = (int)data;
++      long server_fd, client_fd, client_len;
+       pid_t pid;
+       struct timeval tv = { 1, 0 };   /* 1 sec */
+       if (!data) {
+               _E("data is NULL");
+               return NULL;
+       }
 -      int fd, ret;
++      server_fd = (long)data;
+       client_len = sizeof(client_address);
+       if (listen(server_fd, MAX_CONNECTION) < 0) {
+               _E("Failed to listen socket");
+               close(server_fd);
+               return NULL;
+       }
+       while (1) {
+               client_fd =
+                       accept(server_fd, (struct sockaddr *)&client_address,
+                                       (socklen_t *)&client_len);
+               if (client_fd < 0) {
+                       _E("Failed to accept");
+                       continue;
+               }
+               msg = calloc(1, sizeof(struct resourced_noti));
+               if (msg == NULL) {
+                       _E("proc_noti_cb : Not enough memory");
+                       goto end;
+               }
+               ret = setsockopt(client_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
+               if (ret)
+                       _E("failed to set socket option");
+               ret = read_message(client_fd, msg);
+               if (ret)
+                       goto end;
+               if (msg->argc > NOTI_MAXARG || msg->type < PROC_CGROUP_GET_CMDLINE) {
+                       _E("%s : error argument", __func__);
+                       goto end;
+               }
+               pid = atoi(msg->argv[0]);
+               send_len = atoi(msg->argv[1]);
+               send_buffer = calloc(1, send_len);
+               if (send_buffer == NULL) {
+                       _E("Not enough memory");
+                       goto end;
+               }
+               ret = proc_get_state(msg->type, pid, send_buffer, send_len);
+ end:
+               write_response(&ret, client_fd, send_buffer, send_len);
+               free_message(msg);
+               close(client_fd);
+               if (send_buffer) {
+                       free(send_buffer);
+                       send_buffer = NULL;
+               }
+               ret = 0;
+               send_len = 0;
+       }
+       return NULL;
+ }
+ static int proc_info_socket_init(void)
+ {
+       int fd;
+       struct sockaddr_un serveraddr;
+       if (access(RESOURCED_PROC_INFO_SOCKET_PATH, F_OK) == 0)
+               unlink(RESOURCED_PROC_INFO_SOCKET_PATH);
+       fd = socket(AF_UNIX, SOCK_STREAM, 0);
+       if (fd < 0) {
+               _E("Failed to create socket");
+               return -1;
+       }
+       if ((fsetxattr(fd, "security.SMACK64IPOUT", "@", 2, 0)) < 0) {
+               _E("Failed to set Socket SMACK label");
+               if (errno != EOPNOTSUPP) {
+                       close(fd);
+                       return -1;
+               }
+       }
+       if ((fsetxattr(fd, "security.SMACK64IPIN", "*", 2, 0)) < 0) {
+               _E("Failed to set Socket SMACK label");
+               if (errno != EOPNOTSUPP) {
+                       close(fd);
+                       return -1;
+               }
+       }
+       bzero(&serveraddr, sizeof(struct sockaddr_un));
+       serveraddr.sun_family = AF_UNIX;
+       strncpy(serveraddr.sun_path, RESOURCED_PROC_INFO_SOCKET_PATH,
+                       sizeof(serveraddr.sun_path));
+       if (bind(fd, (struct sockaddr *)&serveraddr, sizeof(struct sockaddr)) < 0) {
+               _E("Failed to bind socket");
+               close(fd);
+               return -1;
+       }
+       if (chmod(RESOURCED_PROC_INFO_SOCKET_PATH, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0)
+               _E("Failed to change the socket permission");
+       _D("socket create ok");
+       return fd;
+ }
+ static int proc_info_init(void *data)
+ {
++      int ret;
++      long fd;
+       fd = proc_info_socket_init();
+       if (fd < 0) {
+               _E("Failed to init socket");
+               return -1;
+       }
+       /* start thread */
+       ret = pthread_create(&proc_info_thread, NULL, resourced_proc_info_func,
+                       (void *)fd);
+       if (ret != 0) {
+               _E("Failed to create thread");
+               return RESOURCED_ERROR_FAIL;
+       }
+       return RESOURCED_ERROR_NONE;
+ }
+ static int proc_info_exit(void *data)
+ {
+       _D("proc info exit!");
+       return RESOURCED_ERROR_NONE;
+ }
+ static const struct proc_module_ops proc_info_ops = {
+       .name           = "PROC_INFO",
+       .init           = proc_info_init,
+       .exit           = proc_info_exit,
+ };
+ PROC_MODULE_REGISTER(&proc_info_ops)
@@@ -428,10 -485,30 +485,33 @@@ static void proc_free_exclude_key(gpoin
  
  static gboolean find_excluded(gpointer key, gpointer value, gpointer user_data)
  {
-       if(!user_data || !key)
 -      return (gboolean)strstr((char *)user_data, (char *)key);
++      if (!user_data || !key)
 +              return FALSE;
 +
-       return (strstr((char*)user_data, (char*)key) ? TRUE : FALSE);
++      return (strstr((char *)user_data, (char *)key) ? TRUE : FALSE);
+ }
+ int proc_get_id_info(struct proc_status *ps, char **app_name, char **pkg_name)
+ {
+       if (!ps)
+               return RESOURCED_ERROR_INVALID_PARAMETER;
+       if (!ps->pai || !ps->pai->ai) {
+               *app_name = TIZEN_SYSTEM_APPID;
+               *pkg_name = TIZEN_SYSTEM_APPID;
+       } else {
+               *app_name = ps->pai->ai->appid;
+               *pkg_name = ps->pai->ai->pkgname;
+       }
+       return RESOURCED_ERROR_NONE;
+ }
+ char *proc_get_appid_from_pid(const pid_t pid)
+ {
+       struct proc_app_info *pai = find_app_info(pid);
+       if (!pai)
+               return NULL;
+       return pai->appid;
  }
  
  int resourced_proc_excluded(const char *app_name)
@@@ -737,7 -1128,14 +1131,14 @@@ void resourced_proc_dump(int mode, cons
                f = fopen(buf, "w+");
        }
        proc_dump_process_list(f);
-       modules_dump((void*)f, mode);
-       if (f)
-               fclose(f);
+       modules_dump((void *)f, mode);
  }
 -static const struct module_ops proc_modules_ops = {
++static struct module_ops proc_modules_ops = {
+       .priority       = MODULE_PRIORITY_EARLY,
+       .name           = "PROC",
+       .init           = resourced_proc_init,
+       .exit           = resourced_proc_exit,
+ };
+ MODULE_REGISTER(&proc_modules_ops)
index 0000000,7eb837d..45342d2
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,669 +1,669 @@@
 -static const struct module_ops resourced_dbus_modules_ops = {
+ /*
+  * 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.
+  *
+ */
+ #include <assert.h>
+ #include <dbus/dbus.h>
+ #include <glib.h>
+ #include <E_DBus.h>
+ #include "edbus-handler.h"
+ #include "macro.h"
+ #include "util.h"
+ #include "module.h"
+ #include "resourced.h"
+ #include "trace.h"
+ #include "resourced-dbus.h"
+ /* key  : DBus system BusName */
+ /* value: PID of Busname */
+ /* BusName hash is 1:1 table */
+ static GHashTable *dbus_system_busname_hash = NULL;
+ /* key  : PID */
+ /* value: Another GHashTable of BusNames */
+ /* BusName hash is 1:N table */
+ static GHashTable *dbus_system_pid_hash = NULL;
+ E_DBus_Signal_Handler *dbus_name_owner_changed_handler = NULL;
+ static void ghash_free(void *hash)
+ {
+       if (g_hash_table_size((GHashTable *)hash))
+               g_hash_table_remove_all((GHashTable *)hash);
+       g_hash_table_unref((GHashTable *)hash);
+ }
+ bool resourced_dbus_pid_has_busname(pid_t pid)
+ {
+       return g_hash_table_contains(dbus_system_pid_hash, GUINT_TO_POINTER(pid));
+ }
+ unsigned int resourced_dbus_pid_get_busnames(pid_t pid, char ***busnames)
+ {
+       void *pid_p = GUINT_TO_POINTER(pid);
+       GHashTable *busname_hash = NULL;
+       char **names = NULL;
+       unsigned int len = 0;
+       assert(busnames);
+       busname_hash = g_hash_table_lookup(dbus_system_pid_hash, pid_p);
+       if (!busname_hash)
+               return 0;
+ #if (GLIB_MAJOR_VERSION <= 2 && GLIB_MINOR_VERSION < 40)
+       {
+               GHashTableIter iter;
+               char *busname;
+               int i;
+               names = (char **)malloc(sizeof(char *) * (size_t)(g_hash_table_size(busname_hash) + 1));
+               if (!names)
+                       return 0;
+               g_hash_table_iter_init (&iter, busname_hash);
+               for (i = 0; g_hash_table_iter_next(&iter, (void **)&busname, NULL); i++)
+                       names[i] = strndup(busname, strlen(busname)+1);
+               names[i] = NULL;
+       }
+ #else
+       names = (char **)g_hash_table_get_keys_as_array(busname_hash, &len);
+ #endif
+       *busnames = names;
+       return len;
+ }
+ pid_t resourced_dbus_get_pid_of_busname(const char *busname)
+ {
+       return GPOINTER_TO_UINT(g_hash_table_lookup(dbus_system_busname_hash, busname));
+ }
+ static void resourced_dbus_system_bus_append_connection_info(void *key, void *value, void *data)
+ {
+       DBusMessageIter *iter = data, sub;
+       char *busname = key;
+       pid_t pid = GPOINTER_TO_UINT(value);
+       if (!dbus_message_iter_open_container(iter, DBUS_TYPE_DICT_ENTRY, NULL, &sub)) {
+               _E("Failed to open dictionary");
+               return;
+       }
+       if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &busname)) {
+               _E("Failed to append string: %s", busname);
+               dbus_message_iter_abandon_container(iter, &sub);
+               return;
+       }
+       if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT32, &pid)) {
+               _E("Failed to append uint32: %u", pid);
+               dbus_message_iter_abandon_container(iter, &sub);
+               return;
+       }
+       if (!dbus_message_iter_close_container(iter, &sub)) {
+               _E("Failed to close array");
+               return;
+       }
+ }
+ static DBusMessage *resourced_dbus_handle_get_system_bus_name_info(E_DBus_Object *obj, DBusMessage *msg)
+ {
+       DBusMessageIter iter, sub;
+       DBusMessage *reply;
+       reply = dbus_message_new_method_return(msg);
+       if (!reply) {
+               _E("Failed to create method reply");
+               return NULL;
+       }
+       dbus_message_iter_init_append(reply, &iter);
+       if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{su}", &sub)) {
+               _E("Failed to open string array");
+               return NULL;
+       }
+       g_hash_table_foreach(dbus_system_busname_hash,
+                            resourced_dbus_system_bus_append_connection_info,
+                            &sub);
+       if (!dbus_message_iter_close_container(&iter, &sub)) {
+               _E("Failed to close array");
+               return NULL;
+       }
+       return reply;
+ }
+ static void resourced_dbus_system_bus_append_busname_info(void *key, void *value, void *data)
+ {
+       if (!dbus_message_iter_append_basic((DBusMessageIter *)data, DBUS_TYPE_STRING, &key))
+               _E("Failed to append string: %s", (char *)key);
+ }
+ static DBusMessage *resourced_dbus_handle_get_system_bus_pid_info(E_DBus_Object *obj, DBusMessage *msg)
+ {
+       GHashTable *busname_hash = NULL;
+       DBusMessageIter iter, sub;
+       DBusMessage *reply = NULL;
+       DBusError error = DBUS_ERROR_INIT;
+       pid_t pid;
+       if (!dbus_message_get_args(msg, &error, DBUS_TYPE_UINT32, &pid, DBUS_TYPE_INVALID)) {
+               _E("Failed to get arguments from message: %s", error.message);
+               return NULL;
+       }
+       if (!g_hash_table_contains(dbus_system_pid_hash, GUINT_TO_POINTER(pid))) {
+               reply = dbus_message_new_error(msg,
+                                              DBUS_ERROR_INVALID_ARGS,
+                                              "Given PID has no system bus");
+               return reply;
+       }
+       reply = dbus_message_new_method_return(msg);
+       if (!reply) {
+               _E("Failed to create method reply");
+               return NULL;
+       }
+       busname_hash = g_hash_table_lookup(dbus_system_pid_hash, GUINT_TO_POINTER(pid));
+       if (!busname_hash) {
+               _E("Failed to find value of key(PID: %u)", pid);
+               return NULL;
+       }
+       dbus_message_iter_init_append(reply, &iter);
+       if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) {
+               _E("Failed to open string array");
+               dbus_message_unref (reply);
+               return NULL;
+       }
+       g_hash_table_foreach(busname_hash,
+                            resourced_dbus_system_bus_append_busname_info,
+                            &sub);
+       if (!dbus_message_iter_close_container(&iter, &sub)) {
+               _E("Failed to close array");
+               return NULL;
+       }
+       return reply;
+ }
+ static void resourced_dbus_system_bus_append_pid_info(void *key, void *value, void *data)
+ {
+       DBusMessageIter *iter = data, sub, ssub;
+       pid_t pid = GPOINTER_TO_UINT(key);
+       GHashTable *busname_hash = value;
+       if (!dbus_message_iter_open_container(iter, DBUS_TYPE_DICT_ENTRY, NULL, &sub)) {
+               _E("Failed to open dictionary");
+               return;
+       }
+       if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT32, &pid)) {
+               _E("Failed to append uint32: %u", pid);
+               return;
+       }
+       if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "s", &ssub)) {
+               _E("Failed to open string array");
+               return;
+       }
+       g_hash_table_foreach(busname_hash,
+                            resourced_dbus_system_bus_append_busname_info,
+                            &ssub);
+       if (!dbus_message_iter_close_container(&sub, &ssub)) {
+               _E("Failed to close array");
+               return;
+       }
+       if (!dbus_message_iter_close_container(iter, &sub)) {
+               _E("Failed to close array");
+               return;
+       }
+ }
+ static DBusMessage *resourced_dbus_handle_get_system_bus_pid_info_all(E_DBus_Object *obj, DBusMessage *msg)
+ {
+       DBusMessageIter iter, sub;
+       DBusMessage *reply;
+       reply = dbus_message_new_method_return(msg);
+       if (!reply) {
+               _E("Failed to create method reply");
+               return NULL;
+       }
+       dbus_message_iter_init_append(reply, &iter);
+       if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{uas}", &sub)) {
+               _E("Failed to open string array");
+               dbus_message_unref (reply);
+               return NULL;
+       }
+       g_hash_table_foreach(dbus_system_pid_hash,
+                            resourced_dbus_system_bus_append_pid_info,
+                            &sub);
+       if (!dbus_message_iter_close_container(&iter, &sub)) {
+               _E("Failed to close array");
+               return NULL;
+       }
+       return reply;
+ }
+ static struct edbus_method resourced_dbus_methods[] = {
+       { "GetSystemBusPIDInfo",        "u",    "as",
+         resourced_dbus_handle_get_system_bus_pid_info         },
+       { "GetSystemBusPIDInfoAll",     NULL,   "a{uas}",
+         resourced_dbus_handle_get_system_bus_pid_info_all     },
+       { "GetSystemBusNameInfo",       NULL,   "a{su}",
+         resourced_dbus_handle_get_system_bus_name_info        },
+       { NULL,                         NULL,   NULL,
+         NULL                                                  },
+ };
+ static void resourced_dbus_system_hash_insert_busname(char *busname, pid_t pid)
+ {
+       GHashTable *busname_hash = NULL;
+       void *pid_p = GUINT_TO_POINTER(pid);
+       g_hash_table_replace(dbus_system_busname_hash, busname, pid_p);
+       busname_hash = (GHashTable *)g_hash_table_lookup(dbus_system_pid_hash, pid_p);
+       if (!busname_hash) {
+               /* !! CAUTION !! */
+               /* We are using same busname pointer at two of hash
+                * table. So the free operation should be done at
+                * once. */
+               busname_hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
+               if (!busname_hash) {
+                       _E("Failed to create BusName hash table");
+                       return;
+               }
+               g_hash_table_replace(dbus_system_pid_hash, pid_p, busname_hash);
+       }
+       g_hash_table_replace(busname_hash, busname, NULL);
+ }
+ static void resourced_dbus_system_hash_drop_busname(char *busname)
+ {
+       GHashTable *busname_hash = NULL;
+       void *pid_p;
+       /* BusName hash */
+       if (!g_hash_table_contains(dbus_system_busname_hash, busname)) {
+               _E("Does not exist in busname hash: %s", busname);
+               return;
+       }
+       /* Lookup PID of BusName */
+       pid_p = g_hash_table_lookup(dbus_system_busname_hash, busname);
+       /* Drop PID hash */
+       if (!g_hash_table_contains(dbus_system_pid_hash, pid_p)) {
+               _E("Does not exist in PID hash: %s", busname);
+               return;
+       }
+       busname_hash = (GHashTable *)g_hash_table_lookup(dbus_system_pid_hash, pid_p);
+       if (!busname_hash) {
+               _E("Failed to find value of PID: %u", GPOINTER_TO_UINT(pid_p));
+               g_hash_table_remove(dbus_system_pid_hash, pid_p);
+               return;
+       }
+       g_hash_table_remove(busname_hash, busname);
+       if (!g_hash_table_size(busname_hash)) {
+               g_hash_table_unref(busname_hash);
+               if (!g_hash_table_remove(dbus_system_pid_hash, pid_p))
+                       _E("Failed to drop from PID hash table: %s", busname);
+       }
+       /* Drop BusName hash */
+       if (!g_hash_table_remove(dbus_system_busname_hash, busname))
+               _E("Failed to drop from busname hash table: %s", busname);
+ }
+ static void resourced_dbus_get_connection_unix_process_id_callback(void *data, DBusMessage *msg, DBusError *error)
+ {
+       DBusError err = DBUS_ERROR_INIT;
+       char *busname = data;
+       pid_t pid;
+       if (dbus_error_is_set(error)) {
+               free(busname);
+               return;
+       }
+       if (!dbus_message_get_args(msg, &err, DBUS_TYPE_UINT32, &pid, DBUS_TYPE_INVALID)) {
+               free(busname);
+               _E("Failed to get arguments from message: %s", err.message);
+               return;
+       }
+       resourced_dbus_system_hash_insert_busname(busname, pid);
+ }
+ static void resourced_dbus_get_connection_unix_process_id(char *busname)
+ {
+       E_DBus_Connection *conn = NULL;
+       DBusMessage *msg = NULL;
+       DBusPendingCall *pending = NULL;
+       conn = get_resourced_edbus_connection();
+       msg = dbus_message_new_method_call(DBUS_SERVICE_DBUS,
+                                          DBUS_PATH_DBUS,
+                                          DBUS_INTERFACE_DBUS,
+                                          "GetConnectionUnixProcessID");
+       if (!msg) {
+               _E("Failed to get new message");
+               return;
+       }
+       if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &busname, DBUS_TYPE_INVALID)) {
+               _E("Failed to append args");
+               dbus_message_unref(msg);
+               return;
+       }
+       pending = e_dbus_message_send(conn,
+                                     msg,
+                                     resourced_dbus_get_connection_unix_process_id_callback,
+                                     -1,
+                                     strndup(busname, strlen(busname)+1));
+       if (!pending) {
+               _E("Failed to send message");
+               dbus_message_unref(msg);
+               return;
+       }
+       dbus_message_unref(msg);
+       return;
+ }
+ static void resourced_dbus_get_list_names_callback(void *data, DBusMessage *msg, DBusError *error)
+ {
+       DBusMessageIter iter, sub;
+       char *busname = NULL;
+       if (dbus_error_is_set(error)) {
+               _E("Failed to get DBus list names: %s", error->message);
+               return;
+       }
+       if (!dbus_message_iter_init(msg, &iter)) {
+               _D("message has no arguments");
+               return;
+       }
+       dbus_message_iter_recurse(&iter, &sub);
+       do {
+               dbus_message_iter_get_basic(&sub, &busname);
+               resourced_dbus_get_connection_unix_process_id(busname);
+       } while(dbus_message_iter_next(&sub));
+ }
+ static bool resourced_dbus_get_list_names(void)
+ {
+       DBusMessage *msg = NULL;
+       DBusPendingCall *pending = NULL;
+       msg = dbus_message_new_method_call(DBUS_SERVICE_DBUS,
+                                          DBUS_PATH_DBUS,
+                                          DBUS_INTERFACE_DBUS,
+                                          "ListNames");
+       if (!msg) {
+               _E("Failed to get new message");
+               return FALSE;
+       }
+       pending = e_dbus_message_send(get_resourced_edbus_connection(),
+                                     msg,
+                                     resourced_dbus_get_list_names_callback,
+                                     -1,
+                                     NULL);
+       if (!pending) {
+               _E("Failed to send message");
+               dbus_message_unref(msg);
+               return FALSE;
+       }
+       dbus_message_unref(msg);
+       return TRUE;
+ }
+ static bool resourced_dbus_become_monitor(DBusConnection *connection,
+                                         const char * const *filters)
+ {
+       DBusError error = DBUS_ERROR_INIT;
+       DBusMessage *msg;
+       DBusMessage *reply;
+       int i;
+       unsigned int zero = 0;
+       DBusMessageIter iter, sub;
+       msg = dbus_message_new_method_call(DBUS_SERVICE_DBUS,
+                                          DBUS_PATH_DBUS,
+                                          DBUS_INTERFACE_MONITORING,
+                                          "BecomeMonitor");
+       if (!msg) {
+               _E("Failed to become a monitor");
+               return FALSE;
+       }
+       dbus_message_iter_init_append(msg, &iter);
+       if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) {
+               _E("Failed to open string array");
+               return FALSE;
+       }
+       for (i = 0; filters[i] != NULL; i++) {
+               if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &filters[i])) {
+                       _E("Failed to add filter to array");
+                       return FALSE;
+               }
+       }
+       if (!dbus_message_iter_close_container(&iter, &sub)) {
+               _E("Failed to close array");
+               return FALSE;
+       }
+       if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT32, &zero)) {
+               _E("Failed to append finish argument zero");
+               return FALSE;
+       }
+       reply = dbus_connection_send_with_reply_and_block(connection, msg, -1, &error);
+       if (!reply) {
+               _E("Failed to enable new-style monitoring: "
+                  "%s: \"%s\". Falling back to eavesdropping.",
+                  error.name, error.message);
+               dbus_error_free(&error);
+               return FALSE;
+       }
+       dbus_message_unref(msg);
+       dbus_message_unref(reply);
+       return (reply != NULL);
+ }
+ E_DBus_Connection *resourced_dbus_monitor_new(DBusBusType type,
+                                             DBusHandleMessageFunction filter_func,
+                                             const char * const *filters)
+ {
+       E_DBus_Connection *edbus_conn = NULL;
+       DBusConnection *conn = NULL;
+       DBusError error = DBUS_ERROR_INIT;
+       conn = dbus_bus_get_private(type, &error);
+       if (!conn) {
+               _E("Failed to open connecion: %s", error.message);
+               goto on_error;
+       }
+       if (!dbus_connection_add_filter(conn,
+                                       filter_func,
+                                       NULL,
+                                       NULL)) {
+               _E("Failed to add filter function on connection");
+               goto on_error;
+       }
+       if (!resourced_dbus_become_monitor(conn, filters)) {
+               _E("Failed to become a monitor connection");
+               goto on_error;
+       }
+       edbus_conn = e_dbus_connection_setup(conn);
+       if (!edbus_conn) {
+               _E("Failed to setup edbus connection");
+               goto on_error;
+       }
+       return edbus_conn;
+ on_error:
+       if (dbus_error_is_set(&error))
+           dbus_error_free(&error);
+       if (conn) {
+               dbus_connection_close(conn);
+               dbus_connection_unref(conn);
+       }
+       return NULL;
+ }
+ static void resourced_dbus_name_owner_changed_callback(void *data, DBusMessage *msg)
+ {
+       char *busname = NULL, *from = NULL, *to = NULL;
+       DBusError error = DBUS_ERROR_INIT;
+       if (!dbus_message_get_args(msg, &error,
+                                  DBUS_TYPE_STRING, &busname,
+                                  DBUS_TYPE_STRING, &from,
+                                  DBUS_TYPE_STRING, &to,
+                                  DBUS_TYPE_INVALID)) {
+               _E("Failed to get arguments from message: %s", error.message);
+               return;
+       }
+         /* If the name owner process is activated then: */
+         /* arg_0: busname */
+         /* arg_1: "" */
+         /* arg_2: ":x.xxx" */
+         /* If the name owner process is deactivated then: */
+         /* arg_0: busname */
+         /* arg_1: ":x.xxx" */
+         /* arg_2: "" */
+       if (is_empty(busname)) {
+               _E("NameOwnerChanged: arg_0 is empty");
+               return;
+       }
+       if (is_empty(from) && is_empty(to)) {
+               _E("NameOwnerChanged: both arg_1 and arg_2 are empty");
+               return;
+       }
+       if (is_empty(from) && !is_empty(to)) {
+               /* New BusName */
+               resourced_dbus_get_connection_unix_process_id(busname);
+               return;
+       } else if (!is_empty(from) && is_empty(to)) {
+               /* Drop BusName */
+               resourced_dbus_system_hash_drop_busname(busname);
+               return;
+       }
+       _E("Should NOT reached here!!");
+ }
+ static int resourced_dbus_init(void *data)
+ {
+       resourced_ret_c ret;
+       dbus_system_busname_hash = g_hash_table_new_full(g_str_hash, g_str_equal, free, NULL);
+       if (!dbus_system_busname_hash)
+               _E("Failed to create dbus connection list hash table");
+       dbus_system_pid_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, ghash_free);
+       if (!dbus_system_pid_hash)
+               _E("Failed to create dbus connection list hash table");
+       resourced_dbus_get_list_names();
+       dbus_name_owner_changed_handler = e_dbus_signal_handler_add(get_resourced_edbus_connection(),
+                                                                   DBUS_SERVICE_DBUS,
+                                                                   DBUS_PATH_DBUS,
+                                                                   DBUS_INTERFACE_DBUS,
+                                                                   "NameOwnerChanged",
+                                                                   resourced_dbus_name_owner_changed_callback,
+                                                                   NULL);
+       ret = edbus_add_methods(RESOURCED_PATH_DBUS,
+                               resourced_dbus_methods,
+                               ARRAY_SIZE(resourced_dbus_methods));
+       ret_value_msg_if(ret != RESOURCED_ERROR_NONE, ret,
+                        "DBus method registration for %s is failed", RESOURCED_PATH_DBUS);
+       return RESOURCED_ERROR_NONE;
+ }
+ static int resourced_dbus_finalize(void *data)
+ {
+       ghash_free(dbus_system_busname_hash);
+       ghash_free(dbus_system_pid_hash);
+       return RESOURCED_ERROR_NONE;
+ }
++static struct module_ops resourced_dbus_modules_ops = {
+       .priority = MODULE_PRIORITY_NORMAL,
+       .name = "resourced-dbus",
+       .init = resourced_dbus_init,
+       .exit = resourced_dbus_finalize,
+ };
+ MODULE_REGISTER(&resourced_dbus_modules_ops)
index 0000000,809af1b..bc64e2f
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,14 +1,13 @@@
 -EnvironmentFile=/run/tizen-mobile-env
+ [Unit]
+ Description=Resource management daemon
+ After=wm_ready.service
+ [Service]
+ Type=notify
+ ExecStart=/usr/bin/resourced
+ MemoryLimit=30M
+ Restart=on-failure
+ RestartSec=0
+ [Install]
+ WantedBy=multi-user.target
index 0000000,030ae5b..c0d3db1
mode 000000,100755..100755
--- /dev/null
@@@ -1,0 -1,547 +1,547 @@@
 -static void sluggish_launch_popup(int type)
+ /*
+  * 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 sluggish.c
+  * @desc Sluggishness processing functions
+  *
+  **/
+ #include <glib.h>
+ #include <fcntl.h>
+ #include <sys/stat.h>
+ #include <sys/types.h>
+ #include <unistd.h>
+ #include <stdlib.h>
+ #include "edbus-handler.h"
+ #include "trace.h"
+ #include "module.h"
+ #include "macro.h"
+ #include "time-helper.h"
+ #include "proc-cpu.h"
+ #include "storage-helper.h"
+ #include "file-helper.h"
+ #include "util.h"
+ #define SLUGGISH_PATH "/opt/usr/share/sluggish"       /* Path to dump system snapshot */
+ #define PATH_DLOG     "/opt/var/log/dlog_main"        /* Platform log file */
+ #define PATH_DLOG1    "/opt/var/log/dlog_main.1"      /* Platform log file */
+ #define MAX_TIMESTAMP_LEN     30
+ #define MAX_FILENAME_LEN      256
+ #define MAX_BUF_LEN   1024
+ #define POPUP_KEY_CONTENT     "_SYSPOPUP_CONTENT_"
+ #define SLUGGISH_POPUP        "sluggish_popup"
+ #define SLUGGISH_TYPE "_DETECTION_TYPE_"
+ #define MEMINFO_FILE_PATH     "/proc/meminfo" /* meminfo file path */
+ #define VMSTAT_FILE_PATH      "/proc/vmstat"  /* vmstat file path */
+ #define SLUGGISH_DUP_NOTI_TIMELIMIT   5       /* duplicate sluggish notification timelimit */
+ #define KILOBYTE      1024
+ #define POPUP_DELAY_TIME      15      /* Unit: seconds */
+ #define CPU_THRESHOLD 80      /* Delay popup if CPU usage percentage crossed this limit */
+ #define GET_BATTERY_CAPACITY  "GetPercent"
+ static int sluggish_count;    /* sluggish notification count*/
+ enum sluggish_event {
+       GRAPHICS = 1,   /* Graphics vertical */
+       MULTIMEDIA      /* Multimedia vertical */
+ };
+ typedef void (*sluggish_stat_func)(char *ts);
+ struct sluggish_stat {
+       char *type;
+       sluggish_stat_func func;
+ };
 -      sluggish_launch_popup((int )user_data);
++static void sluggish_launch_popup(long type)
+ {
+       char *param[4];
+       int ret;
+       /* Launch sluggish system popup */
+       param[0] = POPUP_KEY_CONTENT;
+       param[1] = SLUGGISH_POPUP;
+       param[2] = SLUGGISH_TYPE;
+       if (type == GRAPHICS)
+               param[3] = "Graphics sluggishenss";
+       else if (type == MULTIMEDIA)
+               param[3] = "Multimedia sluggishens";
+       else {
+               _E("Invalid sluggish type :%d", type);
+               return;
+       }
+       ret = dbus_method_async("org.tizen.system.popup",
+           "/Org/Tizen/System/Popup/System",
+           "org.tizen.system.popup.System",
+           "SluggishPopupLaunch", "ssss", param);
+       if (ret < 0)
+               _E("Failed to launch SluggishPopup");
+       else
+               _I("SluggishPopupLaunch Success");
+ }
+ static gboolean sluggish_popup_cb(gpointer user_data)
+ {
 -static void sluggish_get_sys_status(char *timestamp, int slug_vertical, int pid)
++      sluggish_launch_popup((long)user_data);
+       return FALSE;
+ }
+ static void sluggish_get_vmstat(char *timestamp)
+ {
+       char file_name[MAX_FILENAME_LEN];
+       int ret;
+       snprintf(file_name, sizeof(file_name), "%s/%s/vmstat", SLUGGISH_PATH, timestamp);
+       /* dump /proc/vmstat to SLUGGISH_PATH */
+       ret = copy_file(file_name, VMSTAT_FILE_PATH);
+       if (ret < 0)
+               _E("Copy: %s to %s FAILED", VMSTAT_FILE_PATH, file_name);
+       else
+               _I("Copy: %s to %s SUCCESS", VMSTAT_FILE_PATH, file_name);
+ }
+ static void sluggish_get_memps(char *timestamp)
+ {
+       char file_name[MAX_FILENAME_LEN];
+       int ret;
+       char *argv[3];
+       snprintf(file_name, sizeof(file_name), "%s/%s/memps", SLUGGISH_PATH, timestamp);
+       argv[0] = "memps";
+       argv[1] = "-a";
+       argv[2] = NULL;
+       /* dump memps output to SLUGGISH_PATH */
+       ret = exec_cmd(argv, file_name);
+       if (ret < 0)
+               _E("Cmd: memps -a Failed");
+       else
+               _I("Cmd: memps -a  Success");
+ }
+ static void sluggish_get_meminfo(char *timestamp)
+ {
+       char file_name[MAX_FILENAME_LEN];
+       int ret;
+       snprintf(file_name, sizeof(file_name), "%s/%s/meminfo", SLUGGISH_PATH, timestamp);
+       /* dump /proc/meminfo to SLUGGISH_PATH */
+       ret = copy_file(file_name, MEMINFO_FILE_PATH);
+       if (ret < 0)
+               _E("Copy: %s to %s FAILED", MEMINFO_FILE_PATH, file_name);
+       else
+               _I("Copy: %s to %s SUCCESS", MEMINFO_FILE_PATH, file_name);
+ }
+ static void sluggish_get_psinfo(char *timestamp)
+ {
+       char file_name[MAX_FILENAME_LEN];
+       int ret;
+       char *argv[4];
+       snprintf(file_name, sizeof(file_name), "%s/%s/ps-eo", SLUGGISH_PATH, timestamp);
+       argv[0] = "ps";
+       argv[1] = "-eo";
+       argv[2] = "pid,uname,ppid,pri,ni,vsize,rss,pcpu,pmem,size,time,s,policy,cmd";
+       argv[3] = NULL;
+       /* dump ps -eo output to SLUGGISH_PATH */
+       ret = exec_cmd(argv, file_name);
+       if (ret < 0)
+               _E("Cmd: ps -eo Failed");
+       else
+               _I("Cmd: ps -eo Success");
+ }
+ static const struct sluggish_stat sluggish_memstat[] = {
+       { "vmstat", sluggish_get_vmstat },
+       { "memps", sluggish_get_memps },
+       { "meminfo", sluggish_get_meminfo },
+ };
+ static void sluggish_get_mem_status(char *timestamp)
+ {
+       /* Get memory status using vmstat, meminfo, memps and dump to SLUGGISH_PATH */
+       int i;
+       for (i = 0; i < ARRAY_SIZE(sluggish_memstat); i++) {
+               sluggish_memstat[i].func(timestamp);
+       }
+ }
+ static void sluggish_get_dlog(char *timestamp)
+ {
+       char file_name[MAX_FILENAME_LEN];
+       char file_name1[MAX_FILENAME_LEN];
+       int ret;
+       /* Dump platform log files to SLUGGISH_PATH */
+       if (!access(PATH_DLOG, F_OK)) {
+               snprintf(file_name, sizeof(file_name), "%s/%s/dlog_main", SLUGGISH_PATH, timestamp);
+               ret = copy_file(file_name, PATH_DLOG);
+               if (ret < 0)
+                       _E("Copy: %s to %s FAILED", PATH_DLOG, file_name);
+               else
+                       _I("Copy: %s to %s SUCCESS", PATH_DLOG, file_name);
+       }
+       if (!access(PATH_DLOG1, F_OK)) {
+               snprintf(file_name1, sizeof(file_name1), "%s/%s/dlog_main.1", SLUGGISH_PATH, timestamp);
+               ret = copy_file(file_name1, PATH_DLOG1);
+               if (ret < 0)
+                       _E("Copy: %s to %s FAILED", PATH_DLOG1, file_name1);
+               else
+                       _I("Copy: %s to %s SUCCESS", PATH_DLOG1, file_name1);
+       }
+ }
+ static int sluggish_get_battery_status(void)
+ {
+       int capacity, ret;
+       DBusMessage *msg;
+       /* Get battery status from deviced */
+       msg = dbus_method_sync(DEVICED_BUS_NAME, DEVICED_PATH_BATTERY,
+                       DEVICED_INTERFACE_BATTERY,
+                       GET_BATTERY_CAPACITY,
+                       NULL, NULL);
+       if (!msg) {
+               _E("Failed to sync DBUS message.");
+               return RESOURCED_ERROR_FAIL;
+       }
+       ret = dbus_message_get_args(msg, NULL, DBUS_TYPE_INT32, &capacity, DBUS_TYPE_INVALID);
+       dbus_message_unref(msg);
+       if (!ret) {
+               _E("Failed: dbus_message_get_args()");
+               return RESOURCED_ERROR_FAIL;
+       }
+       return capacity;
+ }
+ static void sluggish_get_summary(char *timestamp, int slug_vertical, int pid, double cpu_usage)
+ {
+       char file_name[MAX_FILENAME_LEN];
+       char buf[MAX_BUF_LEN] = "";
+       char batbuf[MAX_BUF_LEN] = "";
+       char proc[MAX_FILENAME_LEN];
+       struct statvfs s;
+       double int_tot = 0;
+       double int_free = 0;
+       double ext_tot = 0;
+       double ext_free = 0;
+       FILE *fptr = NULL;
+       FILE *fp = NULL;
+       int batteryp;
+       size_t size;
+       /*
+       * Dump
+       * 1. Storage status
+       * 2. Battery status
+       * 3. Sluggishness type
+       * 4. Sluggish PID/Process
+       * 5. CPU Usage
+       */
+       /* Get internal memory status */
+       memset(&s, 0x00, sizeof(struct statvfs));
+       if (storage_get_size(INTERNAL, &s) < 0 ) {
+               _E("Fail to get internal memory size");
+       } else {
+               int_tot = ((double)s.f_frsize * s.f_blocks) / KILOBYTE;
+               int_free = ((double)s.f_bsize * s.f_bavail) / KILOBYTE;
+               _I("Internal Memory Status:Total : %lfKB, Avail : %lfKB", int_tot, int_free);
+       }
+       /* Get external memory status */
+       memset(&s, 0x00, sizeof(struct statvfs));
+       if (storage_get_size(EXTERNAL, &s) < 0 ) {
+               _E("Fail to get external memory size");
+       } else {
+               ext_tot = ((double)s.f_frsize * s.f_blocks) / KILOBYTE;
+               ext_free = ((double)s.f_bsize * s.f_bavail) / KILOBYTE;
+               _I("External Memory Status:Total : %lfKB, Avail : %lfKB", ext_tot, ext_free);
+       }
+       snprintf(file_name, sizeof(file_name), "%s/%s/summary", SLUGGISH_PATH, timestamp);
+       if (ext_tot > 0) {
+               snprintf(buf, sizeof(buf), "Internal Memory Status:\nTotal : %lfKB, Avail : %lfKB\nExternal Memory Status:\nTotal : %lfKB, Avail : %lfKB\n",
+                   int_tot, int_free, ext_tot, ext_free);
+       } else
+               snprintf(buf, sizeof(buf), "Internal Memory Status:\nTotal : %lfKB, Avail : %lfKB\n", int_tot, int_free);
+       /* Get Battery status */
+       batteryp = sluggish_get_battery_status();
+       if (batteryp >= 0)
+               snprintf(batbuf, sizeof(batbuf), "Battery percentage:%d%%\n", batteryp);
+       /* Open file in SLUGGISH_PATH to dump summary */
+       fptr = fopen(file_name, "w+");
+       if (fptr == NULL) {
+               _E("Failed to open file %s", file_name);
+               return;
+       }
+       /* 1. Write storage status */
+       fputs(buf, fptr);
+       /* 2. Write battery status */
+       if (batteryp >= 0)
+               fputs(batbuf, fptr);
+       /* 3. Write sluggishness type */
+       if (slug_vertical == GRAPHICS)
+               fputs("Sluggishness type: GRAPHICS\n", fptr);
+       else if (slug_vertical == MULTIMEDIA)
+               fputs("Sluggishness type: MULTIMEDIA\n", fptr);
+       /* 4. Write sluggish PID and process name */
+       fprintf(fptr,"Sluggish PID:%d\n", pid);
+       /* Get process name */
+       snprintf(proc, sizeof(proc), "/proc/%d/cmdline", pid);
+       fp = fopen(proc, "rb");
+       if (fp) {
+               memset(buf, 0x00, sizeof(buf));
+               size = fread(buf, 1, MAX_BUF_LEN, fp);
+               if (size > 0) {
+                       fputs("Sluggish Process: ", fptr);
+                       fputs(buf, fptr);
+                       fputs("\n", fptr);
+               }
+               fclose(fp);
+       }
+       /* 5. Write CPU usage */
+       fprintf(fptr,"CPU used:%3.2lf%%, idle:%3.2lf%%\n", cpu_usage, (100 - cpu_usage));
+       fclose(fptr);
+ }
 -static const struct module_ops sluggish_ops = {
++static void sluggish_get_sys_status(char *timestamp, long slug_vertical, int pid)
+ {
+       char dir_name[MAX_FILENAME_LEN];
+       double cu;
+       struct cpu_stat cs1;
+       struct cpu_stat cs2;
+       /* Get first cpu stat reading */
+       memset(&cs1, 0x00, sizeof(struct cpu_stat));
+       memset(&cs2, 0x00, sizeof(struct cpu_stat));
+       proc_cpu_stat(&cs1);
+       /* Get current timestamp */
+       time_stamp(timestamp);
+       /*
+       * Create dir to store the system snapshot
+       * All the data captured on sluggish detection notification will be
+       * stored in this directory for uploading later
+       */
+       /* Note : Data is captured only on receiving "SluggishDetected" signal */
+       snprintf(dir_name, sizeof(dir_name), "%s/%s", SLUGGISH_PATH, timestamp);
+       if (mkdir(dir_name, S_IRUSR | S_IWUSR | S_IRGRP) < 0) {
+               if (errno != EEXIST) {
+                       _E("Failed to create dir %s", dir_name);
+                       return;
+               }
+       }
+       _I("Created %s successfully", dir_name);
+       /* Get process Status */
+       sluggish_get_psinfo(timestamp);
+       /* Get Memory Status */
+       sluggish_get_mem_status(timestamp);
+       /* Get dlog */
+       sluggish_get_dlog(timestamp);
+       /* Get second cpu stat reading */
+       proc_cpu_stat(&cs2);
+       /* Get CPU usage % */
+       cu = proc_cpu_usage(&cs1, &cs2);
+       /* Get storage, battaery, cpu status */
+       sluggish_get_summary(timestamp, slug_vertical, pid, cu);
+       /* If current CPU utilization is > threshold (CPU_THRESHOLD) delay popup display */
+       if ((unsigned int)cu > CPU_THRESHOLD) {
+               _I("CPU used(%d%%) > %d%% - Delaying popup display ", (unsigned int)cu, CPU_THRESHOLD);
+               g_timeout_add_seconds(POPUP_DELAY_TIME, sluggish_popup_cb, (void *)slug_vertical);
+               return;
+       }
+       sluggish_launch_popup(slug_vertical);
+ }
+ static void sluggish_graphics(pid_t pid)
+ {
+       char timestamp[MAX_TIMESTAMP_LEN];
+       struct timeval timeval;
+       struct timeval interval;
+       static pid_t sluggish_graphics_last_pid;        /* PID of last graphics sluggishness */
+       static struct timeval sluggish_graphics_last_ts;        /* Timestamp of last graphics sluggishness */
+       /* Process graphics sluggishness */
+       _I("Graphics sluggishness for PID (%d), Count:%d", pid, ++sluggish_count);
+       if (gettimeofday(&timeval, NULL)) {
+               _E("gettimeofday() failed");
+               return;
+       }
+       if (pid == sluggish_graphics_last_pid) {
+               time_diff(&interval, &sluggish_graphics_last_ts, &timeval);
+               _D("Current ts-sec:%ld usec:%ld", timeval.tv_sec, timeval.tv_usec);
+               _D("Last ts-sec:%ld usec:%ld", sluggish_graphics_last_ts.tv_sec, sluggish_graphics_last_ts.tv_usec);
+               _D("Diff-%ld sec, %ld usec\n", interval.tv_sec, interval.tv_usec);
+               /*
+               *If Duplicate(Same PID, Same sluggish type)
+               * "SluggisgDetected" notification is received
+               * within SLUGGISH_DUP_NOTI_TIMELIMIT ignore it
+               */
+               if (interval.tv_sec <= SLUGGISH_DUP_NOTI_TIMELIMIT) {
+                       _I("Ignoring update for same PID:%d within timelimit(%ds)", pid, SLUGGISH_DUP_NOTI_TIMELIMIT);
+                       return;
+               }
+       }
+       sluggish_graphics_last_pid = pid;
+       sluggish_graphics_last_ts.tv_sec = timeval.tv_sec;
+       sluggish_graphics_last_ts.tv_usec = timeval.tv_usec;
+       /* Get system snapshot and dump to SLUGGISH_PATH */
+       sluggish_get_sys_status(timestamp, GRAPHICS, pid);
+ }
+ static void sluggish_multimedia(pid_t pid)
+ {
+       char timestamp[MAX_TIMESTAMP_LEN];
+       struct timeval timeval;
+       struct timeval interval;
+       static pid_t sluggish_media_last_pid;   /* PID of last multimedia sluggishness */
+       static struct timeval sluggish_media_last_ts;   /* Timestamp of last graphics sluggishness */
+       /* Process multimedia sluggishness */
+       _I("Multimedia sluggishness for PID (%d), Count:%d", pid, ++sluggish_count);
+       if (gettimeofday(&timeval, NULL)) {
+               _E("gettimeofday() failed");
+               return;
+       }
+       if (pid == sluggish_media_last_pid) {
+               time_diff(&interval, &sluggish_media_last_ts, &timeval);
+               _D("Current ts-sec:%ld usec:%ld", timeval.tv_sec, timeval.tv_usec);
+               _D("Last ts-sec:%ld usec:%ld", sluggish_media_last_ts.tv_sec, sluggish_media_last_ts.tv_usec);
+               _D("Diff-%ld sec, %ld usec\n", interval.tv_sec, interval.tv_usec);
+               /*
+               * If Duplicate(Same PID, Same sluggish type)
+               * "SluggisgDetected" notification is received
+               * within SLUGGISH_DUP_NOTI_TIMELIMIT ignore it
+               */
+               if (interval.tv_sec <= SLUGGISH_DUP_NOTI_TIMELIMIT) {
+                       _I("Ignoring update for same PID:%d within timelimit(%ds)", pid, SLUGGISH_DUP_NOTI_TIMELIMIT);
+                       return;
+               }
+       }
+       sluggish_media_last_pid = pid;
+       sluggish_media_last_ts.tv_sec = timeval.tv_sec;
+       sluggish_media_last_ts.tv_usec = timeval.tv_usec;
+       /* Get system snapshot and dump to SLUGGISH_PATH */
+       sluggish_get_sys_status(timestamp, MULTIMEDIA, pid);
+ }
+ static void sluggish_process(enum sluggish_event event, pid_t pid)
+ {
+       switch (event) {
+       case GRAPHICS:
+               sluggish_graphics(pid);
+               break;
+       case MULTIMEDIA:
+               sluggish_multimedia(pid);
+               break;
+       default:
+               break;
+       };
+ }
+ static DBusMessage *edbus_sluggish_detected(E_DBus_Object *obj, DBusMessage *msg)
+ {
+       DBusMessage *reply;
+       dbus_bool_t ret;
+       DBusError err;
+       pid_t pid = 0;
+       int slug_vertical = 0;
+       dbus_error_init(&err);
+       ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &slug_vertical,
+           DBUS_TYPE_INT32, &pid, DBUS_TYPE_INVALID);
+       if (ret == FALSE) {
+               _E("Can't deserialize sluggish detection message ![%s:%s]\n",
+               err.name, err.message);
+               goto error;
+       }
+       dbus_error_free(&err);
+       if (slug_vertical != GRAPHICS && slug_vertical != MULTIMEDIA) {
+               _E("Invalid sluggish vertical:%d", slug_vertical);
+               goto error;
+       }
+       /* Received "SluggishDetected" message, so get system details and dump to SLUGGISH_PATH */
+       sluggish_process(slug_vertical, pid);
+ error:
+       reply = dbus_message_new_method_return(msg);
+       return reply;
+ }
+ static const struct edbus_method edbus_methods[] = {
+       { "SluggishDetected", NULL, "ii", edbus_sluggish_detected },
+       /* Add methods here */
+ };
+ static int sluggish_init(void *data)
+ {
+       resourced_ret_c ret;
+       /* Create SLUGGISH_PATH folder to dump system snapshot*/
+       if (mkdir(SLUGGISH_PATH, S_IRUSR | S_IWUSR | S_IRGRP) < 0) {
+               if (errno != EEXIST) {
+                       _E("Failed to create dir %s", SLUGGISH_PATH);
+                       return RESOURCED_ERROR_FAIL;
+               }
+       }
+       _I("Created %s successfully", SLUGGISH_PATH);
+       ret = edbus_add_methods(RESOURCED_PATH_SLUGGISH, edbus_methods,
+               ARRAY_SIZE(edbus_methods));
+       if (ret != RESOURCED_ERROR_NONE) {
+               _E("DBus method registration for %s is failed", RESOURCED_PATH_SLUGGISH);
+               return ret;
+       }
+       return RESOURCED_ERROR_NONE;
+ }
++static struct module_ops sluggish_ops = {
+       .priority       = MODULE_PRIORITY_NORMAL,
+       .name           = "sluggish",
+       .init           = sluggish_init,
+ };
+ MODULE_REGISTER(&sluggish_ops)
diff --cc src/swap/swap.c
  #define BtoMB(x)                      ((x) >> 20)
  #define BtoPAGE(x)                    ((x) >> 12)
  
- #define SWAP_TIMER_INTERVAL           0.5
  #define SWAP_PRIORITY                 20
  #define SWAP_SORT_MAX                 10
- #define SWAP_COUNT_MAX                                5
+ #define MAX_PIDS                      3
+ #define SWAP_RATIO                    0.5
+ #define SWAP_FULLNESS_RATIO           0.8
+ #define SWAP_FORCE_RECLAIM_NUM_MAX    5
+ #define SWAP_RECLIAM_PAGES_MAX                2560
+ #define SWAP_RECLIAM_PAGES_MIN                128
+ enum swap_thread_op {
+       SWAP_OP_ACTIVATE,
+       SWAP_OP_RECLAIM,
+       SWAP_OP_COMPACT,
+       SWAP_OP_END,
+ };
  
- struct task_info {
-       pid_t pid;
-       pid_t pgid;
-       int oom_score_adj;
+ struct swap_task {
+       struct proc_app_info *pai;
        int size;
-       int cgroup_cnt;
  };
  
- static int swapon;
- static float hard_limit_fraction = SWAP_HARD_LIMIT_DEFAULT;
+ struct swap_zram_control {
+       int max_comp_streams;
+       char comp_algorithm[5];
+       float ratio;
+       unsigned long swap_size_bytes;
+       unsigned long swap_almost_full_bytes;
+ };
+ struct swap_safe_queue {
+       GQueue *queue;
+       pthread_mutex_t lock;
+ };
+ struct swap_thread_bundle {
+       struct swap_status_msg msg;
+       enum swap_thread_op op;
+ };
+ static struct swap_zram_control swap_control = {
+       .max_comp_streams = -1,
+       .comp_algorithm = "lzo",
+       .ratio = SWAP_RATIO,
+       .swap_size_bytes = 0,
+       .swap_almost_full_bytes = 0,
+ };
  static pthread_mutex_t swap_mutex;
  static pthread_cond_t swap_cond;
- static Ecore_Timer *swap_timer = NULL;
+ static struct swap_safe_queue swap_thread_queue;
 -static const struct module_ops swap_modules_ops;
++static struct module_ops swap_modules_ops;
++static char *swap_thread_op_names[SWAP_OP_END] = {
++      "ACTIVATE",
++      "RECLAIM",
++      "COMPACT",
++};
  
- static const struct module_ops swap_modules_ops;
- static const struct module_ops *swap_ops;
+ static int swap_compact_handler(void *data);
+ static const char *compact_reason_to_str(enum swap_compact_reason reason)
+ {
+       static const char *reasons_table[] = {"lowmem: low", "lowmem: medium",
+                       "swap: zram full"};
+       if (reason >= SWAP_COMPACT_LOWMEM_LOW && reason < SWAP_COMPACT_RESASON_MAX)
+               return reasons_table[reason];
+       return "";
+ }
  
static int swap_get_swap_type(void)
enum swap_state swap_get_state(void)
  {
        struct shared_modules_data *modules_data = get_shared_modules_data();
  
@@@ -486,86 -557,203 +562,207 @@@ static int swap_mkswap(void
        return pid;
  }
  
- static Eina_Bool swap_send_signal(void *data)
+ static int swap_zram_activate(void)
  {
        int ret;
+       unsigned int swap_size_bytes;
  
-       _D("swap timer callback function start");
+       ret = fwrite_int(SWAP_ZRAM_MAX_COMP_STREAMS, swap_control.max_comp_streams);
+       if (ret < 0) {
+               _E("fail to write max_comp_streams");
+               return ret;
+       }
  
-       if(!swapon)
-               swap_on();
+       ret = fwrite_str(SWAP_ZRAM_COMP_ALGORITHM, swap_control.comp_algorithm);
+       if (ret < 0) {
+               _E("fail to write comp_algrithm");
+               return ret;
+       }
  
-       /* signal to swap_start to start swap */
-       ret = pthread_mutex_trylock(&swap_mutex);
+       swap_control.swap_size_bytes = swap_size();
+       swap_control.swap_almost_full_bytes = swap_control.swap_size_bytes * SWAP_FULLNESS_RATIO;
+       ret = fwrite_uint(SWAP_ZRAM_DISK_SIZE, swap_control.swap_size_bytes);
+       if (ret < 0) {
+               _E("fail to write disk_size");
+               return ret;
+       }
  
-       if (ret)
-               _E("pthread_mutex_trylock fail : %d, errno : %d", ret, errno);
-       else {
-               pthread_cond_signal(&swap_cond);
-               _I("send signal to swap thread");
-               pthread_mutex_unlock(&swap_mutex);
+       ret = fread_uint(SWAP_ZRAM_DISK_SIZE, &swap_size_bytes);
+       if (ret < 0) {
+               _E("fail to read zram disk_size");
+               return ret;
        }
  
-       _D("swap timer delete");
+       /* Check if zram was sucessfully initialized (zcomp rollback case) */
+       if (swap_size_bytes < swap_control.swap_size_bytes)
+               return RESOURCED_ERROR_OOM;
  
-       ecore_timer_del(swap_timer);
-       swap_timer = NULL;
+       ret = swap_mkswap();
+       if (ret < 0) {
+               _E("swap mkswap failed, fork error = %d", ret);
+               return RESOURCED_ERROR_FAIL;
+       }
  
-       return ECORE_CALLBACK_CANCEL;
+       return RESOURCED_ERROR_NONE;
  }
  
- static int swap_start(void *data)
+ static void swap_activate_in_module(void)
  {
-       if (swap_timer == NULL) {
-               _D("swap timer start");
-               swap_timer =
-                       ecore_timer_add(SWAP_TIMER_INTERVAL, swap_send_signal, (void *)NULL);
+       int disksize;
+       if (swap_get_state() == SWAP_ON)
+               return;
+       
+       disksize = swap_get_disksize_bytes();
+       if (disksize <= 0) {
+               if (swap_zram_activate() < 0) {
+                       _E("swap cannot be activated");
+                       return;
+               }
        }
+       swap_change_state(SWAP_ON);
+       _D("swap activated");
+ }
  
-       return RESOURCED_ERROR_NONE;
+ static void *swap_thread_main(void * data)
+ {
+       int is_empty;
+       struct swap_thread_bundle *bundle;
+       setpriority(PRIO_PROCESS, 0, SWAP_PRIORITY);
+       while (1) {
+               pthread_mutex_lock(&swap_mutex);
+               /* THREAD: WAIT FOR START */
+               pthread_mutex_lock(&swap_thread_queue.lock);
+               is_empty = g_queue_is_empty(swap_thread_queue.queue);
+               pthread_mutex_unlock(&swap_thread_queue.lock);
+               if (is_empty) {
+                       /* The queue is empty, wait for thread signal */
+                       pthread_cond_wait(&swap_cond, &swap_mutex);
+               }
+               /* We're in swap thread, now it's time to dispatch bundles */
+               pthread_mutex_lock(&swap_thread_queue.lock);
+               bundle = g_queue_pop_head(swap_thread_queue.queue);
+               pthread_mutex_unlock(&swap_thread_queue.lock);
+               if (!bundle)
+                       goto unlock_out;
+               switch (bundle->op) {
+               /* Swap activation operttion: mkswap, swapon etc. */
+               case SWAP_OP_ACTIVATE:
+                       swap_activate_in_module();
+                       break;
+               /* Swap reclaim opertation: move to swap, force_reclaim */
+               case SWAP_OP_RECLAIM:
+                       swap_reclaim_memcg(bundle->msg);
+                       break;
+               /* Swap compact operation of zsmalloc. */
+               case SWAP_OP_COMPACT:
+                       swap_compact_zram();
+                       break;
+               case SWAP_OP_END:
+               default:
+                       _D("wrong swap thread operation selected");
+               }
+               free(bundle);
+ unlock_out:
+               pthread_mutex_unlock(&swap_mutex);
+       }
+       return NULL;
  }
  
- static int swap_thread_create(void)
+ static int swap_start_handler(void *data)
  {
-       int ret = RESOURCED_ERROR_NONE;
-       pthread_t pth;
+       int ret;
+       struct swap_thread_bundle *bundle;
  
-       pthread_mutex_init(&swap_mutex, NULL);
-       pthread_cond_init(&swap_cond, NULL);
+       if (!data)
+               return RESOURCED_ERROR_NO_DATA;
  
-       ret = pthread_create(&pth, NULL, &swap_thread_main, (void*)NULL);
-       if (ret) {
-               _E("pthread creation for swap_thread failed\n");
-               return ret;
+       bundle = malloc(sizeof(struct swap_thread_bundle));
+       if (!bundle)
+               return RESOURCED_ERROR_OUT_OF_MEMORY;
+       bundle->op = SWAP_OP_RECLAIM;
+       memcpy(&(bundle->msg), data, sizeof(struct swap_status_msg));
+       if (bundle->msg.type == MEMCG_BACKGROUND) {
+               ret = swap_move_background_to_swap(&(bundle->msg));
+               /* add bundle only if some processes were moved into swap memcg */
+               if (ret) {
+                       free(bundle);
+                       return RESOURCED_ERROR_NO_DATA;
+               }
+       }
+       swap_add_bundle(bundle);
+       /* Try to signal swap thread, that there is some work to do */
+       ret = pthread_mutex_trylock(&swap_mutex);
+       if (ret == 0) {
+               pthread_cond_signal(&swap_cond);
+               pthread_mutex_unlock(&swap_mutex);
+               _I("send signal to swap thread");
+               return RESOURCED_ERROR_NONE;
+       }
+       if (ret && ret == EBUSY) {
+               _D("swap thread already active");
        } else {
-               pthread_detach(pth);
+               _E("pthread_mutex_trylock fail : %d, errno : %d", ret, errno);
+               return RESOURCED_ERROR_FAIL;
        }
  
-       return ret;
+       return RESOURCED_ERROR_NONE;
  }
  
int swap_check_swap_pid(int pid)
static int swap_simple_bundle_sender(enum swap_thread_op operation)
  {
-       char buf[SWAP_PATH_MAX] = {0,};
-       int swappid;
-       int ret = 0;
-       FILE *f;
+       int ret;
+       struct swap_thread_bundle *bundle;
  
-       f = fopen(SWAPCG_PROCS, "r");
-       if (!f) {
-               _E("%s open failed", SWAPCG_PROCS);
-               return RESOURCED_ERROR_FAIL;
+       bundle = malloc(sizeof(struct swap_thread_bundle));
+       if (!bundle)
+               return RESOURCED_ERROR_OUT_OF_MEMORY;
+       bundle->op = operation;
+       swap_add_bundle(bundle);
++      if (operation >= 0 && operation < SWAP_OP_END)
++              _D("added %s operation to swap queue",
++                              swap_thread_op_names[operation]);
++
+       /* Try to signal swap thread, that there is some work to do */
+       ret = pthread_mutex_trylock(&swap_mutex);
+       if (ret == 0) {
+               pthread_cond_signal(&swap_cond);
+               pthread_mutex_unlock(&swap_mutex);
+               _I("send signal to swap thread");
+               return RESOURCED_ERROR_NONE;
        }
  
-       while (fgets(buf, SWAP_PATH_MAX, f) != NULL) {
-               swappid = atoi(buf);
-               if (swappid == pid) {
-                       ret = swappid;
-                       break;
-               }
+       if (ret && ret == EBUSY) {
+               _D("swap thread already active");
+       } else {
+               _E("pthread_mutex_trylock fail : %d, errno : %d", ret, errno);
+               return RESOURCED_ERROR_FAIL;
        }
-       fclose(f);
-       return ret;
+       return RESOURCED_ERROR_NONE;
+ }
+ static int swap_activate_handler(void *data)
+ {
+       return swap_simple_bundle_sender(SWAP_OP_ACTIVATE);
+ }
+ static int swap_compact_handler(void *data)
+ {
+       _I("compaction request. Reason: %s",
+                       compact_reason_to_str((enum swap_compact_reason)data));
+       return swap_simple_bundle_sender(SWAP_OP_COMPACT);
  }
  
  static void swap_start_pid_edbus_signal_handler(void *data, DBusMessage *msg)
@@@ -753,7 -1034,7 +1043,7 @@@ static int resourced_swap_finalize(voi
        return RESOURCED_ERROR_NONE;
  }
  
--static const struct module_ops swap_modules_ops = {
++static struct module_ops swap_modules_ops = {
        .priority = MODULE_PRIORITY_NORMAL,
        .name = "swap",
        .init = resourced_swap_init,
@@@ -264,7 -266,7 +266,7 @@@ static int resourced_timer_slack_finali
        return RESOURCED_ERROR_NONE;
  }
  
--static const struct module_ops timer_modules_ops = {
++static struct module_ops timer_modules_ops = {
        .priority = MODULE_PRIORITY_NORMAL,
        .name = TIMER_MODULE_NAME,
        .init = resourced_timer_slack_init,