barbieri pushed a commit to branch master.
commit c0c5736a4e0d41adc9c97577006c289718c926de
Author: Gustavo Sverzut Barbieri <[email protected]>
Date: Thu Aug 8 20:32:53 2013 -0300
ecore: add system modules, implement 'systemd'.
Ecore will now load "system modules" on ecore_init(). The "systemd"
module will use DBus to monitor localed, hostnamed and timedated and
add system events related to those changes.
---
configure.ac | 2 +
data/Makefile.am | 6 +
data/ecore/checkme | 1 +
pc/ecore.pc.in | 2 +
src/Makefile_Ecore.am | 32 +-
src/lib/ecore/ecore.c | 90 ++++++
.../ecore/system/systemd/ecore_system_systemd.c | 354 +++++++++++++++++++++
7 files changed, 486 insertions(+), 1 deletion(-)
diff --git a/configure.ac b/configure.ac
index 0d4f96b..1a01978 100644
--- a/configure.ac
+++ b/configure.ac
@@ -549,6 +549,8 @@ AC_ARG_ENABLE([systemd],
fi
],
[want_systemd="no"])
+AM_CONDITIONAL([WANT_SYSTEMD], [test "${want_systemd}" = "yes"])
+
#### Platform-dependent
DL_LIBS=""
diff --git a/data/Makefile.am b/data/Makefile.am
index e6926e5..5cd88de 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -22,6 +22,12 @@ eezefiles_DATA = eeze/checkme
EXTRA_DIST += $(eezefiles_DATA)
########################################################################
+# Ecore
+ecorefilesdir = $(datadir)/ecore
+ecorefiles_DATA = ecore/checkme
+EXTRA_DIST += $(ecorefiles_DATA)
+
+########################################################################
# Ecore_Imf
ecoreimffilesdir = $(datadir)/ecore_imf
ecoreimffiles_DATA = ecore_imf/checkme
diff --git a/data/ecore/checkme b/data/ecore/checkme
new file mode 100644
index 0000000..1688a66
--- /dev/null
+++ b/data/ecore/checkme
@@ -0,0 +1 @@
+This is just a test file used to help ecore determine its prefix location.
diff --git a/pc/ecore.pc.in b/pc/ecore.pc.in
index 2f0de2a..ab7004a 100644
--- a/pc/ecore.pc.in
+++ b/pc/ecore.pc.in
@@ -2,6 +2,8 @@ prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
+modules=@libdir@/ecore
+module_arch=@MODULE_ARCH@
Name: ecore
Description: Ecore event abstraction library
diff --git a/src/Makefile_Ecore.am b/src/Makefile_Ecore.am
index 40329a0..5e6515b 100644
--- a/src/Makefile_Ecore.am
+++ b/src/Makefile_Ecore.am
@@ -52,11 +52,41 @@ lib_ecore_libecore_la_SOURCES += lib/ecore/ecore_signal.c
lib/ecore/ecore_exe.c
endif
endif
-lib_ecore_libecore_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl @ECORE_CFLAGS@
+lib_ecore_libecore_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
+-DPACKAGE_BIN_DIR=\"$(bindir)\" \
+-DPACKAGE_LIB_DIR=\"$(libdir)\" \
+-DPACKAGE_DATA_DIR=\"$(datadir)/ecore\" \
+-DPACKAGE_BUILD_DIR=\"`pwd`/$(top_builddir)\" \
+@ECORE_CFLAGS@
lib_ecore_libecore_la_LIBADD = @ECORE_LIBS@
lib_ecore_libecore_la_DEPENDENCIES = @ECORE_INTERNAL_LIBS@
lib_ecore_libecore_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
+
+### Modules
+
+# systemd
+
+if WANT_SYSTEMD
+ecoresystemdpkgdir = $(libdir)/ecore/system/systemd/$(MODULE_ARCH)
+ecoresystemdpkg_LTLIBRARIES = modules/ecore/system/systemd/module.la
+modules_ecore_system_systemd_module_la_SOURCES = \
+modules/ecore/system/systemd/ecore_system_systemd.c
+modules_ecore_system_systemd_module_la_CPPFLAGS = \
+-I$(top_builddir)/src/lib/efl \
+@ECORE_CFLAGS@ \
+@ELDBUS_CFLAGS@
+modules_ecore_system_systemd_module_la_LIBADD = \
+@USE_ECORE_LIBS@ \
+@USE_ELDBUS_LIBS@
+modules_ecore_system_systemd_module_la_DEPENDENCIES = \
+@USE_ECORE_INTERNAL_LIBS@ \
+@USE_ELDBUS_INTERNAL_LIBS@
+modules_ecore_system_systemd_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
+modules_ecore_system_systemd_module_la_LIBTOOLFLAGS = --tag=disable-static
+endif
+
+
### Unit tests
if EFL_ENABLE_TESTS
diff --git a/src/lib/ecore/ecore.c b/src/lib/ecore/ecore.c
index 28726a2..489dc60 100644
--- a/src/lib/ecore/ecore.c
+++ b/src/lib/ecore/ecore.c
@@ -116,6 +116,77 @@ int _ecore_main_lock_count;
# define CODESET "INVALID"
#endif
+static Eina_Prefix *_ecore_pfx = NULL;
+static Eina_Array *module_list = NULL;
+
+static void
+ecore_system_modules_load(void)
+{
+ char buf[PATH_MAX] = "";
+ char *path;
+
+ if (getenv("EFL_RUN_IN_TREE"))
+ {
+ struct stat st;
+ snprintf(buf, sizeof(buf), "%s/src/modules/ecore/system",
+ PACKAGE_BUILD_DIR);
+ if (stat(buf, &st) == 0)
+ {
+ const char *built_modules[] = {
+#ifdef HAVE_SYSTEMD
+ "systemd",
+#endif
+ NULL
+ };
+ const char **itr;
+ for (itr = built_modules; *itr != NULL; itr++)
+ {
+ snprintf(buf, sizeof(buf),
+ "%s/src/modules/ecore/system/%s/.libs",
+ PACKAGE_BUILD_DIR, *itr);
+ module_list = eina_module_list_get(module_list, buf,
+ EINA_FALSE, NULL, NULL);
+ }
+
+ if (module_list)
+ eina_module_list_load(module_list);
+ return;
+ }
+ }
+
+ path = eina_module_environment_path_get("ECORE_MODULES_DIR",
+ "/ecore/system");
+ if (path)
+ {
+ module_list = eina_module_arch_list_get(module_list, path,
MODULE_ARCH);
+ free(path);
+ }
+
+ path = eina_module_environment_path_get("HOME", "/.ecore/system");
+ if (path)
+ {
+ module_list = eina_module_arch_list_get(module_list, path,
MODULE_ARCH);
+ free(path);
+ }
+
+ snprintf(buf, sizeof(buf), "%s/ecore/system",
+ eina_prefix_lib_get(_ecore_pfx));
+ module_list = eina_module_arch_list_get(module_list, buf, MODULE_ARCH);
+
+ eina_module_list_load(module_list);
+}
+
+static void
+ecore_system_modules_unload(void)
+{
+ if (module_list)
+ {
+ eina_module_list_free(module_list);
+ eina_array_free(module_list);
+ module_list = NULL;
+ }
+}
+
/**
* @addtogroup Ecore_Init_Group
*
@@ -170,6 +241,16 @@ ecore_init(void)
goto shutdown_log_dom;
}
+ _ecore_pfx = eina_prefix_new(NULL, ecore_init,
+ "ECORE", "ecore", "checkme",
+ PACKAGE_BIN_DIR, PACKAGE_LIB_DIR,
+ PACKAGE_DATA_DIR, PACKAGE_DATA_DIR);
+ if (!_ecore_pfx)
+ {
+ ERR("Could not get ecore installation prefix");
+ goto shutdown_log_dom;
+ }
+
eo_init();
if (getenv("ECORE_FPS_DEBUG")) _ecore_fps_debug = 1;
@@ -230,6 +311,9 @@ ecore_init(void)
EINA_LOG_STATE_STOP,
EINA_LOG_STATE_INIT);
+
+ ecore_system_modules_load();
+
return _ecore_init_count;
shutdown_mempool:
@@ -273,6 +357,8 @@ ecore_shutdown(void)
if (--_ecore_init_count != 0)
goto unlock;
+ ecore_system_modules_unload();
+
eina_log_timing(_ecore_log_dom,
EINA_LOG_STATE_START,
EINA_LOG_STATE_SHUTDOWN);
@@ -345,6 +431,10 @@ ecore_shutdown(void)
ecore_mempool_shutdown();
eina_log_domain_unregister(_ecore_log_dom);
_ecore_log_dom = -1;
+
+ eina_prefix_free(_ecore_pfx);
+ _ecore_pfx = NULL;
+
eina_shutdown();
#ifdef HAVE_EVIL
evil_shutdown();
diff --git a/src/modules/ecore/system/systemd/ecore_system_systemd.c
b/src/modules/ecore/system/systemd/ecore_system_systemd.c
new file mode 100644
index 0000000..0943775
--- /dev/null
+++ b/src/modules/ecore/system/systemd/ecore_system_systemd.c
@@ -0,0 +1,354 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <Eldbus.h>
+#include <Ecore.h>
+#include <locale.h>
+
+static int _log_dom = -1;
+static Eldbus_Connection *_conn = NULL;
+
+static Eina_List *_objs = NULL;
+static Eina_List *_proxies = NULL;
+
+#ifdef CRITICAL
+#undef CRITICAL
+#endif
+#define CRITICAL(...) EINA_LOG_DOM_CRIT(_log_dom, __VA_ARGS__)
+
+#ifdef ERR
+#undef ERR
+#endif
+#define ERR(...) EINA_LOG_DOM_ERR(_log_dom, __VA_ARGS__)
+
+#ifdef WRN
+#undef WRN
+#endif
+#define WRN(...) EINA_LOG_DOM_WARN(_log_dom, __VA_ARGS__)
+
+#ifdef DBG
+#undef DBG
+#endif
+#define DBG(...) EINA_LOG_DOM_DBG(_log_dom, __VA_ARGS__)
+
+
+static void
+_props_changed_hostname(void *data EINA_UNUSED, const Eldbus_Message *msg)
+{
+ Eldbus_Message_Iter *changed, *entry, *invalidated;
+ const char *iface, *prop;
+
+ if (!eldbus_message_arguments_get(msg, "sa{sv}as",
+ &iface, &changed, &invalidated))
+ {
+ ERR("Error getting data from properties changed signal.");
+ return;
+ }
+
+ while (eldbus_message_iter_get_and_next(changed, 'e', &entry))
+ {
+ const void *key;
+ Eldbus_Message_Iter *var;
+ if (!eldbus_message_iter_arguments_get(entry, "sv", &key, &var))
+ continue;
+ if (strcmp(key, "Hostname") == 0)
+ goto changed_hostname;
+ }
+
+ while (eldbus_message_iter_get_and_next(invalidated, 's', &prop))
+ {
+ if (strcmp(prop, "Hostname") == 0)
+ goto changed_hostname;
+ }
+
+ return;
+
+ changed_hostname:
+ ecore_event_add(ECORE_EVENT_HOSTNAME_CHANGED, NULL, NULL, NULL);
+}
+
+static void
+_props_changed_timedate(void *data EINA_UNUSED, const Eldbus_Message *msg)
+{
+ Eldbus_Message_Iter *changed, *entry, *invalidated;
+ const char *iface, *prop;
+
+ if (!eldbus_message_arguments_get(msg, "sa{sv}as",
+ &iface, &changed, &invalidated))
+ {
+ ERR("Error getting data from properties changed signal.");
+ return;
+ }
+
+ while (eldbus_message_iter_get_and_next(changed, 'e', &entry))
+ {
+ const void *key;
+ Eldbus_Message_Iter *var;
+ if (!eldbus_message_iter_arguments_get(entry, "sv", &key, &var))
+ continue;
+ if (strcmp(key, "Timezone") == 0)
+ goto changed_timedate;
+ }
+
+ while (eldbus_message_iter_get_and_next(invalidated, 's', &prop))
+ {
+ if (strcmp(prop, "Timezone") == 0)
+ goto changed_timedate;
+ }
+
+ return;
+
+ changed_timedate:
+ ecore_event_add(ECORE_EVENT_SYSTEM_TIMEDATE_CHANGED, NULL, NULL, NULL);
+}
+
+struct locale_cat_desc {
+ int cat;
+ int namelen;
+ const char *name;
+};
+
+static const struct locale_cat_desc locale_cat_desc[] = {
+#define CAT(name) {name, sizeof(#name) - 1, #name}
+ CAT(LC_CTYPE),
+ CAT(LC_NUMERIC),
+ CAT(LC_TIME),
+ CAT(LC_COLLATE),
+ CAT(LC_MONETARY),
+ CAT(LC_MESSAGES),
+ CAT(LC_ALL),
+ CAT(LC_PAPER),
+ CAT(LC_NAME),
+ CAT(LC_ADDRESS),
+ CAT(LC_TELEPHONE),
+ CAT(LC_MEASUREMENT),
+ CAT(LC_IDENTIFICATION),
+#undef CAT
+ {-1, -1, NULL}
+};
+
+static int _locale_parse(const char *str, int *cat, const char **value)
+{
+ const struct locale_cat_desc *itr;
+ const char *p = strchr(str, '=');
+ int klen;
+
+ if (!p) goto end;
+
+ klen = p - str;
+ for (itr = locale_cat_desc; itr->name != NULL; itr++)
+ {
+ if ((klen == itr->namelen) && (memcmp(str, itr->name, klen) == 0))
+ {
+ *cat = itr->cat;
+ *value = str + itr->namelen + 1;
+ return itr - locale_cat_desc;
+ }
+ }
+
+ end:
+ *cat = -1;
+ *value = NULL;
+ return -1;
+}
+
+static void _locale_get(void *data EINA_UNUSED, const Eldbus_Message *msg,
+ Eldbus_Pending *pending EINA_UNUSED)
+{
+ Eldbus_Message_Iter *variant, *array;
+ const char *errname, *errmsg, *val;
+ Eina_Bool setlocs[EINA_C_ARRAY_LENGTH(locale_cat_desc)];
+ unsigned int i;
+
+ if (eldbus_message_error_get(msg, &errname, &errmsg))
+ {
+ ERR("Message error %s - %s", errname, errmsg);
+ goto end;
+ }
+ if (!eldbus_message_arguments_get(msg, "v", &variant))
+ {
+ ERR("Error getting arguments.");
+ goto end;
+ }
+
+ if (!eldbus_message_iter_get_and_next(variant, 'a', &array))
+ {
+ ERR("Error getting array.");
+ goto end;
+ }
+
+ memset(setlocs, 0, sizeof(setlocs));
+ while (eldbus_message_iter_get_and_next(array, 's', &val))
+ {
+ int cat, idx;
+ const char *value;
+ idx = _locale_parse(val, &cat, &value);
+ if (idx >= 0)
+ setlocs[idx] = EINA_TRUE;
+ setlocale(cat, value);
+ }
+
+ for (i = 0; i < EINA_C_ARRAY_LENGTH(locale_cat_desc); i++)
+ {
+ if ((!setlocs[i]) && (locale_cat_desc[i].cat != LC_ALL))
+ setlocale(locale_cat_desc[i].cat, "C");
+ }
+
+ end:
+ ecore_event_add(ECORE_EVENT_LOCALE_CHANGED, NULL, NULL, NULL);
+}
+
+static void
+_props_changed_locale(void *data, const Eldbus_Message *msg)
+{
+ Eldbus_Proxy *proxy = data;
+ Eldbus_Message_Iter *changed, *entry, *invalidated;
+ const char *iface, *prop;
+
+ if (!eldbus_message_arguments_get(msg, "sa{sv}as",
+ &iface, &changed, &invalidated))
+ {
+ ERR("Error getting data from properties changed signal.");
+ return;
+ }
+
+ while (eldbus_message_iter_get_and_next(changed, 'e', &entry))
+ {
+ const void *key;
+ Eldbus_Message_Iter *var;
+ if (!eldbus_message_iter_arguments_get(entry, "sv", &key, &var))
+ continue;
+ if (strcmp(key, "Locale") == 0)
+ goto changed_locale;
+ }
+
+ while (eldbus_message_iter_get_and_next(invalidated, 's', &prop))
+ {
+ if (strcmp(prop, "Locale") == 0)
+ goto changed_locale;
+ }
+
+ return;
+
+ changed_locale:
+ eldbus_proxy_property_get(proxy, "Locale", _locale_get, NULL);
+}
+
+static Eina_Bool
+_property_change_monitor(const char *name,
+ const char *path,
+ const char *iface,
+ Eldbus_Signal_Cb cb)
+{
+ Eldbus_Object *o;
+ Eldbus_Proxy *p;
+ Eldbus_Signal_Handler *s;
+
+ o = eldbus_object_get(_conn, name, path);
+ if (!o)
+ {
+ ERR("could not get object name=%s, path=%s", name, path);
+ return EINA_FALSE;
+ }
+
+ p = eldbus_proxy_get(o, iface);
+ if (!p)
+ {
+ ERR("could not get proxy interface=%s, name=%s, path=%s",
+ iface, name, path);
+ eldbus_object_unref(o);
+ return EINA_FALSE;
+ }
+
+ s = eldbus_proxy_properties_changed_callback_add(p, cb, p);
+ if (!s)
+ {
+ ERR("could not add signal handler for properties changed for proxy "
+ "interface=%s, name=%s, path=%s", iface, name, path);
+ eldbus_proxy_unref(p);
+ eldbus_object_unref(o);
+ return EINA_FALSE;
+ }
+
+ _objs = eina_list_append(_objs, o);
+ _proxies = eina_list_append(_proxies, p);
+ return EINA_TRUE;
+}
+
+static void _ecore_system_systemd_shutdown(void);
+
+static Eina_Bool
+_ecore_system_systemd_init(void)
+{
+ eldbus_init();
+
+ _log_dom = eina_log_domain_register("ecore_system_systemd", NULL);
+ if (_log_dom < 0)
+ {
+ EINA_LOG_ERR("Could not register log domain: ecore_system_systemd");
+ goto error;
+ }
+
+ _conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM);
+
+ if (!_property_change_monitor("org.freedesktop.hostname1",
+ "/org/freedesktop/hostname1",
+ "org.freedesktop.hostname1",
+ _props_changed_hostname))
+ goto error;
+
+ if (!_property_change_monitor("org.freedesktop.timedate1",
+ "/org/freedesktop/timedate1",
+ "org.freedesktop.timedate1",
+ _props_changed_timedate))
+ goto error;
+
+ if (!_property_change_monitor("org.freedesktop.locale1",
+ "/org/freedesktop/locale1",
+ "org.freedesktop.locale1",
+ _props_changed_locale))
+ goto error;
+
+ DBG("ecore system 'systemd' loaded");
+ return EINA_TRUE;
+
+ error:
+ _ecore_system_systemd_shutdown();
+ return EINA_FALSE;
+}
+
+static void
+_ecore_system_systemd_shutdown(void)
+{
+ DBG("ecore system 'systemd' unloaded");
+
+ while (_proxies)
+ {
+ eldbus_proxy_unref(_proxies->data);
+ _proxies = eina_list_remove_list(_proxies, _proxies);
+ }
+
+ while (_objs)
+ {
+ eldbus_object_unref(_objs->data);
+ _objs = eina_list_remove_list(_objs, _objs);
+ }
+
+ if (_conn)
+ {
+ eldbus_connection_unref(_conn);
+ _conn = NULL;
+ }
+
+ if (_log_dom > 0)
+ {
+ eina_log_domain_unregister(_log_dom);
+ _log_dom = -1;
+ }
+
+ eldbus_shutdown();
+}
+
+EINA_MODULE_INIT(_ecore_system_systemd_init);
+EINA_MODULE_SHUTDOWN(_ecore_system_systemd_shutdown);
--
------------------------------------------------------------------------------
Get 100% visibility into Java/.NET code with AppDynamics Lite!
It's a free troubleshooting tool designed for production.
Get down to code-level detail for bottlenecks, with <2% overhead.
Download for free and get started troubleshooting in minutes.
http://pubads.g.doubleclick.net/gampad/clk?id=48897031&iu=/4140/ostg.clktrk