[Workman-devel] [PATCH v2] CLI: workman command line interface framework

Josh Poimboeuf jpoimboe at redhat.com
Fri Apr 19 01:28:58 UTC 2013


v2: 
- use glib option parser framework

---8<---

This adds the framework for the "workman" tool which will be the command
line interface to libworkman.

- Add a barely functional workman.c with the basic interfaces in place,
  and one of the commands implemented.
- Update the makefiles to build tools/Makefile and workman.
- Update the libworkman makefile to link with libgobject.
- Export some needed libworkman symbols.
---
 .gitignore             |   1 +
 Makefile.am            |   2 +-
 configure.ac           |   1 +
 tools/Makefile.am      |  14 ++++
 tools/workman.c        | 220 +++++++++++++++++++++++++++++++++++++++++++++++++
 workman/Makefile.am    |   5 +-
 workman/libworkman.sym |   2 +
 7 files changed, 243 insertions(+), 2 deletions(-)
 create mode 100644 tools/Makefile.am
 create mode 100644 tools/workman.c

diff --git a/.gitignore b/.gitignore
index 348274b..b4996bb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -64,3 +64,4 @@ docs/workman/version.xml
 *.swp
 cscope.*
 workman/workman-enums.[ch]
+tools/workman
diff --git a/Makefile.am b/Makefile.am
index 4eac35b..4cec125 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,5 +1,5 @@
 
-SUBDIRS = workman docs
+SUBDIRS = workman tools docs
 
 ACLOCAL_AMFLAGS = -I m4
 
diff --git a/configure.ac b/configure.ac
index 3ea30da..8df0ed2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -89,6 +89,7 @@ AM_CONDITIONAL([WITH_GOBJECT_INTROSPECTION], [test "x$enable_introspection" = "x
 
 AC_OUTPUT(Makefile
           workman/Makefile
+          tools/Makefile
           docs/Makefile
           docs/workman/Makefile
           docs/workman/version.xml
diff --git a/tools/Makefile.am b/tools/Makefile.am
new file mode 100644
index 0000000..1cfc65c
--- /dev/null
+++ b/tools/Makefile.am
@@ -0,0 +1,14 @@
+bin_PROGRAMS = workman
+
+workman_SOURCES = workman.c
+
+workman_CFLAGS = \
+		 -I$(top_srcdir) \
+		 $(GOBJECT2_CFLAGS) \
+		 $(WARN_CFLAGS) \
+		 $(NULL)
+
+workman_LDADD = \
+		../workman/libworkman-1.0.la \
+		$(NULL)
+
diff --git a/tools/workman.c b/tools/workman.c
new file mode 100644
index 0000000..2ec9965
--- /dev/null
+++ b/tools/workman.c
@@ -0,0 +1,220 @@
+/*
+ * workman.c: cmdline interface to libworkman
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Author: Josh Poimboeuf <jpoimboe at redhat.com>
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <glib.h>
+#include <config.h>
+#include "workman/workman.h"
+
+struct workman_args {
+    WorkmanState state;
+    int cmd_argc;
+    char **cmd_argv;
+};
+
+struct workman_cmd {
+    const char *name;
+    const char *arg_description;
+    int min_args;
+    int max_args;
+    void (*handler)(WorkmanManager *, struct workman_args *);
+};
+
+
+#define WORKMAN_ERROR_EXIT(err, fmt, ...)                                   \
+({                                                                          \
+    fprintf(stderr, fmt, ##__VA_ARGS__);                                    \
+    if (err)                                                                \
+        fprintf(stderr, ": %s", err->message);                              \
+    fprintf(stderr, "\n");                                                  \
+    exit(1);                                                                \
+})
+
+#define WORKMAN_USAGE_EXIT(...)                                             \
+({                                                                          \
+    GError *err = NULL;                                                     \
+    WORKMAN_ERROR_EXIT(err, __VA_ARGS__);                                   \
+})
+
+static void
+list_partitions(WorkmanManager *mgr,
+                struct workman_args *args)
+{
+    GList *partitions, *p;
+    GError *err = NULL;
+    char *parent_name = NULL;
+
+    if (args->cmd_argc == 1)
+        parent_name = args->cmd_argv[0];
+    else if (args->cmd_argc != 0)
+        WORKMAN_USAGE_EXIT("unknown arguments");
+
+    partitions = workman_manager_get_partitions(mgr, args->state, &err);
+
+    if (partitions) {
+        g_warn_if_fail(err == NULL);
+        for (p = partitions; p; p = p->next) {
+            WorkmanPartition *part = WORKMAN_PARTITION(p->data);
+
+            if (parent_name) {
+                WorkmanPartition *parent;
+                parent = workman_partition_get_parent(part, args->state, &err);
+                if (err)
+                    WORKMAN_ERROR_EXIT(err,
+                                       "workman_partition_get_parent failed");
+                if (!parent ||
+                    g_strcmp0(parent_name,
+                              workman_object_get_name(WORKMAN_OBJECT(parent))))
+                    continue;
+            }
+
+            printf("%s\n", workman_object_get_name(WORKMAN_OBJECT(part)));
+        }
+
+        g_boxed_free(WORKMAN_TYPE_PARTITION_LIST, partitions);
+    }
+}
+
+static void list_consumers(WorkmanManager *mgr, struct workman_args *args) {}
+static void list_attributes(WorkmanManager *mgr, struct workman_args *args) {}
+static void list_processes(WorkmanManager *mgr, struct workman_args *args) {}
+static void show_partition(WorkmanManager *mgr, struct workman_args *args) {}
+static void show_attribute(WorkmanManager *mgr, struct workman_args *args) {}
+static void set_partition(WorkmanManager *mgr, struct workman_args *args) {}
+static void set_attribute(WorkmanManager *mgr, struct workman_args *args) {}
+static void create_partition(WorkmanManager *mgr, struct workman_args *args) {}
+
+static const struct workman_cmd workman_cmds[] = {
+    {"partitions",          "[PARTITION]",              0, 0, list_partitions},
+    {"consumers",           "[PARTITION]",              0, 1, list_consumers},
+    {"attributes",          "OBJECT",                   1, 1, list_attributes},
+    {"processes",           "CONSUMER",                 1, 1, list_processes},
+    {"partition",           "PARTITION|CONSUMER",       1, 1, show_partition},
+    {"attribute",           "OBJECT ATTRIBUTE",         2, 2, show_attribute},
+    {"set-partition",       "PARTITION|CONSUMER",       2, 2, set_partition},
+    {"set-attribute",       "OBJECT ATTRIBUTE VALUE",   3, 3, set_attribute},
+    {"create-partition",    "NAME",                     1, 1, create_partition},
+    {},
+};
+
+
+int
+main(int argc, char **argv)
+{
+    const struct workman_cmd *cmd;
+    struct workman_args args;
+    static gchar *state = NULL;
+    static gchar **cmd_args = NULL;
+    GOptionContext *context;
+    GError *error = NULL;
+    static gchar *description, *tmpstr;
+    int i;
+
+    static GOptionEntry options[] = {
+        {"state", 's', 0, G_OPTION_ARG_STRING, &state, "active, persistent, or all (default=active)\n", NULL},
+        {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &cmd_args, NULL, "COMMAND [ARGS...]"},
+        {},
+    };
+
+    g_type_init();
+
+    context = g_option_context_new(" - workload manager");
+
+    g_option_context_add_main_entries(context, options, NULL);;
+
+    tmpstr = g_malloc(1024);
+    i = sprintf(tmpstr, "Commands:\n");
+    for (cmd = workman_cmds; cmd->name; cmd++)
+        i += snprintf(tmpstr + i, 1024 - i, "  %s %s\n", cmd->name, cmd->arg_description);
+    description = g_strdup(tmpstr);
+    g_free(tmpstr);
+    g_option_context_set_description(context, description);
+
+    if (!g_option_context_parse(context, &argc, &argv, &error)) {
+        g_print("option parsing failed: %s\n", error->message);
+        exit(1);
+    }
+
+    if (!state || !g_strcmp0(state, "active"))
+        args.state = WORKMAN_STATE_ACTIVE;
+    else if (!g_strcmp0(state, "persistent"))
+        args.state = WORKMAN_STATE_PERSISTENT;
+    else if (!g_strcmp0(state, "all"))
+        args.state = WORKMAN_STATE_ALL;
+    else
+        WORKMAN_USAGE_EXIT("invalid state");
+    g_free(state);
+
+    if (!cmd_args || !cmd_args[0])
+        WORKMAN_USAGE_EXIT("missing command");
+
+    for (cmd = workman_cmds; ; cmd++) {
+
+        if (!cmd->name)
+            WORKMAN_USAGE_EXIT("unknown command '%s'", cmd_args[0]);
+
+        if (!g_strcmp0(cmd_args[0], cmd->name)) {
+
+            WorkmanManager *mgr;
+            GError *err = NULL;
+
+            args.cmd_argc = 0;
+            while (cmd_args[args.cmd_argc + 1])
+                args.cmd_argc++;
+
+            args.cmd_argv = &cmd_args[1];
+
+            if (args.cmd_argc < cmd->min_args || args.cmd_argc > cmd->max_args)
+                WORKMAN_USAGE_EXIT("invalid number of arguments for '%s'",
+                                   cmd->name);
+
+            workman_init(NULL, NULL);
+
+            mgr = workman_manager_get_default(&err);
+            if (!mgr)
+                WORKMAN_ERROR_EXIT(err, "workman_manager_get_default failed");
+
+            cmd->handler(mgr, &args);
+            break;
+        }
+    }
+
+    g_option_context_free(context);
+
+    return 0;
+}
+
+
+
+/*
+ * Local variables:
+ *  indent-tabs-mode: nil
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ * End:
+ *
+ * vim: set expandtab shiftwidth=4 tabstop=4 :
+ */
diff --git a/workman/Makefile.am b/workman/Makefile.am
index 4ef03f3..67c16c9 100644
--- a/workman/Makefile.am
+++ b/workman/Makefile.am
@@ -49,10 +49,13 @@ libworkman_1_0_la_CFLAGS = \
 			-I$(top_srcdir) \
 			$(GLIB2_CFLAGS) \
 			$(GTHREAD2_CFLAGS) \
+			$(GOBJECT2_CFLAGS) \
 			$(WARN_CFLAGS)
 libworkman_1_0_la_LIBADD = \
 			$(GLIB2_LIBS) \
-			$(GTHREAD2_LIBS)
+			$(GTHREAD2_LIBS) \
+			$(GOBJECT2_LIBS) \
+			$(NULL)
 libworkman_1_0_la_DEPENDENCIES = \
 			libworkman.sym
 libworkman_1_0_la_LDFLAGS = \
diff --git a/workman/libworkman.sym b/workman/libworkman.sym
index 1eefc96..ff4065b 100644
--- a/workman/libworkman.sym
+++ b/workman/libworkman.sym
@@ -10,6 +10,7 @@ LIBworkman_0.0.1 {
         workman_object_save_attributes;
         workman_object_get_state;
         workman_object_attribute_list_get_type;
+        workman_object_get_name;
 
         workman_attribute_get_name;
         workman_attribute_get_type;
@@ -30,6 +31,7 @@ LIBworkman_0.0.1 {
         workman_manager_new;
         workman_manager_remove_partition;
         workman_manager_refresh_objects;
+        workman_manager_get_default;
 
         workman_partition_get_consumers;
         workman_partition_get_children;
-- 
1.7.11.7




More information about the Workman-devel mailing list