summaryrefslogtreecommitdiffstats
path: root/src/service-dbus
diff options
context:
space:
mode:
authorVitezslav Crhonek <vcrhonek@redhat.com>2014-04-10 14:14:29 +0200
committerVitezslav Crhonek <vcrhonek@redhat.com>2014-04-10 14:14:29 +0200
commitbbf83307946d07c7189ba7bfe90b56797c11ef39 (patch)
tree9f2e8205c862385062c8d14f90326dd87459bdaa /src/service-dbus
parent40d748aee3fdbfea407f9ed9312f8979c489e207 (diff)
downloadopenlmi-providers-bbf83307946d07c7189ba7bfe90b56797c11ef39.tar.gz
openlmi-providers-bbf83307946d07c7189ba7bfe90b56797c11ef39.tar.xz
openlmi-providers-bbf83307946d07c7189ba7bfe90b56797c11ef39.zip
Service-dbus: Improve EnumerateInstances efficiency
Diffstat (limited to 'src/service-dbus')
-rw-r--r--src/service-dbus/LMI_ServiceProvider.c55
-rw-r--r--src/service-dbus/util/serviceutil.c199
-rw-r--r--src/service-dbus/util/serviceutil.h10
3 files changed, 249 insertions, 15 deletions
diff --git a/src/service-dbus/LMI_ServiceProvider.c b/src/service-dbus/LMI_ServiceProvider.c
index ff61e49..709faa5 100644
--- a/src/service-dbus/LMI_ServiceProvider.c
+++ b/src/service-dbus/LMI_ServiceProvider.c
@@ -77,24 +77,49 @@ static CMPIStatus LMI_ServiceEnumInstances(
const CMPIObjectPath* cop,
const char** properties)
{
- CMPIStatus st;
- CMPIEnumeration* e;
- if (!(e = _cb->bft->enumerateInstanceNames(_cb, cc, cop, &st))) {
- KReturn2(_cb, ERR_FAILED, "Unable to enumerate instances of LMI_Service");
- }
- CMPIData cd;
- while (CMHasNext(e, &st)) {
+ AllServices *svcs = NULL;
+ CMPIStatus status;
+ char output[1024];
- cd = CMGetNext(e, &st);
- if (st.rc || cd.type != CMPI_ref) {
- KReturn2(_cb, ERR_FAILED, "Enumerate instances didn't returned list of references");
- }
- CMPIInstance *in = _cb->bft->getInstance(_cb, cc, cd.value.ref, properties, &st);
- if (st.rc) {
- KReturn2(_cb, ERR_FAILED, "Unable to get instance of LMI_Service");
+ if ((svcs = service_get_properties_all(output, sizeof(output))) != NULL) {
+ for(int i = 0; i < svcs->cnt; i++) {
+ LMI_Service w;
+ LMI_Service_InitFromObjectPath(&w, _cb, cop);
+ LMI_Service_Set_CreationClassName(&w, LMI_Service_ClassName);
+ LMI_Service_Set_SystemCreationClassName(&w, get_system_creation_class_name());
+ LMI_Service_Set_SystemName(&w, get_system_name());
+ LMI_Service_Set_Name(&w, svcs->svc[i]->svName);
+ LMI_Service_Set_Status(&w, svcs->svc[i]->svStatus);
+ LMI_Service_Set_Started(&w, svcs->svc[i]->svStarted);
+ LMI_Service_Set_Caption(&w, svcs->svc[i]->svCaption);
+ LMI_Service_Init_OperationalStatus(&w, svcs->svc[i]->svOperationalStatusCnt);
+ for (int j = 0; j < svcs->svc[i]->svOperationalStatusCnt; j++) {
+ LMI_Service_Set_OperationalStatus(&w, j, svcs->svc[i]->svOperationalStatus[j]);
+ }
+
+ switch (svcs->svc[i]->svEnabledDefault) {
+ case ENABLED:
+ LMI_Service_Set_EnabledDefault(&w, LMI_Service_EnabledDefault_Enabled);
+ break;
+ case DISABLED:
+ LMI_Service_Set_EnabledDefault(&w, LMI_Service_EnabledDefault_Disabled);
+ break;
+ default:
+ LMI_Service_Set_EnabledDefault(&w, LMI_Service_EnabledDefault_Not_Applicable);
+ break;
+ }
+
+ status = __KReturnInstance((cr), &(w).__base);
+ if (!KOkay(status)) {
+ service_free_all_services(svcs);
+ return status;
+ }
}
- cr->ft->returnInstance(cr, in);
+ } else {
+ KReturn2(_cb, ERR_FAILED, "%s", output);
}
+
+ service_free_all_services(svcs);
KReturn(OK);
}
diff --git a/src/service-dbus/util/serviceutil.c b/src/service-dbus/util/serviceutil.c
index b56bd16..bca196e 100644
--- a/src/service-dbus/util/serviceutil.c
+++ b/src/service-dbus/util/serviceutil.c
@@ -56,6 +56,24 @@ void service_free_slist(SList *slist)
return;
}
+void service_free_all_services(AllServices *svcs)
+{
+ int i;
+
+ if (!svcs)
+ return;
+
+ for(i = 0; i < svcs->cnt; i++) {
+ free(svcs->svc[i]->svName);
+ free(svcs->svc[i]->svCaption);
+ free(svcs->svc[i]->svStatus);
+ free(svcs->svc[i]);
+ }
+ free(svcs);
+
+ return;
+}
+
SList *service_find_all(
char *output,
int output_len)
@@ -140,6 +158,187 @@ SList *service_find_all(
return slist;
}
+AllServices *service_get_properties_all(
+ char *output,
+ int output_len)
+{
+ GDBusProxy *manager_proxy = NULL;
+ GDBusProxy *proxy = NULL;
+ GVariantIter *arr = NULL;
+ GVariant *result = NULL;
+ GVariant *result2 = NULL;
+ GError *error = NULL;
+ gchar *primary_unit_name = NULL, *unit_file_state = NULL;
+ gchar *unit, *value_str;
+ AllServices *svcs = NULL;
+ char *tmps = NULL;
+
+ svcs = malloc(sizeof(AllServices));
+ if (!svcs) {
+ strncpy(output, "Insufficient memory", output_len);
+ return NULL;
+ }
+ svcs->nalloc = INITIAL_SLIST_NALLOC;
+ svcs->svc = malloc(svcs->nalloc * sizeof(Service *));
+ if (!svcs->svc) {
+ free(svcs);
+ strncpy(output, "Insufficient memory", output_len);
+ return NULL;
+ }
+ svcs->cnt = 0;
+
+#if !defined(GLIB_VERSION_2_36)
+ g_type_init();
+#endif
+
+ manager_proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
+ NULL, MANAGER_NAME, MANAGER_OP, MANAGER_INTERFACE, NULL, &error);
+ if (!manager_proxy) goto err;
+
+ error = NULL;
+ result = g_dbus_proxy_call_sync(manager_proxy, "ListUnitFiles", NULL,
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+ if (error) goto err;
+
+ g_variant_get(result, "(a(ss))", &arr);
+ while (g_variant_iter_loop(arr, "(ss)", &primary_unit_name, &unit_file_state)) {
+ /* Ignore instantiable units (containing '@') until we find out how to properly present them */
+ if (strstr(primary_unit_name, ".service") && strchr(primary_unit_name, '@') == NULL) {
+
+ /* Realloc we are out of space */
+ if (svcs->cnt >= svcs->nalloc) {
+ Service **tmpp = NULL;
+ svcs->nalloc *= 2;
+ tmpp = realloc(svcs->svc, svcs->nalloc * sizeof(Service *));
+ if (!tmpp) {
+ g_variant_iter_free(arr);
+ service_free_all_services(svcs);
+ g_object_unref(manager_proxy);
+ strncpy(output, "Insufficient memory", output_len);
+ return NULL;
+ }
+ svcs->svc = tmpp;
+ }
+
+ svcs->svc[svcs->cnt] = malloc(sizeof(Service));
+
+ /* Fill svName */
+ tmps = strdup(primary_unit_name);
+ if (!tmps) {
+ g_variant_iter_free(arr);
+ service_free_all_services(svcs);
+ g_object_unref(manager_proxy);
+ strncpy(output, "Insufficient memory", output_len);
+ return NULL;
+ }
+ svcs->svc[svcs->cnt]->svName = strndup(basename(tmps), strlen(basename(tmps)));
+ if (!svcs->svc[svcs->cnt]->svName) {
+ free(tmps);
+ g_variant_iter_free(arr);
+ service_free_all_services(svcs);
+ g_object_unref(manager_proxy);
+ strncpy(output, "Insufficient memory", output_len);
+ return NULL;
+ }
+ free(tmps);
+
+ /* Fill svEnabledDefault */
+ svcs->svc[svcs->cnt]->svEnabledDefault = NOT_APPLICABLE;
+ if (strncmp(unit_file_state, "enabled", 7) == 0)
+ svcs->svc[svcs->cnt]->svEnabledDefault = ENABLED;
+ if (strncmp(unit_file_state, "disabled", 8) == 0)
+ svcs->svc[svcs->cnt]->svEnabledDefault = DISABLED;
+
+ error = NULL;
+ result = g_dbus_proxy_call_sync(manager_proxy, "LoadUnit", g_variant_new("(s)", svcs->svc[svcs->cnt]->svName),
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+ if (error) goto err;
+
+ g_variant_get(result, "(o)", &unit);
+
+ proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
+ NULL, MANAGER_NAME, unit, PROPERTY_INTERFACE, NULL, &error);
+ if (!proxy) goto err;
+
+ error = NULL;
+ result = g_dbus_proxy_call_sync(proxy, "Get", g_variant_new("(ss)", UNIT_INTERFACE, "Description"),
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+ if (error) goto err;
+
+ /* Fill svCaption */
+ g_variant_get(result, "(v)", &result2);
+ g_variant_get(result2, "s", &value_str);
+ svcs->svc[svcs->cnt]->svCaption = strdup(value_str);
+ if (!svcs->svc[svcs->cnt]->svCaption) goto err;
+
+ error = NULL;
+ result = g_dbus_proxy_call_sync(proxy, "Get", g_variant_new("(ss)", UNIT_INTERFACE, "ActiveState"),
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+ if (error) goto err;
+
+ /* Fill svOperationalStatus, svStarted, svStatus */
+ g_variant_get(result, "(v)", &result2);
+ g_variant_get(result2, "s", &value_str);
+
+ if (strcmp(value_str, "active") == 0) {
+ svcs->svc[svcs->cnt]->svOperationalStatus[0] = OS_OK;
+ svcs->svc[svcs->cnt]->svOperationalStatusCnt = 1;
+ svcs->svc[svcs->cnt]->svStarted = 1;
+ svcs->svc[svcs->cnt]->svStatus = strdup("OK");
+ }
+ else if (strcmp(value_str, "inactive") == 0) {
+ svcs->svc[svcs->cnt]->svOperationalStatus[0] = OS_COMPLETED;
+ svcs->svc[svcs->cnt]->svOperationalStatus[1] = OS_OK;
+ svcs->svc[svcs->cnt]->svOperationalStatusCnt = 2;
+ svcs->svc[svcs->cnt]->svStarted = 0;
+ svcs->svc[svcs->cnt]->svStatus = strdup("Stopped");
+ }
+ else if (strcmp(value_str, "failed") == 0) {
+ svcs->svc[svcs->cnt]->svOperationalStatus[0] = OS_COMPLETED;
+ svcs->svc[svcs->cnt]->svOperationalStatus[1] = OS_ERROR;
+ svcs->svc[svcs->cnt]->svOperationalStatusCnt = 2;
+ svcs->svc[svcs->cnt]->svStarted = 0;
+ svcs->svc[svcs->cnt]->svStatus = strdup("Stopped");
+ }
+ else if (strcmp(value_str, "activating") == 0) {
+ svcs->svc[svcs->cnt]->svOperationalStatus[0] = OS_STARTING;
+ svcs->svc[svcs->cnt]->svOperationalStatusCnt = 1;
+ svcs->svc[svcs->cnt]->svStarted = 0;
+ svcs->svc[svcs->cnt]->svStatus = strdup("Stopped");
+ }
+ else if (strcmp(value_str, "deactivating") == 0) {
+ svcs->svc[svcs->cnt]->svOperationalStatus[0] = OS_STOPPING;
+ svcs->svc[svcs->cnt]->svOperationalStatusCnt = 1;
+ svcs->svc[svcs->cnt]->svStarted = 1;
+ svcs->svc[svcs->cnt]->svStatus = strdup("OK");
+ }
+ if (!svcs->svc[svcs->cnt]->svStatus) goto err;
+
+ g_object_unref(proxy);
+ svcs->cnt++;
+ }
+ }
+ g_variant_iter_free(arr);
+ arr = NULL;
+
+ g_object_unref(manager_proxy);
+ manager_proxy = NULL;
+
+ return svcs;
+
+err:
+ service_free_all_services(svcs);
+ if (error) {
+ strncpy(output, error->message, output_len);
+ g_error_free(error);
+ }
+ if (arr) g_variant_iter_free(arr);
+ if (manager_proxy) g_object_unref(manager_proxy);
+ if (proxy) g_object_unref(proxy);
+
+ return NULL;
+}
+
int service_get_properties(
Service *svc,
diff --git a/src/service-dbus/util/serviceutil.h b/src/service-dbus/util/serviceutil.h
index 99a228e..c5b0abf 100644
--- a/src/service-dbus/util/serviceutil.h
+++ b/src/service-dbus/util/serviceutil.h
@@ -61,9 +61,19 @@ struct _SList {
typedef struct _Service Service;
typedef struct _SList SList;
+struct _AllServices {
+ Service **svc;
+ int cnt;
+ int nalloc;
+};
+
+typedef struct _AllServices AllServices;
+
void service_free_slist(SList *slist);
+void service_free_all_services(AllServices *svcs);
SList *service_find_all(char *output, int output_len);
+AllServices *service_get_properties_all(char *output, int output_len);
int service_get_properties(Service *svc, const char *service, char *output, int output_len);
unsigned int service_operation(const char *service, const char *method, char *output, int output_len);