From f2b0384f6231324f53e78aa458b9a46b0e659c43 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Orsini Date: Mon, 16 May 2011 08:59:30 +0000 Subject: [PATCH] added --debug option added cache (for distro_arch_series and distro_series) improved stats displayed --- src/Makefile.am | 4 ++- src/Makefile.in | 9 ++++-- src/cache.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/cache.h | 30 ++++++++++++++++++++ src/html.c | 3 +- src/lp.c | 32 ++++++++++++++++++++- src/lp.h | 25 ++++++++++++++--- src/lp_json.c | 33 +++++++++++++++++++++- src/lp_json.h | 1 + src/lp_ws.c | 56 +++++++++++++++++++++++++++++++++---- src/lp_ws.h | 6 +++- src/main.c | 24 ++++++++++++---- src/ppastats.h | 25 +++++++++++++++++ 13 files changed, 312 insertions(+), 23 deletions(-) create mode 100644 src/cache.c create mode 100644 src/cache.h create mode 100644 src/ppastats.h diff --git a/src/Makefile.am b/src/Makefile.am index 4a81afd..1cd1da4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -6,11 +6,13 @@ LIBS += $(CURL_LIBS) $(JSON_LIBS) bin_PROGRAMS = ppastats ppastats_SOURCES = \ + cache.h cache.c\ html.h html.c\ lp.h lp.c\ lp_json.h lp_json.c\ lp_ws.h lp_ws.c\ - main.c + main.c\ + ppastats.h dist_man_MANS = ppastats.1 diff --git a/src/Makefile.in b/src/Makefile.in index 0ba5682..fc6b2a6 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -46,8 +46,8 @@ CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" PROGRAMS = $(bin_PROGRAMS) -am_ppastats_OBJECTS = html.$(OBJEXT) lp.$(OBJEXT) lp_json.$(OBJEXT) \ - lp_ws.$(OBJEXT) main.$(OBJEXT) +am_ppastats_OBJECTS = cache.$(OBJEXT) html.$(OBJEXT) lp.$(OBJEXT) \ + lp_json.$(OBJEXT) lp_ws.$(OBJEXT) main.$(OBJEXT) ppastats_OBJECTS = $(am_ppastats_OBJECTS) ppastats_LDADD = $(LDADD) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) @@ -187,11 +187,13 @@ AM_CPPFLAGS = -Wall -std=gnu99 -Werror \ $(CURL_CFLAGS) $(JSON_CFLAGS) ppastats_SOURCES = \ + cache.h cache.c\ html.h html.c\ lp.h lp.c\ lp_json.h lp_json.c\ lp_ws.h lp_ws.c\ - main.c + main.c\ + ppastats.h dist_man_MANS = ppastats.1 all: all-am @@ -275,6 +277,7 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cache.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/html.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lp_json.Po@am__quote@ diff --git a/src/cache.c b/src/cache.c new file mode 100644 index 0000000..d70e308 --- /dev/null +++ b/src/cache.c @@ -0,0 +1,87 @@ +/* + Copyright (C) 2011 jeanfi@gmail.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA +*/ + +#include "cache.h" +#include "ppastats.h" + +#include +#include +#include + +/* + Stupid cache implementation but should be enough for storing LP data. +*/ + +struct entry { + const char *key; + const void *value; + void (*fct_cleanup)(void *); +}; + +#define CAPACITY 1024 + +struct cache { + int size; + struct entry entries[CAPACITY]; +}; + +static struct cache cache; + +const void *cache_get(const char *key) +{ + int i; + + for (i = 0; i < cache.size; i++) + if (!strcmp(cache.entries[i].key, key)) { + if (debug) + printf("DEBUG: cache hit %s\n", key); + + return cache.entries[i].value; + } + + if (debug) + printf("DEBUG: cache miss %s\n", key); + + return NULL; +} + +void cache_put(const char *key, const void *value, + void (*fct_cleanup)(void *)) +{ + if (cache.size == CAPACITY) { + fprintf(stderr, "WARNING: exceed cache capacity\n"); + return ; + } + + cache.entries[cache.size].key = strdup(key); + cache.entries[cache.size].value = value; + cache.entries[cache.size].fct_cleanup = fct_cleanup; + + cache.size++; +} + +void cache_cleanup() +{ + int i; + + for (i = 0; i < cache.size; i++) { + free((char *)cache.entries[i].key); + cache.entries[i].fct_cleanup((void *)cache.entries[i].value); + } +} diff --git a/src/cache.h b/src/cache.h new file mode 100644 index 0000000..c3462c9 --- /dev/null +++ b/src/cache.h @@ -0,0 +1,30 @@ +/* + Copyright (C) 2011 jeanfi@gmail.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA +*/ + +#ifndef _PPASTATS_CACHE_H_ +#define _PPASTATS_CACHE_H_ + +const void *cache_get(const char *key); + +void cache_put(const char *key, const void *value, + void (*fct_cleanup)(void *)); + +void cache_cleanup(); + +#endif diff --git a/src/html.c b/src/html.c index 9734c72..fb4dac1 100644 --- a/src/html.c +++ b/src/html.c @@ -142,7 +142,7 @@ build_data_str(struct binary_package_publishing_history **list) data = json_object_new_array(); for (i = 0; i < n; i++) { struct binary_package_publishing_history *binary; - struct distro_arch_series *dist; + const struct distro_arch_series *dist; struct daily_download_total **totals; struct daily_download_total **t_cur; @@ -175,7 +175,6 @@ build_data_str(struct binary_package_publishing_history **list) } daily_download_total_list_free(totals); - distro_arch_series_free(dist); } str = strdup(json_object_to_json_string(data)); diff --git a/src/lp.c b/src/lp.c index c80210b..e927b2e 100644 --- a/src/lp.c +++ b/src/lp.c @@ -23,6 +23,33 @@ #include "lp.h" +struct distro_series *distro_series_new(const char *name, + const char *version, + const char *title, + const char *displayname) +{ + struct distro_series *d; + + d = malloc(sizeof(struct distro_series)); + + d->name = strdup(name); + d->version = strdup(version); + d->title = strdup(title); + d->displayname = strdup(displayname); + + return d; +} + +void distro_series_free(struct distro_series *d) +{ + if (d) { + free(d->name); + free(d->version); + free(d->title); + free(d->displayname); + } +} + void binary_package_publishing_history_free(struct binary_package_publishing_history *b) { @@ -87,7 +114,8 @@ char *get_archive_url(const char *owner, const char *ppa) struct distro_arch_series *distro_arch_series_new(const char *display_name, const char *title, const char *architecture_tag, - int is_nominated_arch_indep) + int is_nominated_arch_indep, + const char *distroseries_link) { struct distro_arch_series *d; @@ -97,6 +125,7 @@ struct distro_arch_series *distro_arch_series_new(const char *display_name, d->title = strdup(title); d->architecture_tag = strdup(architecture_tag); d->is_nominated_arch_indep = is_nominated_arch_indep; + d->distroseries_link = strdup(distroseries_link); return d; } @@ -106,6 +135,7 @@ void distro_arch_series_free(struct distro_arch_series *d) free(d->display_name); free(d->title); free(d->architecture_tag); + free(d->distroseries_link); free(d); } diff --git a/src/lp.h b/src/lp.h index edb87d3..95415c6 100644 --- a/src/lp.h +++ b/src/lp.h @@ -43,14 +43,31 @@ struct distro_arch_series { char *title; char *architecture_tag; int is_nominated_arch_indep; + char *distroseries_link; }; +struct distro_series { + char *displayname; + char *name; + char *version; + char *title; +}; + +struct distro_series *distro_series_new(const char *name, + const char *version, + const char *title, + const char *displayname); + +void distro_series_free(struct distro_series *distro_series); + void daily_download_total_list_free(struct daily_download_total **); -struct distro_arch_series *distro_arch_series_new(const char *display_name, - const char *title, - const char *architecture_tag, - int is_nominated_arch_indep); +struct distro_arch_series * +distro_arch_series_new(const char *display_name, + const char *title, + const char *architecture_tag, + int is_nominated_arch_indep, + const char *distroseries_link); void distro_arch_series_free(struct distro_arch_series *); diff --git a/src/lp_json.c b/src/lp_json.c index 088d189..1c31ccb 100644 --- a/src/lp_json.c +++ b/src/lp_json.c @@ -58,6 +58,7 @@ struct distro_arch_series *json_object_to_distro_arch_series(json_object *o) const char *title; const char *architecture_tag; boolean is_nominated_arch_indep; + const char *distroseries_link; display_name = json_object_get_string @@ -69,14 +70,44 @@ struct distro_arch_series *json_object_to_distro_arch_series(json_object *o) architecture_tag = json_object_get_string (json_object_object_get(o, "architecture_tag")); + distroseries_link = json_object_get_string + (json_object_object_get(o, "distroseries_link")); + is_nominated_arch_indep = json_object_get_boolean (json_object_object_get(o, "is_nominated_arch_indep")); return distro_arch_series_new(display_name, title, architecture_tag, - is_nominated_arch_indep); + is_nominated_arch_indep, + distroseries_link); } +struct distro_series *json_object_to_distro_series(json_object *o) +{ + const char *displayname; + const char *title; + const char *name; + const char *version; + + displayname = json_object_get_string + (json_object_object_get(o, "displayname")); + + title = json_object_get_string + (json_object_object_get(o, "title")); + + version = json_object_get_string + (json_object_object_get(o, "version")); + + name = json_object_get_string + (json_object_object_get(o, "name")); + + return distro_series_new(name, + version, + title, + displayname); +} + + struct binary_package_publishing_history * * json_object_to_binary_package_publishing_history_list(json_object *o) diff --git a/src/lp_json.h b/src/lp_json.h index 9d40a54..09b6891 100644 --- a/src/lp_json.h +++ b/src/lp_json.h @@ -31,6 +31,7 @@ struct binary_package_publishing_history * * json_object_to_binary_package_publishing_history_list(json_object *o); struct distro_arch_series *json_object_to_distro_arch_series(json_object *o); +struct distro_series *json_object_to_distro_series(json_object *o); struct daily_download_total * * json_object_to_daily_download_totals(json_object *o); diff --git a/src/lp_ws.c b/src/lp_ws.c index a6b95d1..aa6ace7 100644 --- a/src/lp_ws.c +++ b/src/lp_ws.c @@ -23,8 +23,10 @@ #include #include +#include "cache.h" #include "lp_ws.h" #include "lp_json.h" +#include "ppastats.h" #define QUERY_GET_PUBLISHED_BINARIES \ "?ws.op=getPublishedBinaries&status=Published" @@ -59,8 +61,13 @@ static char *fetch_url(const char *url) char *result = NULL; long code; - if (!curl) + if (debug) + printf("DEBUG: fetch_url %s\n", url); + + if (!curl) { + curl_global_init(CURL_GLOBAL_ALL); curl = curl_easy_init(); + } if (!curl) exit(EXIT_FAILURE); @@ -156,10 +163,14 @@ int get_download_count(const char *archive_url) return result; } -struct distro_arch_series *get_distro_arch_series(const char *url) +const struct distro_arch_series *get_distro_arch_series(const char *url) { json_object *obj; - struct distro_arch_series *distro; + const struct distro_arch_series *distro; + + distro = cache_get(url); + if (distro) + return (struct distro_arch_series *)distro; obj = get_json_object(url); @@ -170,6 +181,31 @@ struct distro_arch_series *get_distro_arch_series(const char *url) json_object_put(obj); + cache_put(url, distro, (void (*)(void *))&distro_arch_series_free); + + return distro; +} + +const struct distro_series *get_distro_series(const char *url) +{ + json_object *obj; + const struct distro_series *distro; + + distro = cache_get(url); + if (distro) + return (struct distro_series *)distro; + + obj = get_json_object(url); + + if (!obj) + return NULL; + + distro = json_object_to_distro_series(obj); + + json_object_put(obj); + + cache_put(url, distro, (void (*)(void *))&distro_series_free); + return distro; } @@ -187,11 +223,21 @@ struct daily_download_total **get_daily_download_totals(const char *binary_url) obj = get_json_object(url); - if (obj) + if (obj) { result = json_object_to_daily_download_totals(obj); + json_object_put(obj); + } free(url); - json_object_put(obj); return result; } + +void lp_ws_cleanup() +{ + if (debug) + printf("DEBUG: cleanup CURL\n"); + + curl_easy_cleanup(curl); + curl_global_cleanup(); +} diff --git a/src/lp_ws.h b/src/lp_ws.h index 30d6d75..f4489dc 100644 --- a/src/lp_ws.h +++ b/src/lp_ws.h @@ -27,8 +27,12 @@ get_binary_package_publishing_history_list(const char *archive_url); int get_download_count(const char *archive_url); -struct distro_arch_series *get_distro_arch_series(const char *url); +const struct distro_arch_series *get_distro_arch_series(const char *url); struct daily_download_total **get_daily_download_totals(const char *binary_url); +const struct distro_series *get_distro_series(const char *distro_series_url); + +void lp_ws_cleanup(); + #endif diff --git a/src/main.c b/src/main.c index 0df293d..02861ea 100644 --- a/src/main.c +++ b/src/main.c @@ -22,10 +22,13 @@ #include #include +#include "cache.h" #include "html.h" #include "lp_ws.h" #include "config.h" +#include "ppastats.h" +int debug; static const char *program_name; static void display_published_binaries(const char *owner, const char *ppa) @@ -44,15 +47,18 @@ static void display_published_binaries(const char *owner, const char *ppa) e_cur = list; while (*e_cur) { struct binary_package_publishing_history *binary; - struct distro_arch_series *dist; + const struct distro_arch_series *arch; + const struct distro_series *distro; binary = *e_cur; - dist = get_distro_arch_series(binary->distro_arch_series_link); + arch = get_distro_arch_series(binary->distro_arch_series_link); + distro = get_distro_series(arch->distroseries_link); - printf("%s %s %s %d\n", - dist->display_name, + printf("%s %s %s(%s): %d\n", binary->binary_package_name, binary->binary_package_version, + distro->name, + arch->architecture_tag, get_download_count(binary->self_link)); e_cur++; } @@ -64,6 +70,7 @@ static struct option long_options[] = { {"version", no_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}, {"html", no_argument, 0, 't'}, + {"debug", no_argument, 0, 'd'}, {0, 0, 0, 0} }; @@ -117,12 +124,15 @@ int main(int argc, char **argv) program_name = argv[0]; - while ((optc = getopt_long(argc, argv, "vht", long_options, + while ((optc = getopt_long(argc, argv, "vhtd", long_options, NULL)) != -1) { switch (optc) { case 't': output_html = 1; break; + case 'd': + debug = 1; + break; case 'h': print_help(); exit(EXIT_SUCCESS); @@ -149,5 +159,9 @@ int main(int argc, char **argv) else display_published_binaries(owner, ppa); + /* for valgrind.... */ + lp_ws_cleanup(); + cache_cleanup(); + exit(EXIT_SUCCESS); } diff --git a/src/ppastats.h b/src/ppastats.h new file mode 100644 index 0000000..4eabf01 --- /dev/null +++ b/src/ppastats.h @@ -0,0 +1,25 @@ +/* + Copyright (C) 2011 jeanfi@gmail.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA +*/ + +#ifndef _PPASTATS_PPASTATS_H_ +#define _PPASTATS_PPASTATS_H_ + +extern int debug; + +#endif -- 2.7.4