From 0f87c35a7b01b7e56d03a78fa133a43f41c423a1 Mon Sep 17 00:00:00 2001 From: Cedric BAIL Date: Fri, 19 Oct 2012 11:10:28 +0000 Subject: [PATCH] e: add a tool to gather statistic. NOTE: The goal of this tool is to gather statistic about our user base so we could know what to improve and optimize in the futur. We don't gather personnal information only hardware and software configuration, so we know more about the real use of Enlightenment. At the moment this tool is not uploading anything on a website nor is it ready at all. I am just pushing it early so that people using other OS than Linux, can contribute to it. If that tool is ready for the release, we will use the gathered statistic for all our futur plan. If your OS is not in, we will basically not see it and so not take it into account. That's why I highly encourage those using E on other OS to contribute to this tool. SVN revision: 78247 --- configure.ac | 8 + src/bin/Makefile.am | 7 +- src/bin/e_static_grab.c | 465 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 479 insertions(+), 1 deletion(-) create mode 100644 src/bin/e_static_grab.c diff --git a/configure.ac b/configure.ac index 90164cfe0..6bfd89c95 100644 --- a/configure.ac +++ b/configure.ac @@ -466,6 +466,14 @@ PKG_CHECK_MODULES(E_THUMB, [ efreet >= ${efl_version} ]) +PKG_CHECK_MODULES(E_GRABBER, [ + eina >= ${efl_version} + ecore >= ${efl_version} + eet >= ${efl_version} + efreet >= ${efl_version} + ecore-x >= ${efl_version} +]) + efm_requires="\ ecore >= 1.2.0 \ ecore-file >= 1.2.0 \ diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am index 5772dc051..91dfc9b74 100644 --- a/src/bin/Makefile.am +++ b/src/bin/Makefile.am @@ -33,7 +33,8 @@ enlightenment_fm_op \ enlightenment_init \ enlightenment_sys \ enlightenment_thumb \ -enlightenment_alert +enlightenment_alert \ +enlightenment_static_grabber if HAVE_EEZE internal_bin_PROGRAMS += enlightenment_backlight @@ -426,6 +427,10 @@ enlightenment_open_SOURCES = e_open.c enlightenment_open_LDADD = @E_OPEN_LIBS@ enlightenment_open_CFLAGS = @E_OPEN_CFLAGS@ +enlightenment_static_grabber_SOURCES = e_static_grab.c +enlightenment_static_grabber_LDADD = @E_GRABBER_LIBS@ +enlightenment_static_grabber_CFLAGS = @E_GRABBER_CFLAGS@ + # HACK! why install-data-hook? install-exec-hook is run after bin_PROGRAMS # and before internal_bin_PROGRAMS are installed. install-data-hook is # run after both diff --git a/src/bin/e_static_grab.c b/src/bin/e_static_grab.c new file mode 100644 index 000000000..e3f5b41e1 --- /dev/null +++ b/src/bin/e_static_grab.c @@ -0,0 +1,465 @@ +#include +#include + +typedef struct _E_Static_Grab E_Static_Grab; +typedef struct _E_Static_Grab_Module E_Static_Grab_Module; + +struct _E_Static_Grab +{ + struct + { + int core_count; + int thread_count; + int bogo; + int model; + int family; + int stepping; + int cache_size; + int addr_space; + + const char *vendor; + const char *model_name; + + Eina_Bool fpu; + } cpu; + + struct + { + const char *name; + const char *release; + const char *os; + const char *kernel_release; + } distribution; + + struct { + struct + { + const char *vendor; + const char *renderer; + const char *version; + } gpu; + + const char *name; + const char *release_date; + const char *build_date; + + Eina_List *modules; + } x; +}; + +struct _E_Static_Grab_Module +{ + const char *name; + const char *vendor; + const char *compiled_for; + const char *version; + const char *class; + const char *ABI_class; + const char *ABI_version; +}; + +/* For /proc/cpuinfo */ +#define CPU_CORES "cpu cores" +#define CACHE_SIZE "cache size" +#define CPU_FAMILY "cpu family" +#define STEPPING "stepping" +#define SIBLINGS "siblings" +#define BOGOMIPS "bogomips" +#define MODEL "model" +#define MODEL_NAME "model name" +#define VENDOR_ID "vendor_id" +#define FPU "fpu" + +/* For /var/log/Xorg.0.log */ +#define RELEASE_DATE "Release Date" +#define BUILD_DATE "Build Date" +#define LOAD_MODULE "(II) LoadModule" +#define UNLOAD_MODULE "(II) UnloadModule" +#define MODULE_OF "(II) Module %s" +#define LOADING "(II) Loading" +#define VENDOR "vendor=\"" +#define COMPILED "compiled for " +#define MODULE_CLASS "Module class" +#define ABI_CLASS "ABI class" +#define VERSION ", version " + +static const char * +_e_static_grab_name(const char *line, const char *end, const char *name) +{ + size_t l; + + l = strlen(name); + if (line + l + 3 > end) return end; + if (strncmp(name, line, l)) return end; + + return line + l; +} + +static Eina_Bool +_e_static_grab_int(const char *line, const char *end, const char *txt, int *v) +{ + static const char *value = "0123456789"; + const char *over; + int r = 0; + + over = _e_static_grab_name(line, end, txt); + while (over < end) + { + if (strchr(value, *over)) break; + over++; + } + if (over == end) return EINA_FALSE; + + while (over < end) + { + const char *offset = strchr(value, *over); + + if (!offset) break; + r = r * 10 + (offset - value); + + over++; + } + + *v = r; + + return EINA_TRUE; +} + +static Eina_Bool +_e_static_grab_string(const char *line, const char *end, const char *txt, const char **s) +{ + static const char *value = " :\t"; + const char *over; + + over = _e_static_grab_name(line, end, txt); + while (over < end) + { + if (!strchr(value, *over)) break; + over++; + } + if (over == end) return EINA_FALSE; + + if (*over == '"' && *(end - 2) == '"') + { + over++; + end--; + } + + *s = eina_stringshare_add_length(over, end - over - 1); + return EINA_TRUE; +} + +static const char * +_e_static_grab_discard(const char *current, Eina_File_Line *line, int begin, int end) +{ + while (current < line->end && + strchr(" \t", *current)) + current++; + + if (*current != begin) return current; + + while (current < line->end && + *current != end) + current++; + + if (current == line->end) return current; + + for (current++; + current < line->end && strchr(" \t", *current); + current++) + ; + + return current; +} + +static void +_e_static_grab_cpu(E_Static_Grab *grab) +{ + char buf[4096]; + FILE *f; + const char *fpu = NULL; + int siblings = 0; + + grab->cpu.addr_space = sizeof (void*); + + f = fopen("/proc/cpuinfo", "r"); + if (!f) return ; + + while (!feof(f)) + { + char *end; + size_t length = 0; + size_t start = 0; + + fgets(buf, sizeof (buf), f); + length = strlen(buf); + end = buf + length; + + if (length < 3) continue ; + + switch (*buf) + { + case 'c': + if (_e_static_grab_int(buf, end, CPU_CORES, &grab->cpu.core_count)) break; + if (_e_static_grab_int(buf, end, CACHE_SIZE, &grab->cpu.cache_size)) break; + _e_static_grab_int(buf, end, CPU_FAMILY, &grab->cpu.family); + break; + case 's': + if (_e_static_grab_int(buf, end, STEPPING, &grab->cpu.stepping)) break; + _e_static_grab_int(buf, end, SIBLINGS, &siblings); + break; + case 'b': + _e_static_grab_int(buf, end, BOGOMIPS, &grab->cpu.bogo); + break; + case 'm': + if (_e_static_grab_string(buf, end, MODEL_NAME, &grab->cpu.model_name)) break; + _e_static_grab_int(buf, end, MODEL, &grab->cpu.model); + break; + case 'v': + _e_static_grab_string(buf, end, VENDOR_ID, &grab->cpu.vendor); + break; + case 'f': + _e_static_grab_string(buf, end, FPU, &fpu); + break; + } + } + fclose(f); + + if (siblings) grab->cpu.thread_count = siblings / grab->cpu.core_count; + if (fpu) + { + if (!strcmp(fpu, "yes")) grab->cpu.fpu = EINA_TRUE; + eina_stringshare_del(fpu); + } +} + +static void +_e_static_grab_x(E_Static_Grab *grab) +{ + Eina_Bool in_module = EINA_FALSE; + E_Static_Grab_Module *module; + Eina_File_Line *line; + Eina_Iterator *it; + Eina_File *f; + + module = calloc(1, sizeof (E_Static_Grab_Module)); + if (!module) return ; + + f = eina_file_open("/var/log/Xorg.0.log", EINA_FALSE); + if (!f) return ; + + it = eina_file_map_lines(f); + EINA_ITERATOR_FOREACH(it, line) + { + const char *current; + + current = _e_static_grab_discard(line->start, line, '[', ']'); + if (current >= line->end) continue ; + + if (!grab->x.name) + { + if (line->end - current - 1 <= 0) continue ; + grab->x.name = eina_stringshare_add_length(current, line->end - current - 1); + continue ; + } + + if (!in_module) + { + switch (*current) + { + case 'R': + if (_e_static_grab_string(current, line->end, RELEASE_DATE, &grab->x.release_date)) break; + break; + + case 'B': + if (_e_static_grab_string(current, line->end, BUILD_DATE, &grab->x.build_date)) break; + break; + + case '(': + { + E_Static_Grab_Module *md; + Eina_List *l; + const char *tmp; + + if (_e_static_grab_string(current, line->end, LOAD_MODULE, &module->name)) + { + EINA_LIST_FOREACH(grab->x.modules, l, md) + if (md->name == module->name) + { + eina_stringshare_del(module->name); + module->name = NULL; + break; + } + + if (module->name) in_module = EINA_TRUE; + break; + } + else if (_e_static_grab_string(current, line->end, UNLOAD_MODULE, &tmp)) + { + EINA_LIST_FOREACH(grab->x.modules, l, md) + if (md->name == tmp) + { + grab->x.modules = eina_list_remove_list(grab->x.modules, l); + + eina_stringshare_del(md->name); + eina_stringshare_del(md->vendor); + eina_stringshare_del(md->compiled_for); + eina_stringshare_del(md->version); + eina_stringshare_del(md->class); + eina_stringshare_del(md->ABI_class); + eina_stringshare_del(md->ABI_version); + free(md); + break; + } + eina_stringshare_del(tmp); + } + break; + } + } + } + else + { + char *buffer; + Eina_Bool found = EINA_FALSE; + + switch (*current) + { + case '(': + { + const char *vendor; + + if (strncmp(current, LOADING, strlen(LOADING)) == 0) + { + found = EINA_TRUE; + break; + } + + buffer = alloca(strlen(MODULE_OF) + strlen(module->name)); + sprintf(buffer, MODULE_OF, module->name); + + if (_e_static_grab_string(current, line->end, buffer, &vendor)) + { + if (strncmp(vendor, VENDOR, strlen(VENDOR)) == 0) + { + module->vendor = eina_stringshare_add_length(vendor + strlen(VENDOR), + eina_stringshare_strlen(vendor) - strlen(VENDOR) - 1); + found = EINA_TRUE; + } + eina_stringshare_del(vendor); + } + break; + } + case 'c': + if (strncmp(current, COMPILED, strlen(COMPILED)) == 0) + { + const char *lookup = current + strlen(COMPILED); + + while (lookup < line->end && *lookup != ',') + lookup++; + + module->compiled_for = eina_stringshare_add_length(current + strlen(COMPILED), + lookup - current - strlen(COMPILED)); + found = EINA_TRUE; + break; + } + break; + case 'M': + if (_e_static_grab_string(current, line->end, MODULE_CLASS, &module->class)) + { + found = EINA_TRUE; + break; + } + break; + case 'A': + { + const char *tmp; + + if (_e_static_grab_string(current, line->end, ABI_CLASS, &tmp)) + { + const char *lookup = strchr(tmp, ','); + + if (lookup) + { + module->ABI_class = eina_stringshare_add_length(tmp, lookup - tmp); + if (strncmp(lookup, VERSION, strlen(VERSION)) == 0) + { + module->ABI_version = eina_stringshare_add_length(lookup + strlen(VERSION), + eina_stringshare_strlen(tmp) - (lookup - tmp + strlen(VERSION) - 1)); + } + eina_stringshare_del(tmp); + } + else + { + module->ABI_class = tmp; + } + } + break; + } + } + + if (!found) + { + in_module = EINA_FALSE; + grab->x.modules = eina_list_append(grab->x.modules, module); + module = calloc(1, sizeof (E_Static_Grab_Module)); + } + } + } + + free(module); + + eina_iterator_free(it); + eina_file_close(f); +} + +int +main(int argc, char **argv) +{ + E_Static_Grab_Module *module; + Eina_List *l; + E_Static_Grab grab; + const char *output; + + if (argc != 2) exit(0); + +#if 0 + /* FIXME: Latter push information into an eet file when updated */ + if ((!strcmp(argv[1], "-h")) || + (!strcmp(argv[1], "-help")) || + (!strcmp(argv[1], "--help"))) + { + printf("This is an internal tool for Enlightenment.\n" + "do not use it.\n"); + exit(0); + } +#endif + + eina_init(); + eet_init(); + + output = argv[1]; + + memset(&grab, 0, sizeof (grab)); + _e_static_grab_cpu(&grab); /* FIXME: please provide patch for more Unix */ + _e_static_grab_x(&grab); + + fprintf(stderr, "%i core with %i thread running in %i bits at %i bogomips with %i cache from vendor %s with model %s\n", + grab.cpu.core_count, grab.cpu.thread_count, grab.cpu.addr_space * 8, grab.cpu.bogo, grab.cpu.cache_size, grab.cpu.vendor, grab.cpu.model_name); + fprintf(stderr, "X Server: '%s' released '%s' and build '%s'\n", + grab.x.name, grab.x.release_date, grab.x.build_date); + fprintf(stderr, "*** X Modules ***\n"); + EINA_LIST_FOREACH(grab.x.modules, l, module) + fprintf(stderr, "[%s - '%s' - '%s' - '%s' - '%s','%s' ]\n", + module->name, module->vendor, module->compiled_for, + module->class, module->ABI_class, module->ABI_version); + fprintf(stderr, "*** ***\n"); + + /* FIXME: Get information about what Unix (Linux, BSD, ...) it is run on */ + /* FIXME: run a mainloop and start gathering result from df, free, lspci and lsusb */ + /* FIXME: use xrandr to figure out the screen config */ + + eet_shutdown(); + eina_shutdown(); + + return 0; +}