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
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)
$(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
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@
--- /dev/null
+/*
+ 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+/*
+ 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);
+ }
+}
--- /dev/null
+/*
+ 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
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;
}
daily_download_total_list_free(totals);
- distro_arch_series_free(dist);
}
str = strdup(json_object_to_json_string(data));
#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)
{
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;
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;
}
free(d->display_name);
free(d->title);
free(d->architecture_tag);
+ free(d->distroseries_link);
free(d);
}
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 *);
const char *title;
const char *architecture_tag;
boolean is_nominated_arch_indep;
+ const char *distroseries_link;
display_name = json_object_get_string
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)
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);
#include <curl/curl.h>
#include <json/json.h>
+#include "cache.h"
#include "lp_ws.h"
#include "lp_json.h"
+#include "ppastats.h"
#define QUERY_GET_PUBLISHED_BINARIES \
"?ws.op=getPublishedBinaries&status=Published"
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);
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);
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;
}
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();
+}
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
#include <stdio.h>
#include <string.h>
+#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)
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++;
}
{"version", no_argument, 0, 'v'},
{"help", no_argument, 0, 'h'},
{"html", no_argument, 0, 't'},
+ {"debug", no_argument, 0, 'd'},
{0, 0, 0, 0}
};
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);
else
display_published_binaries(owner, ppa);
+ /* for valgrind.... */
+ lp_ws_cleanup();
+ cache_cleanup();
+
exit(EXIT_SUCCESS);
}
--- /dev/null
+/*
+ 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