Revision 1913
| trunk/nntpgrab_core/nntpgrab_plugin.h (revision 1913) | ||
|---|---|---|
| 27 | 27 |
|
| 28 | 28 |
G_BEGIN_DECLS |
| 29 | 29 |
|
| 30 |
#define NNTPGRAB_PLUGIN_API_VERSION 20111121 |
|
| 30 |
#define NNTPGRAB_PLUGIN_API_VERSION 20111201 |
|
| 31 | 31 |
|
| 32 | 32 |
typedef enum {
|
| 33 | 33 |
NNTP_ERROR_NONE, |
| ... | ... | |
| 67 | 67 |
* @config_save: Save the configuration to disk |
| 68 | 68 |
* @config_get_folder_listing: Retrieve a list containing all the sub-folders which are in the given folder. Needs to be free'd using config_free_folder_listing |
| 69 | 69 |
* @config_free_folder_listing: Free a list of sub-folders |
| 70 |
* @config_get_config_folder: Retrieve the folder where all configuration files can be stored. Needs to be free'd using ng_free |
|
| 70 | 71 |
* @schedular_start: Start the schedular |
| 71 | 72 |
* @schedular_stop: Stop the schedular |
| 72 | 73 |
* @schedular_get_state: Retrieve the current state of the schedular |
| ... | ... | |
| 101 | 102 |
NGConfigOpts (*config_get_opts) (void); |
| 102 | 103 |
void (*config_set_opts) (NGConfigOpts opts); |
| 103 | 104 |
ngboolean (*config_save) (char **errmsg); |
| 105 |
char *(*config_get_config_folder) (void); |
|
| 104 | 106 |
ngboolean (*schedular_start) (void); |
| 105 | 107 |
ngboolean (*schedular_stop) (const char *reason, ngboolean wait); |
| 106 | 108 |
NGSchedularState (*schedular_get_state) (void); |
| trunk/nntpgrab_core/configuration.c (revision 1913) | ||
|---|---|---|
| 564 | 564 |
} |
| 565 | 565 |
|
| 566 | 566 |
/** |
| 567 |
* configuration_get_config_folder: |
|
| 568 |
* |
|
| 569 |
* Retrieve the folder where all configuration files can be stored |
|
| 570 |
* |
|
| 571 |
* Returns: The folder where all configuration files can be stored. Needs to be g_free'd after use |
|
| 572 |
*/ |
|
| 573 |
char * |
|
| 574 |
configuration_get_config_folder(void) |
|
| 575 |
{
|
|
| 576 |
if (g_getenv("NNTPGRAB_CONFIG_DIR")) {
|
|
| 577 |
return g_build_path(G_DIR_SEPARATOR_S, g_getenv("NNTPGRAB_CONFIG_DIR"), "NNTPGrab", NULL);
|
|
| 578 |
} else {
|
|
| 579 |
return g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), "NNTPGrab", NULL); |
|
| 580 |
} |
|
| 581 |
} |
|
| 582 |
|
|
| 583 |
/** |
|
| 567 | 584 |
* Load all settings from a local file on the harddrive |
| 568 | 585 |
* |
| 569 | 586 |
* @param obj The configuration object |
| ... | ... | |
| 576 | 593 |
Configuration *config = CONFIGURATION(obj); |
| 577 | 594 |
GKeyFile *keyfile; |
| 578 | 595 |
GError *err = NULL; |
| 596 |
char *config_folder; |
|
| 579 | 597 |
char *filename; |
| 580 | 598 |
char **groups; |
| 581 | 599 |
int i; |
| ... | ... | |
| 583 | 601 |
|
| 584 | 602 |
g_static_rw_lock_writer_lock(&config->rwlock); |
| 585 | 603 |
|
| 586 |
// Free the already known settings |
|
| 604 |
/* Free the already known settings */ |
|
| 587 | 605 |
list = config->servers; |
| 588 | 606 |
while (list) {
|
| 589 | 607 |
NGConfigServer *server = list->data; |
| ... | ... | |
| 596 | 614 |
g_list_free(config->servers); |
| 597 | 615 |
config->servers = NULL; |
| 598 | 616 |
|
| 599 |
// Try to load the config file |
|
| 600 |
if (g_getenv("NNTPGRAB_CONFIG_DIR")) {
|
|
| 601 |
filename = g_build_filename(g_getenv("NNTPGRAB_CONFIG_DIR"), "NNTPGrab", "nntpgrab.conf", NULL);
|
|
| 602 |
} else {
|
|
| 603 |
filename = g_build_filename(g_get_user_config_dir(), "NNTPGrab", "nntpgrab.conf", NULL); |
|
| 604 |
} |
|
| 617 |
/* Try to load the config file */ |
|
| 618 |
config_folder = configuration_get_config_folder(); |
|
| 619 |
filename = g_build_filename(config_folder, "nntpgrab.conf", NULL); |
|
| 620 |
g_free(config_folder); |
|
| 621 |
|
|
| 605 | 622 |
keyfile = g_key_file_new(); |
| 606 | 623 |
if (!g_key_file_load_from_file(keyfile, filename, G_KEY_FILE_NONE, &err)) {
|
| 607 | 624 |
char *tmp; |
| ... | ... | |
| 907 | 924 |
Configuration *config = CONFIGURATION(obj); |
| 908 | 925 |
GKeyFile *keyfile; |
| 909 | 926 |
GError *err = NULL; |
| 927 |
char *config_folder; |
|
| 910 | 928 |
char *filename; |
| 911 |
char *dirname; |
|
| 912 | 929 |
char *contents; |
| 913 | 930 |
GList *list; |
| 914 |
const char *config_dir; |
|
| 915 | 931 |
|
| 916 | 932 |
g_static_rw_lock_reader_lock(&config->rwlock); |
| 917 | 933 |
|
| ... | ... | |
| 965 | 981 |
return FALSE; |
| 966 | 982 |
} |
| 967 | 983 |
|
| 968 |
// Create the folder ~/.config/NNTPGrab if it didn't exist already |
|
| 969 |
if (g_getenv("NNTPGRAB_CONFIG_DIR")) {
|
|
| 970 |
config_dir = g_getenv("NNTPGRAB_CONFIG_DIR");
|
|
| 971 |
} else {
|
|
| 972 |
config_dir = g_get_user_config_dir(); |
|
| 973 |
} |
|
| 984 |
/* Create the folder ~/.config/NNTPGrab if it didn't exist already */ |
|
| 985 |
config_folder = configuration_get_config_folder(); |
|
| 986 |
g_mkdir_with_parents(config_folder, 0700); |
|
| 974 | 987 |
|
| 975 |
dirname = g_build_path(G_DIR_SEPARATOR_S, config_dir, "NNTPGrab", NULL); |
|
| 976 |
g_mkdir_with_parents(dirname, 0700); |
|
| 977 |
g_free(dirname); |
|
| 988 |
/* Write the configuration to disk */ |
|
| 989 |
filename = g_build_filename(config_folder, "nntpgrab.conf", NULL); |
|
| 990 |
g_free(config_folder); |
|
| 978 | 991 |
|
| 979 |
filename = g_build_filename(config_dir, "NNTPGrab", "nntpgrab.conf", NULL); |
|
| 980 |
|
|
| 981 | 992 |
if (!g_file_set_contents(filename, contents, -1, &err)) {
|
| 982 | 993 |
if (errmsg) {
|
| 983 | 994 |
*errmsg = g_strdup_printf(_("configuration_save(): Error while opening file '%s'\n%s"), filename, err->message);
|
| trunk/nntpgrab_core/configuration.h (revision 1913) | ||
|---|---|---|
| 46 | 46 |
void configuration_set_newsgroup_info(Configuration *obj, const char *servername, const char *newsgroup, ConfigGroupInfo info); |
| 47 | 47 |
NGConfigOpts configuration_get_opts(Configuration *obj); |
| 48 | 48 |
void configuration_set_opts(Configuration *obj, NGConfigOpts opts); |
| 49 |
char *configuration_get_config_folder(void); |
|
| 49 | 50 |
gboolean configuration_load(Configuration *config, char **errmsg); |
| 50 | 51 |
gboolean configuration_save(Configuration *config, char **errmsg); |
| 51 | 52 |
|
| trunk/nntpgrab_core/plugins.c (revision 1913) | ||
|---|---|---|
| 212 | 212 |
obj->core_funcs.config_get_opts = config_get_opts_wrapper; |
| 213 | 213 |
obj->core_funcs.config_set_opts = config_set_opts_wrapper; |
| 214 | 214 |
obj->core_funcs.config_save = config_save_wrapper; |
| 215 |
obj->core_funcs.config_get_config_folder = configuration_get_config_folder; |
|
| 215 | 216 |
obj->core_funcs.schedular_start = schedular_start_wrapper; |
| 216 | 217 |
obj->core_funcs.schedular_stop = schedular_stop_wrapper; |
| 217 | 218 |
obj->core_funcs.schedular_get_state = download_thread_get_state; |
| trunk/plugins/counter/plugin_counter.c (revision 1913) | ||
|---|---|---|
| 17 | 17 |
*/ |
| 18 | 18 |
|
| 19 | 19 |
#include |
| 20 |
#include |
|
| 20 | 21 |
#include "nntpgrab_plugin.h" |
| 22 |
#include "nntpgrab_utils.h" |
|
| 21 | 23 |
#include "config.h" |
| 22 | 24 |
|
| 23 |
static void config_changed_cb(NGPlugin *plugin_data, gpointer data); |
|
| 24 |
static void part_done_cb(NGPlugin *plugin_data, const char *servername, int conn_id, const char *collection_name, const char *subject, int part_num, int size, gpointer data); |
|
| 25 |
typedef struct _counter_server_data {
|
|
| 26 |
NGConfigServer server_info; |
|
| 27 |
guint64 num_bytes_downloaded; |
|
| 28 |
guint64 num_parts_succeeded; |
|
| 29 |
guint64 num_parts_failed; |
|
| 30 |
} CounterServerData; |
|
| 25 | 31 |
|
| 32 |
typedef struct _counter_data {
|
|
| 33 |
time_t stamp_started; |
|
| 34 |
gboolean data_changed_since_last_announce; |
|
| 35 |
GList *collected_data; /* List contains CounterServerData elements */ |
|
| 36 |
} CounterData; |
|
| 37 |
|
|
| 38 |
static void plugin_counter_free_cached_data(NGPlugin *plugin_data); |
|
| 39 |
static gboolean plugin_counter_load_cached_data(NGPlugin *plugin_data, char **errmsg); |
|
| 40 |
static gboolean plugin_counter_save_cached_data(NGPlugin *plugin_data, char **errmsg); |
|
| 41 |
static gboolean plugin_counter_send_update_announcement(gpointer data); |
|
| 42 |
static CounterServerData *plugin_counter_lookup_server(NGPlugin *plugin_data, const char *servername); |
|
| 43 |
static void plugin_counter_part_done_cb(NGPlugin *plugin_data, const char *servername, int conn_id, const char *collection_name, const char *subject, int part_num, int size, gpointer data); |
|
| 44 |
static void plugin_counter_part_failed_cb(NGPlugin *plugin_data, const char *servername, int conn_id, const char *collection_name, const char *subject, int part_num,int size, gboolean all_servers_tried); |
|
| 45 |
|
|
| 26 | 46 |
void |
| 27 | 47 |
nntpgrab_plugin_initialize(NGPlugin *plugin_data) |
| 28 | 48 |
{
|
| ... | ... | |
| 32 | 52 |
ng_plugin_set_url(plugin_data, "https://www.nntpgrab.nl"); |
| 33 | 53 |
ng_plugin_set_description(plugin_data, "Count the amount of download traffic for each configured usenet server "); |
| 34 | 54 |
|
| 35 |
ng_plugin_set_required_event(plugin_data, "config_changed"); |
|
| 55 |
ng_plugin_create_event(plugin_data, "counter_data_changed", 0); |
|
| 56 |
|
|
| 36 | 57 |
ng_plugin_set_required_event(plugin_data, "part_done"); |
| 58 |
ng_plugin_set_required_event(plugin_data, "part_failed"); |
|
| 37 | 59 |
} |
| 38 | 60 |
|
| 39 | 61 |
ngboolean |
| 40 | 62 |
nntpgrab_plugin_load(NGPlugin *plugin_data, char **errmsg) |
| 41 | 63 |
{
|
| 42 |
ng_plugin_connect_event(plugin_data, "config_changed", NG_PLUGIN_FUNCTION(config_changed_cb), NULL); |
|
| 43 |
ng_plugin_connect_event(plugin_data, "part_done", NG_PLUGIN_FUNCTION(part_done_cb), NULL); |
|
| 64 |
ng_plugin_connect_event(plugin_data, "part_done", NG_PLUGIN_FUNCTION(plugin_counter_part_done_cb), NULL); |
|
| 65 |
ng_plugin_connect_event(plugin_data, "part_failed", NG_PLUGIN_FUNCTION(plugin_counter_part_failed_cb), NULL); |
|
| 44 | 66 |
|
| 67 |
plugin_data->priv = g_slice_new0(CounterData); |
|
| 68 |
|
|
| 69 |
if (!plugin_counter_load_cached_data(plugin_data, errmsg)) {
|
|
| 70 |
return FALSE; |
|
| 71 |
} |
|
| 72 |
|
|
| 73 |
/* Make sure the plugin sends update announcements every 10 seconds */ |
|
| 74 |
g_timeout_add_seconds(10, plugin_counter_send_update_announcement, plugin_data); |
|
| 75 |
plugin_counter_send_update_announcement(plugin_data); |
|
| 76 |
|
|
| 45 | 77 |
return TRUE; |
| 46 | 78 |
} |
| 47 | 79 |
|
| ... | ... | |
| 54 | 86 |
void |
| 55 | 87 |
nntpgrab_plugin_unload(NGPlugin *plugin_data) |
| 56 | 88 |
{
|
| 89 |
char *errmsg = NULL; |
|
| 90 |
|
|
| 91 |
if (!plugin_counter_save_cached_data(plugin_data, &errmsg)) {
|
|
| 92 |
ng_plugin_emit_log_msg(plugin_data, NG_LOG_LEVEL_WARNING, errmsg); |
|
| 93 |
g_free(errmsg); |
|
| 94 |
} |
|
| 95 |
|
|
| 96 |
plugin_counter_free_cached_data(plugin_data); |
|
| 97 |
|
|
| 98 |
g_slice_free(CounterData, plugin_data->priv); |
|
| 99 |
plugin_data->priv = NULL; |
|
| 57 | 100 |
} |
| 58 | 101 |
|
| 59 | 102 |
void |
| ... | ... | |
| 67 | 110 |
return NNTPGRAB_PLUGIN_API_VERSION; |
| 68 | 111 |
} |
| 69 | 112 |
|
| 113 |
static NGVariant * |
|
| 114 |
get_collected_data(NGPlugin *plugin_data, NGVariant *parameters, char **errmsg) |
|
| 115 |
{
|
|
| 116 |
GVariant *variant_counter; |
|
| 117 |
GVariant *variant_servers; |
|
| 118 |
GVariantBuilder *builder_counter; |
|
| 119 |
GVariantBuilder *builder_servers; |
|
| 120 |
CounterData *counter_data; |
|
| 121 |
NGList *servers; |
|
| 122 |
NGList *list; |
|
| 123 |
|
|
| 124 |
g_return_if_fail(plugin_data != NULL); |
|
| 125 |
|
|
| 126 |
counter_data = (CounterData*) plugin_data->priv; |
|
| 127 |
|
|
| 128 |
g_return_if_fail(counter_data != NULL); |
|
| 129 |
|
|
| 130 |
builder_counter = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
|
|
| 131 |
g_variant_builder_add(builder_counter, "{sv}", "stamp_started", g_variant_new_uint64((guint64) counter_data->stamp_started));
|
|
| 132 |
|
|
| 133 |
builder_servers = g_variant_builder_new(G_VARIANT_TYPE("av"));
|
|
| 134 |
|
|
| 135 |
servers = plugin_data->core_funcs.config_get_avail_servers(); |
|
| 136 |
list = servers; |
|
| 137 |
while (list) {
|
|
| 138 |
const char *servername = (const char*) list->data; |
|
| 139 |
GVariant *variant_server; |
|
| 140 |
GVariantBuilder *builder_server; |
|
| 141 |
CounterServerData *server_data; |
|
| 142 |
|
|
| 143 |
server_data = plugin_counter_lookup_server(plugin_data, servername); |
|
| 144 |
|
|
| 145 |
g_return_val_if_fail(server_data != NULL, NULL); |
|
| 146 |
|
|
| 147 |
builder_server = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
|
|
| 148 |
g_variant_builder_add(builder_server, "{sv}", "servername", g_variant_new_string(server_data->server_info.servername));
|
|
| 149 |
g_variant_builder_add(builder_server, "{sv}", "num_bytes_downloaded", g_variant_new_uint64(server_data->num_bytes_downloaded));
|
|
| 150 |
g_variant_builder_add(builder_server, "{sv}", "num_parts_succeeded", g_variant_new_uint64(server_data->num_parts_succeeded));
|
|
| 151 |
g_variant_builder_add(builder_server, "{sv}", "num_parts_failed", g_variant_new_uint64(server_data->num_parts_failed));
|
|
| 152 |
variant_server = g_variant_builder_end(builder_server); |
|
| 153 |
|
|
| 154 |
g_variant_builder_add(builder_servers, "v", variant_server); |
|
| 155 |
|
|
| 156 |
list = ng_list_next(list); |
|
| 157 |
} |
|
| 158 |
|
|
| 159 |
variant_servers = g_variant_builder_end(builder_servers); |
|
| 160 |
g_variant_builder_add(builder_counter, "{sv}", "collected_data", variant_servers);
|
|
| 161 |
|
|
| 162 |
plugin_data->core_funcs.config_free_avail_servers(servers); |
|
| 163 |
|
|
| 164 |
variant_counter = g_variant_builder_end(builder_counter); |
|
| 165 |
return (NGVariant*) variant_counter; |
|
| 166 |
} |
|
| 167 |
|
|
| 168 |
static NGVariant * |
|
| 169 |
reset_collected_data(NGPlugin *plugin_data, NGVariant *parameters, char **errmsg) |
|
| 170 |
{
|
|
| 171 |
plugin_counter_free_cached_data(plugin_data); |
|
| 172 |
|
|
| 173 |
/* Manually emit an update announcement so that all frontends |
|
| 174 |
* will know that the collected data was reset */ |
|
| 175 |
plugin_counter_send_update_announcement(plugin_data); |
|
| 176 |
|
|
| 177 |
return (NGVariant*) g_variant_new_boolean(TRUE); |
|
| 178 |
} |
|
| 179 |
|
|
| 70 | 180 |
NGVariant * |
| 71 | 181 |
nntpgrab_plugin_call_plugin_method(NGPlugin *plugin_data, const char *method, NGVariant *parameters, char **errmsg) |
| 72 | 182 |
{
|
| 73 |
return NULL; |
|
| 183 |
if (!g_strcmp0(method, "get_collected_data")) {
|
|
| 184 |
return get_collected_data(plugin_data, parameters, errmsg); |
|
| 185 |
} else if (!g_strcmp0(method, "reset")) {
|
|
| 186 |
return reset_collected_data(plugin_data, parameters, errmsg); |
|
| 187 |
} else {
|
|
| 188 |
return NULL; |
|
| 189 |
} |
|
| 74 | 190 |
} |
| 75 | 191 |
|
| 76 | 192 |
static void |
| 77 |
config_changed_cb(NGPlugin *plugin_data, gpointer data) |
|
| 193 |
plugin_counter_free_cached_data(NGPlugin *plugin_data) |
|
| 78 | 194 |
{
|
| 79 |
/* Make sure all our cached servers are still part of the NNTPGrab configuration */ |
|
| 195 |
CounterData *counter_data; |
|
| 196 |
GList *list; |
|
| 80 | 197 |
|
| 198 |
g_return_if_fail(plugin_data != NULL); |
|
| 199 |
|
|
| 200 |
counter_data = (CounterData*) plugin_data->priv; |
|
| 201 |
|
|
| 202 |
g_return_if_fail(counter_data != NULL); |
|
| 203 |
|
|
| 204 |
list = counter_data->collected_data; |
|
| 205 |
while (list) {
|
|
| 206 |
CounterServerData *server_data = (CounterServerData*) list->data; |
|
| 207 |
|
|
| 208 |
g_slice_free(CounterServerData, server_data); |
|
| 209 |
|
|
| 210 |
list = g_list_next(list); |
|
| 211 |
} |
|
| 212 |
|
|
| 213 |
g_list_free(counter_data->collected_data); |
|
| 214 |
counter_data->collected_data = NULL; |
|
| 215 |
counter_data->stamp_started = time(NULL); |
|
| 216 |
|
|
| 217 |
counter_data->data_changed_since_last_announce = TRUE; |
|
| 81 | 218 |
} |
| 82 | 219 |
|
| 220 |
static gboolean |
|
| 221 |
plugin_counter_load_cached_data(NGPlugin *plugin_data, char **errmsg) |
|
| 222 |
{
|
|
| 223 |
CounterData *counter_data; |
|
| 224 |
GKeyFile *keyfile; |
|
| 225 |
char *config_dir; |
|
| 226 |
char *filename; |
|
| 227 |
GError *err = NULL; |
|
| 228 |
char **groups; |
|
| 229 |
int i; |
|
| 230 |
|
|
| 231 |
g_return_val_if_fail(plugin_data != NULL, FALSE); |
|
| 232 |
g_return_val_if_fail(errmsg != NULL, FALSE); |
|
| 233 |
|
|
| 234 |
counter_data = (CounterData*) plugin_data->priv; |
|
| 235 |
|
|
| 236 |
g_return_if_fail(counter_data != NULL); |
|
| 237 |
|
|
| 238 |
counter_data->stamp_started = time(NULL); |
|
| 239 |
|
|
| 240 |
config_dir = plugin_data->core_funcs.config_get_config_folder(); |
|
| 241 |
g_return_val_if_fail(config_dir != NULL, FALSE); |
|
| 242 |
|
|
| 243 |
filename = g_build_filename(config_dir, "plugin_counter.conf", NULL); |
|
| 244 |
ng_free(config_dir); |
|
| 245 |
|
|
| 246 |
if (!g_file_test(filename, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
|
|
| 247 |
/* No cached configuration file exists yet */ |
|
| 248 |
return TRUE; |
|
| 249 |
} |
|
| 250 |
|
|
| 251 |
/* Clean up old entries */ |
|
| 252 |
plugin_counter_free_cached_data(plugin_data); |
|
| 253 |
|
|
| 254 |
/* Load the contents of the configuration file from disk */ |
|
| 255 |
keyfile = g_key_file_new(); |
|
| 256 |
if (!g_key_file_load_from_file(keyfile, filename, G_KEY_FILE_NONE, &err)) {
|
|
| 257 |
*errmsg = g_strdup_printf("Unable to load file '%s': %s", filename, err->message);
|
|
| 258 |
g_error_free(err); |
|
| 259 |
g_free(filename); |
|
| 260 |
return FALSE; |
|
| 261 |
} |
|
| 262 |
g_free(filename); |
|
| 263 |
|
|
| 264 |
groups = g_key_file_get_groups(keyfile, NULL); |
|
| 265 |
i = 0; |
|
| 266 |
while (groups && groups[i] != NULL) {
|
|
| 267 |
CounterServerData *server_data; |
|
| 268 |
NGConfigServer server_info; |
|
| 269 |
|
|
| 270 |
/* Only read the stamp_started key from the generic group */ |
|
| 271 |
if (!g_strcmp0(groups[i], "generic")) {
|
|
| 272 |
if (!g_key_file_has_key(keyfile, groups[i], "stamp_started", NULL)) {
|
|
| 273 |
counter_data->stamp_started = time(NULL); |
|
| 274 |
} else {
|
|
| 275 |
counter_data->stamp_started = (time_t) g_key_file_get_uint64(keyfile, groups[i], "stamp_started", NULL); |
|
| 276 |
} |
|
| 277 |
|
|
| 278 |
i++; |
|
| 279 |
continue; |
|
| 280 |
} |
|
| 281 |
|
|
| 282 |
if (!g_key_file_has_key(keyfile, groups[i], "num_bytes_downloaded", NULL) || |
|
| 283 |
!g_key_file_has_key(keyfile, groups[i], "num_parts_succeeded", NULL) || |
|
| 284 |
!g_key_file_has_key(keyfile, groups[i], "num_parts_failed", NULL)) {
|
|
| 285 |
|
|
| 286 |
/* One or more keys weren't found */ |
|
| 287 |
ng_plugin_emit_log_msg(plugin_data, NG_LOG_LEVEL_INFO, "Server named '%s' was found in counter plugin configuration file, but is missing some keys", groups[i]); |
|
| 288 |
i++; |
|
| 289 |
continue; |
|
| 290 |
} |
|
| 291 |
|
|
| 292 |
/* All required keys are found */ |
|
| 293 |
|
|
| 294 |
if (!plugin_data->core_funcs.config_get_server_info(groups[i], &server_info)) {
|
|
| 295 |
/* Server doesn't exist in current NNTPGrab configuration */ |
|
| 296 |
ng_plugin_emit_log_msg(plugin_data, NG_LOG_LEVEL_INFO, "Server named '%s' was found in counter plugin configuration file, but isn't known in the NNTPGrab configuration", groups[i]); |
|
| 297 |
i++; |
|
| 298 |
continue; |
|
| 299 |
} |
|
| 300 |
|
|
| 301 |
server_data = g_slice_new0(CounterServerData); |
|
| 302 |
|
|
| 303 |
server_data->server_info = server_info; |
|
| 304 |
server_data->num_bytes_downloaded = g_key_file_get_uint64(keyfile, groups[i], "num_bytes_downloaded", NULL); |
|
| 305 |
server_data->num_parts_succeeded = g_key_file_get_uint64(keyfile, groups[i], "num_parts_succeeded", NULL); |
|
| 306 |
server_data->num_parts_failed = g_key_file_get_uint64(keyfile, groups[i], "num_parts_failed", NULL); |
|
| 307 |
|
|
| 308 |
counter_data->collected_data = g_list_append(counter_data->collected_data, server_data); |
|
| 309 |
|
|
| 310 |
i++; |
|
| 311 |
} |
|
| 312 |
|
|
| 313 |
g_key_file_free(keyfile); |
|
| 314 |
|
|
| 315 |
return TRUE; |
|
| 316 |
} |
|
| 317 |
|
|
| 318 |
static gboolean |
|
| 319 |
plugin_counter_save_cached_data(NGPlugin *plugin_data, char **errmsg) |
|
| 320 |
{
|
|
| 321 |
GKeyFile *keyfile; |
|
| 322 |
char *config_dir; |
|
| 323 |
char *filename; |
|
| 324 |
GError *err = NULL; |
|
| 325 |
CounterData *counter_data = (CounterData*) plugin_data->priv; |
|
| 326 |
GList *list; |
|
| 327 |
char *contents; |
|
| 328 |
|
|
| 329 |
g_return_val_if_fail(plugin_data != NULL, FALSE); |
|
| 330 |
g_return_val_if_fail(errmsg != NULL, FALSE); |
|
| 331 |
g_return_val_if_fail(counter_data != NULL, FALSE); |
|
| 332 |
|
|
| 333 |
keyfile = g_key_file_new(); |
|
| 334 |
|
|
| 335 |
g_key_file_set_uint64(keyfile, "generic", "stamp_started", (guint64) counter_data->stamp_started); |
|
| 336 |
|
|
| 337 |
list = counter_data->collected_data; |
|
| 338 |
while (list) {
|
|
| 339 |
CounterServerData *server_data = (CounterServerData*) list->data; |
|
| 340 |
|
|
| 341 |
g_key_file_set_uint64(keyfile, server_data->server_info.servername, "num_bytes_downloaded", server_data->num_bytes_downloaded); |
|
| 342 |
g_key_file_set_uint64(keyfile, server_data->server_info.servername, "num_parts_succeeded", server_data->num_parts_succeeded); |
|
| 343 |
g_key_file_set_uint64(keyfile, server_data->server_info.servername, "num_parts_failed", server_data->num_parts_failed); |
|
| 344 |
|
|
| 345 |
list = g_list_next(list); |
|
| 346 |
} |
|
| 347 |
|
|
| 348 |
contents = g_key_file_to_data(keyfile, NULL, &err); |
|
| 349 |
if (!contents) {
|
|
| 350 |
*errmsg = g_strdup(err->message); |
|
| 351 |
g_error_free(err); |
|
| 352 |
g_free(contents); |
|
| 353 |
g_key_file_free(keyfile); |
|
| 354 |
|
|
| 355 |
return FALSE; |
|
| 356 |
} |
|
| 357 |
|
|
| 358 |
/* Write the configuration to disk */ |
|
| 359 |
config_dir = plugin_data->core_funcs.config_get_config_folder(); |
|
| 360 |
g_return_val_if_fail(config_dir != NULL, FALSE); |
|
| 361 |
filename = g_build_filename(config_dir, "plugin_counter.conf", NULL); |
|
| 362 |
g_free(config_dir); |
|
| 363 |
|
|
| 364 |
if (!g_file_set_contents(filename, contents, -1, &err)) {
|
|
| 365 |
*errmsg = g_strdup_printf("Error while saving download counter configuration to file '%s'\n%s", filename, err->message);
|
|
| 366 |
g_error_free(err); |
|
| 367 |
g_free(contents); |
|
| 368 |
g_free(filename); |
|
| 369 |
g_key_file_free(keyfile); |
|
| 370 |
|
|
| 371 |
return FALSE; |
|
| 372 |
} |
|
| 373 |
|
|
| 374 |
g_free(contents); |
|
| 375 |
g_free(filename); |
|
| 376 |
g_key_file_free(keyfile); |
|
| 377 |
|
|
| 378 |
return TRUE; |
|
| 379 |
} |
|
| 380 |
|
|
| 381 |
static gboolean |
|
| 382 |
plugin_counter_send_update_announcement(gpointer data) |
|
| 383 |
{
|
|
| 384 |
static int times_been_here = 0; |
|
| 385 |
CounterData *counter_data; |
|
| 386 |
NGPlugin *plugin_data = (NGPlugin*) data; |
|
| 387 |
|
|
| 388 |
g_return_val_if_fail(plugin_data != NULL, FALSE); |
|
| 389 |
g_return_val_if_fail(plugin_data->priv != NULL, FALSE); |
|
| 390 |
|
|
| 391 |
counter_data = (CounterData*) plugin_data->priv; |
|
| 392 |
|
|
| 393 |
/* Only send a new announcement when something got changed */ |
|
| 394 |
if (!counter_data->data_changed_since_last_announce) {
|
|
| 395 |
return TRUE; |
|
| 396 |
} |
|
| 397 |
|
|
| 398 |
ng_plugin_emit_event(plugin_data, "counter_data_changed", NULL); |
|
| 399 |
counter_data->data_changed_since_last_announce = FALSE; |
|
| 400 |
|
|
| 401 |
/* Periodically (every 60 seconds) save the cached data back to disk */ |
|
| 402 |
if (times_been_here % 6 == 0) {
|
|
| 403 |
char *errmsg = NULL; |
|
| 404 |
|
|
| 405 |
if (!plugin_counter_save_cached_data(plugin_data, &errmsg)) {
|
|
| 406 |
ng_plugin_emit_log_msg(plugin_data, NG_LOG_LEVEL_WARNING, errmsg); |
|
| 407 |
g_free(errmsg); |
|
| 408 |
} |
|
| 409 |
} |
|
| 410 |
times_been_here++; |
|
| 411 |
|
|
| 412 |
return TRUE; |
|
| 413 |
} |
|
| 414 |
|
|
| 415 |
static CounterServerData* |
|
| 416 |
plugin_counter_lookup_server(NGPlugin *plugin_data, const char *servername) |
|
| 417 |
{
|
|
| 418 |
CounterData *counter_data; |
|
| 419 |
CounterServerData *server_data; |
|
| 420 |
GList *list; |
|
| 421 |
|
|
| 422 |
g_return_val_if_fail(plugin_data != NULL, NULL); |
|
| 423 |
g_return_val_if_fail(servername != NULL, NULL); |
|
| 424 |
g_return_val_if_fail(plugin_data->priv != NULL, NULL); |
|
| 425 |
|
|
| 426 |
counter_data = (CounterData*) plugin_data->priv; |
|
| 427 |
|
|
| 428 |
list = counter_data->collected_data; |
|
| 429 |
while (list) {
|
|
| 430 |
server_data = list->data; |
|
| 431 |
|
|
| 432 |
g_return_val_if_fail(server_data != NULL, NULL); |
|
| 433 |
|
|
| 434 |
if (!g_strcmp0(server_data->server_info.servername, servername)) {
|
|
| 435 |
return server_data; |
|
| 436 |
} |
|
| 437 |
|
|
| 438 |
list = g_list_next(list); |
|
| 439 |
} |
|
| 440 |
|
|
| 441 |
/* If we got here then there's no entry available for this server. Add it now */ |
|
| 442 |
server_data = g_slice_new0(CounterServerData); |
|
| 443 |
g_return_val_if_fail(plugin_data->core_funcs.config_get_server_info(servername, &server_data->server_info), NULL); |
|
| 444 |
|
|
| 445 |
server_data->num_bytes_downloaded = 0; |
|
| 446 |
server_data->num_parts_succeeded = 0; |
|
| 447 |
server_data->num_parts_failed = 0; |
|
| 448 |
|
|
| 449 |
counter_data->collected_data = g_list_append(counter_data->collected_data, server_data); |
|
| 450 |
|
|
| 451 |
return server_data; |
|
| 452 |
} |
|
| 453 |
|
|
| 83 | 454 |
static void |
| 84 |
part_done_cb(NGPlugin *plugin_data, const char *servername, int conn_id, const char *collection_name, const char *subject, int part_num, int size, gpointer data) |
|
| 455 |
plugin_counter_part_done_cb(NGPlugin *plugin_data, const char *servername, int conn_id, const char *collection_name, const char *subject, int part_num, int size, gpointer data) |
|
| 85 | 456 |
{
|
| 457 |
CounterData *counter_data; |
|
| 458 |
CounterServerData *server_data; |
|
| 459 |
|
|
| 86 | 460 |
/* We only process the part_done event as this is the only event which contains both |
| 87 | 461 |
* the servername and the size of the part. The event traffic_monitor_update contains |
| 88 | 462 |
* a more reliable amount of traffic transferred, but doesn't show the per-server |
| ... | ... | |
| 91 | 465 |
* When only processing this event we will lose some traffic data (for missing parts |
| 92 | 466 |
* for example) but that amount of traffic should be low so it should be okay to |
| 93 | 467 |
* ignore that type of traffic */ |
| 468 |
g_return_if_fail(plugin_data != NULL); |
|
| 469 |
g_return_if_fail(servername != NULL); |
|
| 470 |
g_return_if_fail(size >= 0); |
|
| 471 |
g_return_if_fail(plugin_data->priv != NULL); |
|
| 94 | 472 |
|
| 473 |
counter_data = (CounterData*) plugin_data->priv; |
|
| 474 |
server_data = plugin_counter_lookup_server(plugin_data, servername); |
|
| 95 | 475 |
|
| 476 |
g_return_if_fail(server_data != NULL); |
|
| 477 |
|
|
| 478 |
counter_data->data_changed_since_last_announce = TRUE; |
|
| 479 |
server_data->num_bytes_downloaded += size; |
|
| 480 |
server_data->num_parts_succeeded++; |
|
| 96 | 481 |
} |
| 482 |
|
|
| 483 |
static void |
|
| 484 |
plugin_counter_part_failed_cb(NGPlugin *plugin_data, const char *servername, int conn_id, const char *collection_name, const char *subject, int part_num,int size, gboolean all_servers_tried) |
|
| 485 |
{
|
|
| 486 |
CounterData *counter_data; |
|
| 487 |
CounterServerData *server_data; |
|
| 488 |
|
|
| 489 |
g_return_if_fail(plugin_data != NULL); |
|
| 490 |
g_return_if_fail(servername != NULL); |
|
| 491 |
g_return_if_fail(plugin_data->priv != NULL); |
|
| 492 |
|
|
| 493 |
counter_data = (CounterData*) plugin_data->priv; |
|
| 494 |
server_data = plugin_counter_lookup_server(plugin_data, servername); |
|
| 495 |
|
|
| 496 |
g_return_if_fail(server_data != NULL); |
|
| 497 |
|
|
| 498 |
counter_data->data_changed_since_last_announce = TRUE; |
|
| 499 |
server_data->num_parts_failed++; |
|
| 500 |
} |
|
| trunk/plugins/jsonrpc/jsonrpc_events.c (revision 1913) | ||
|---|---|---|
| 479 | 479 |
json_object_object_add(event, "values", obj_values); |
| 480 | 480 |
|
| 481 | 481 |
i = 0; |
| 482 |
while (values[i]) {
|
|
| 482 |
while (values && values[i]) {
|
|
| 483 | 483 |
json_object_array_add(obj_values, json_object_new_string((char*) values[i])); |
| 484 | 484 |
i++; |
| 485 | 485 |
} |
| trunk/glue/glue_json.c (revision 1913) | ||
|---|---|---|
| 1834 | 1834 |
GVariant *ret; |
| 1835 | 1835 |
GError *error = NULL; |
| 1836 | 1836 |
|
| 1837 |
g_return_val_if_fail(glue != NULL, NULL); |
|
| 1838 |
g_return_val_if_fail(plugin_name != NULL, NULL); |
|
| 1839 |
g_return_val_if_fail(method != NULL, NULL); |
|
| 1840 |
g_return_val_if_fail(parameters != NULL, NULL); |
|
| 1841 |
|
|
| 1837 | 1842 |
params_str = g_variant_print((GVariant*) parameters, TRUE); |
| 1838 | 1843 |
|
| 1839 | 1844 |
request_params = json_object_new_array(); |
| trunk/base/utils.c (revision 1913) | ||
|---|---|---|
| 379 | 379 |
} |
| 380 | 380 |
} |
| 381 | 381 |
|
| 382 |
void |
|
| 383 |
nntpgrab_utils_get_readable_time_stamp(time_t stamp, char *stamp_str, int stamp_str_len) |
|
| 384 |
{
|
|
| 385 |
struct tm *now; |
|
| 386 |
static int nugrft_once = 0; |
|
| 387 |
|
|
| 388 |
if (stamp <= 0) {
|
|
| 389 |
stamp_str[0] = '\0'; |
|
| 390 |
return; |
|
| 391 |
} |
|
| 392 |
|
|
| 393 |
if ((now = localtime(&stamp)) == NULL) {
|
|
| 394 |
// Date could not be parsed |
|
| 395 |
stamp_str[0] = '\0'; |
|
| 396 |
return; |
|
| 397 |
} |
|
| 398 |
|
|
| 399 |
if (strftime(stamp_str, stamp_str_len, "%c", now) == 0) {
|
|
| 400 |
if (!nugrft_once) {
|
|
| 401 |
g_error(__FILE__ ":%i buffer too small", __LINE__); |
|
| 402 |
nugrft_once = 1; |
|
| 403 |
} |
|
| 404 |
} |
|
| 405 |
} |
|
| 406 |
|
|
| 382 | 407 |
static gint |
| 383 | 408 |
sort_folders_func(gconstpointer a, gconstpointer b) |
| 384 | 409 |
{
|
| trunk/base/nntpgrab_utils.h (revision 1913) | ||
|---|---|---|
| 319 | 319 |
void nntpgrab_utils_get_readable_finished_time(int estimated_time_remaining, char *time_remaining_str, int time_remaining_str_len); |
| 320 | 320 |
|
| 321 | 321 |
/** |
| 322 |
* nntpgrab_utils_get_readable_time_stamp: |
|
| 323 |
* @stamp: The time stamp which needs to be transformed to a readable notation |
|
| 324 |
* @stamp_str: (out): Pointer to the location where the human readable notation (like 'Friday February 6 2009 - 22:15') can be saved |
|
| 325 |
* @stamp_str_len: The maximum length of the time_remaining_str buffer |
|
| 326 |
* |
|
| 327 |
* Transform a time stamp into a human readable value |
|
| 328 |
*/ |
|
| 329 |
void nntpgrab_utils_get_readable_time_stamp(time_t stamp, char *stamp_str, int stamp_str_len); |
|
| 330 |
|
|
| 331 |
/** |
|
| 322 | 332 |
* nntpgrab_utils_sanitize_text: |
| 323 | 333 |
* @text: (inout): The text which need to be sanitized |
| 324 | 334 |
* @length: The length of the text |
| trunk/base/nntpgrab_utils.def (revision 1913) | ||
|---|---|---|
| 9 | 9 |
nntpgrab_utils_calculate_estimated_time_remaining |
| 10 | 10 |
nntpgrab_utils_get_readable_time_remaining |
| 11 | 11 |
nntpgrab_utils_get_readable_finished_time |
| 12 |
nntpgrab_utils_get_readable_time_stamp |
|
| 12 | 13 |
nntpgrab_utils_get_folder_listing |
| 13 | 14 |
nntpgrab_utils_free_folder_listing |
| 14 | 15 |
nntpgrab_utils_sanitize_text |
| trunk/client/gui/gui_plugins.c (revision 1913) | ||
|---|---|---|
| 420 | 420 |
nntpgrab_glue_signal_connect(glue, "plugin_unloaded", NG_CALLBACK(on_plugin_unloaded), NULL); |
| 421 | 421 |
} |
| 422 | 422 |
|
| 423 |
void |
|
| 424 |
gui_plugins_cleanup(void) |
|
| 425 |
{
|
|
| 426 |
#ifdef HAVE_LIBPEAS |
|
| 427 |
if (extension_set != NULL) {
|
|
| 428 |
g_object_unref(extension_set); |
|
| 429 |
extension_set = NULL; |
|
| 430 |
} |
|
| 431 |
#endif |
|
| 432 |
} |
|
| trunk/client/gui/plugins/counter/plugin_counter_gtk.c (revision 1913) | ||
|---|---|---|
| 29 | 29 |
#include |
| 30 | 30 |
#include |
| 31 | 31 |
|
| 32 |
#include "nntpgrab_utils.h" |
|
| 32 | 33 |
#include "nntpgrab_gui_base.h" |
| 34 |
#include "gui.h" |
|
| 33 | 35 |
|
| 34 | 36 |
#include "plugin_counter_gtk.h" |
| 35 | 37 |
///#include "peasdemo-hello-world-configurable.h" |
| ... | ... | |
| 92 | 94 |
nntpgrab_counter_plugin_init(NntpgrabCounterPlugin *plugin) |
| 93 | 95 |
{
|
| 94 | 96 |
plugin->menuItemDownloadCounter = NULL; |
| 97 |
plugin->counter_data = g_slice_new0(CounterData); |
|
| 95 | 98 |
} |
| 96 | 99 |
|
| 97 | 100 |
static void |
| ... | ... | |
| 104 | 107 |
plugin->menuItemDownloadCounter = NULL; |
| 105 | 108 |
} |
| 106 | 109 |
|
| 110 |
g_slice_free(CounterData, plugin->counter_data); |
|
| 111 |
|
|
| 107 | 112 |
G_OBJECT_CLASS (nntpgrab_counter_plugin_parent_class)->finalize (object); |
| 108 | 113 |
} |
| 109 | 114 |
|
| ... | ... | |
| 114 | 119 |
gtk_widget_hide(windowPluginCounter); |
| 115 | 120 |
} |
| 116 | 121 |
|
| 117 |
G_MODULE_EXPORT void |
|
| 122 |
static void |
|
| 118 | 123 |
btnCounterPluginReset_clicked(GtkWidget *widget, gpointer data) |
| 119 | 124 |
{
|
| 120 |
GVariant *ret; |
|
| 125 |
NGVariant *ret; |
|
| 121 | 126 |
char *errmsg = NULL; |
| 122 | 127 |
NntpgrabCounterPlugin *plugin = NNTPGRAB_COUNTER_PLUGIN(data); |
| 123 | 128 |
|
| 124 | 129 |
g_return_if_fail(plugin != NULL); |
| 125 | 130 |
|
| 126 |
ret = nntpgrab_glue_plugins_call_plugin_method(plugin->glue, PLUGIN_NAME, "reset", NULL, &errmsg); |
|
| 131 |
ret = nntpgrab_glue_plugins_call_plugin_method(plugin->glue, |
|
| 132 |
PLUGIN_NAME, |
|
| 133 |
"reset", |
|
| 134 |
(NGVariant*) g_variant_new("()"),
|
|
| 135 |
&errmsg); |
|
| 136 |
|
|
| 127 | 137 |
if (!ret) {
|
| 128 | 138 |
g_warning(_("Unable to reset download counters: %s"), errmsg);
|
| 129 | 139 |
return; |
| 130 | 140 |
} |
| 131 | 141 |
|
| 132 |
g_variant_unref(ret); |
|
| 142 |
g_variant_unref((GVariant*) ret); |
|
| 133 | 143 |
} |
| 134 | 144 |
|
| 135 | 145 |
G_MODULE_EXPORT gboolean |
| ... | ... | |
| 139 | 149 |
return TRUE; |
| 140 | 150 |
} |
| 141 | 151 |
|
| 152 |
/* Copied over from plugin_counter.c */ |
|
| 142 | 153 |
static void |
| 143 |
menuItemDownloadCounter_clicked(GtkWidget *widget, gpointer data) |
|
| 154 |
free_cached_data(CounterData *counter_data) |
|
| 144 | 155 |
{
|
| 145 |
GVariant *ret; |
|
| 146 |
char *errmsg = NULL; |
|
| 147 |
NntpgrabCounterPlugin *plugin = NNTPGRAB_COUNTER_PLUGIN(data); |
|
| 156 |
GList *list; |
|
| 148 | 157 |
|
| 158 |
g_return_if_fail(counter_data != NULL); |
|
| 159 |
|
|
| 160 |
list = counter_data->collected_data; |
|
| 161 |
while (list) {
|
|
| 162 |
CounterServerData *server_data = (CounterServerData*) list->data; |
|
| 163 |
|
|
| 164 |
g_slice_free(CounterServerData, server_data); |
|
| 165 |
|
|
| 166 |
list = g_list_next(list); |
|
| 167 |
} |
|
| 168 |
|
|
| 169 |
g_list_free(counter_data->collected_data); |
|
| 170 |
counter_data->collected_data = NULL; |
|
| 171 |
} |
|
| 172 |
|
|
| 173 |
static void |
|
| 174 |
update_counter_user_interface(NntpgrabCounterPlugin *plugin) |
|
| 175 |
{
|
|
| 176 |
GtkWidget *lblPluginCounterMeasuredSince; |
|
| 177 |
GtkListStore *store; |
|
| 178 |
GList *list; |
|
| 179 |
char stamp[64]; |
|
| 180 |
|
|
| 149 | 181 |
g_return_if_fail(plugin != NULL); |
| 182 |
g_return_if_fail(plugin->counter_data != NULL); |
|
| 150 | 183 |
|
| 151 |
gtk_widget_show(plugin->windowPluginCounter); |
|
| 152 |
gtk_window_present(GTK_WINDOW(plugin->windowPluginCounter)); |
|
| 184 |
nntpgrab_utils_get_readable_time_stamp(plugin->counter_data->stamp_started, stamp, sizeof(stamp)); |
|
| 185 |
lblPluginCounterMeasuredSince = nntpgrab_gui_base_get_widget("lblPluginCounterMeasuredSince");
|
|
| 186 |
gtk_label_set_text(GTK_LABEL(lblPluginCounterMeasuredSince), stamp); |
|
| 153 | 187 |
|
| 188 |
store = GTK_LIST_STORE(nntpgrab_gui_base_get_object("liststorePluginCounter"));
|
|
| 189 |
|
|
| 190 |
g_return_if_fail(store != NULL); |
|
| 191 |
|
|
| 192 |
gtk_list_store_clear(store); |
|
| 193 |
|
|
| 194 |
list = plugin->counter_data->collected_data; |
|
| 195 |
while (list) {
|
|
| 196 |
CounterServerData *server_data = (CounterServerData*) list->data; |
|
| 197 |
char file_size[64]; |
|
| 198 |
GtkTreeIter iter; |
|
| 199 |
|
|
| 200 |
memset(&file_size, 0, sizeof(file_size)); |
|
| 201 |
nntpgrab_utils_calculate_file_size(server_data->num_bytes_downloaded, file_size, sizeof(file_size)); |
|
| 202 |
|
|
| 203 |
gtk_list_store_append(store, &iter); |
|
| 204 |
gtk_list_store_set(store, &iter, 0, server_data->servername, 1, file_size, 2, server_data->num_parts_succeeded, 3, server_data->num_parts_failed, -1); |
|
| 205 |
|
|
| 206 |
list = g_list_next(list); |
|
| 207 |
} |
|
| 208 |
} |
|
| 209 |
|
|
| 210 |
static void |
|
| 211 |
process_collected_data(CounterData *counter_data, GVariant *servers_data) |
|
| 212 |
{
|
|
| 213 |
GVariantIter *iter_servers; |
|
| 214 |
GVariant *variant_server_data; |
|
| 215 |
|
|
| 216 |
g_variant_get(servers_data, "av", &iter_servers); |
|
| 217 |
while (g_variant_iter_loop(iter_servers, "v", &variant_server_data)) {
|
|
| 218 |
char *key; |
|
| 219 |
GVariant *value; |
|
| 220 |
GVariantIter *iter_server; |
|
| 221 |
CounterServerData *server_data = g_slice_new0(CounterServerData); |
|
| 222 |
|
|
| 223 |
g_variant_get(variant_server_data, "a{sv}", &iter_server);
|
|
| 224 |
while (g_variant_iter_loop(iter_server, "{sv}", &key, &value)) {
|
|
| 225 |
if (!g_strcmp0(key, "servername")) {
|
|
| 226 |
strncpy(server_data->servername, g_variant_get_string(value, NULL), sizeof(server_data->servername) - 1); |
|
| 227 |
} else if (!g_strcmp0(key, "num_bytes_downloaded")) {
|
|
| 228 |
server_data->num_bytes_downloaded = g_variant_get_uint64(value); |
|
| 229 |
} else if (!g_strcmp0(key, "num_parts_succeeded")) {
|
|
| 230 |
server_data->num_parts_succeeded = g_variant_get_uint64(value); |
|
| 231 |
} else if (!g_strcmp0(key, "num_parts_failed")) {
|
|
| 232 |
server_data->num_parts_failed = g_variant_get_uint64(value); |
|
| 233 |
} else {
|
|
| 234 |
g_print(__FILE__ ":%i Invalid parameter detected in result from 'get_collected_data' call: %s\n", __LINE__, key); |
|
| 235 |
} |
|
| 236 |
} |
|
| 237 |
|
|
| 238 |
counter_data->collected_data = g_list_append(counter_data->collected_data, server_data); |
|
| 239 |
} |
|
| 240 |
} |
|
| 241 |
|
|
| 242 |
static void |
|
| 243 |
retrieve_collected_data(NntpgrabCounterPlugin *plugin) |
|
| 244 |
{
|
|
| 245 |
NGVariant *ret; |
|
| 246 |
GVariantIter *iter; |
|
| 247 |
char *key; |
|
| 248 |
GVariant *value; |
|
| 249 |
char *errmsg = NULL; |
|
| 250 |
|
|
| 154 | 251 |
ret = nntpgrab_glue_plugins_call_plugin_method(plugin->glue, |
| 155 | 252 |
PLUGIN_NAME, |
| 156 | 253 |
"get_collected_data", |
| 157 |
g_variant_new("()"),
|
|
| 254 |
(NGVariant*) g_variant_new("()"),
|
|
| 158 | 255 |
&errmsg); |
| 159 | 256 |
|
| 160 | 257 |
if (!ret) {
|
| ... | ... | |
| 162 | 259 |
return; |
| 163 | 260 |
} |
| 164 | 261 |
|
| 165 |
g_variant_unref(ret); |
|
| 262 |
free_cached_data(plugin->counter_data); |
|
| 263 |
|
|
| 264 |
g_variant_get((GVariant*) ret, "a{sv}", &iter);
|
|
| 265 |
while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
|
|
| 266 |
if (!g_strcmp0(key, "stamp_started")) {
|
|
| 267 |
plugin->counter_data->stamp_started = (time_t) g_variant_get_uint64(value); |
|
| 268 |
} else if (!g_strcmp0(key, "collected_data")) {
|
|
| 269 |
process_collected_data(plugin->counter_data, value); |
|
| 270 |
} else {
|
|
| 271 |
g_print(__FILE__ ":%i Invalid parameter detected in result from 'get_collected_data' call: %s\n", __LINE__, key); |
|
| 272 |
} |
|
| 273 |
} |
|
| 274 |
g_variant_iter_free(iter); |
|
| 275 |
|
|
| 276 |
g_variant_unref((GVariant*) ret); |
|
| 277 |
|
|
| 166 | 278 |
} |
| 167 | 279 |
|
| 168 | 280 |
static void |
| 281 |
menuItemDownloadCounter_clicked(GtkWidget *widget, gpointer data) |
|
| 282 |
{
|
|
| 283 |
NntpgrabCounterPlugin *plugin = NNTPGRAB_COUNTER_PLUGIN(data); |
|
| 284 |
|
|
| 285 |
g_return_if_fail(plugin != NULL); |
|
| 286 |
|
|
| 287 |
gtk_widget_show(plugin->windowPluginCounter); |
|
| 288 |
gtk_window_present(GTK_WINDOW(plugin->windowPluginCounter)); |
|
| 289 |
|
|
| 290 |
retrieve_collected_data(plugin); |
|
| 291 |
update_counter_user_interface(plugin); |
|
| 292 |
} |
|
| 293 |
|
|
| 294 |
static void |
|
| 295 |
plugin_event_cb(NntpgrabGlue *obj, const char *plugin_name, const char *event_name, const char **values, gpointer data) |
|
| 296 |
{
|
|
| 297 |
NntpgrabCounterPlugin *plugin = NNTPGRAB_COUNTER_PLUGIN(data); |
|
| 298 |
|
|
| 299 |
g_return_if_fail(plugin != NULL); |
|
| 300 |
|
|
| 301 |
if (!strcmp(plugin_name, "Download counter")) {
|
|
| 302 |
if (!strcmp(event_name, "counter_data_changed")) {
|
|
| 303 |
/* Only retrieve the new statistics when the statistics window is currently visible */ |
|
| 304 |
GtkWidget *windowPluginCounter = nntpgrab_gui_base_get_widget("windowPluginCounter");
|
|
| 305 |
|
|
| 306 |
if (!gtk_widget_get_visible(windowPluginCounter)) {
|
|
| 307 |
return; |
|
| 308 |
} |
|
| 309 |
|
|
| 310 |
retrieve_collected_data(plugin); |
|
| 311 |
update_counter_user_interface(plugin); |
|
| 312 |
} |
|
| 313 |
} |
|
| 314 |
} |
|
| 315 |
|
|
| 316 |
static void |
|
| 169 | 317 |
nntpgrab_counter_plugin_activate(PeasActivatable *activatable) |
| 170 | 318 |
{
|
| 319 |
GtkWidget *btnCounterPluginReset; |
|
| 171 | 320 |
GtkWidget *menuPlugins; |
| 172 | 321 |
NntpgrabCounterPlugin *plugin = NNTPGRAB_COUNTER_PLUGIN(activatable); |
| 173 | 322 |
|
| ... | ... | |
| 177 | 326 |
plugin->windowPluginCounter = nntpgrab_gui_base_get_widget("windowPluginCounter");
|
| 178 | 327 |
g_return_if_fail(plugin->windowPluginCounter != NULL); |
| 179 | 328 |
|
| 329 |
btnCounterPluginReset = nntpgrab_gui_base_get_widget("btnCounterPluginReset");
|
|
| 330 |
g_return_if_fail(btnCounterPluginReset != NULL); |
|
| 331 |
|
|
| 180 | 332 |
/* Hook up a new menu item to the 'Plugins' menu */ |
| 181 | 333 |
menuPlugins = nntpgrab_gui_base_get_widget("menuPlugins");
|
| 182 | 334 |
g_return_if_fail(menuPlugins != NULL); |
| ... | ... | |
| 187 | 339 |
gtk_menu_shell_append(GTK_MENU_SHELL(menuPlugins), plugin->menuItemDownloadCounter); |
| 188 | 340 |
|
| 189 | 341 |
g_signal_connect(plugin->menuItemDownloadCounter, "activate", G_CALLBACK(menuItemDownloadCounter_clicked), plugin); |
| 342 |
g_signal_connect(btnCounterPluginReset, "clicked", G_CALLBACK(btnCounterPluginReset_clicked), plugin); |
|
| 343 |
|
|
| 344 |
nntpgrab_glue_signal_connect(glue, "plugin_event", NG_CALLBACK(plugin_event_cb), plugin); |
|
| 190 | 345 |
} |
| 191 | 346 |
|
| 192 | 347 |
static void |
| trunk/client/gui/plugins/counter/plugin_counter_gtk.h (revision 1913) | ||
|---|---|---|
| 36 | 36 |
typedef struct _NntpgrabCounterPlugin NntpgrabCounterPlugin; |
| 37 | 37 |
typedef struct _NntpgrabCounterPluginClass NntpgrabCounterPluginClass; |
| 38 | 38 |
|
| 39 |
typedef struct _counter_server_data {
|
|
| 40 |
char servername[128]; |
|
| 41 |
guint64 num_bytes_downloaded; |
|
| 42 |
guint64 num_parts_succeeded; |
|
| 43 |
guint64 num_parts_failed; |
|
| 44 |
} CounterServerData; |
|
| 45 |
|
|
| 46 |
typedef struct _counter_data {
|
|
| 47 |
time_t stamp_started; |
|
| 48 |
GList *collected_data; /* List contains CounterServerData elements */ |
|
| 49 |
} CounterData; |
|
| 50 |
|
|
| 51 |
|
|
| 39 | 52 |
struct _NntpgrabCounterPlugin {
|
| 40 | 53 |
PeasExtensionBase parent_instance; |
| 41 | 54 |
|
| 42 | 55 |
NntpgrabGlue *glue; |
| 56 |
CounterData *counter_data; |
|
| 43 | 57 |
|
| 44 | 58 |
GtkWidget *menuItemDownloadCounter; |
| 45 | 59 |
GtkWidget *windowPluginCounter; |
| trunk/client/gui/plugins/counter/Makefile.am (revision 1913) | ||
|---|---|---|
| 5 | 5 |
plugin_DATA = nntpgrab_plugin_counter_gtk.plugin |
| 6 | 6 |
|
| 7 | 7 |
libnntpgrab_plugin_counter_gtk_la_SOURCES = plugin_counter_gtk.c |
| 8 |
libnntpgrab_plugin_counter_gtk_la_CFLAGS = -I$(top_srcdir)/nntpgrab_core -I$(top_srcdir)/base -I$(top_srcdir)/gui_base -I$(top_srcdir)/glue $(GLIB_CFLAGS) $(GTK3_CFLAGS) $(GTK_CFLAGS) $(LIBPEAS_CFLAGS) |
|
| 8 |
libnntpgrab_plugin_counter_gtk_la_CFLAGS = -I$(top_srcdir)/nntpgrab_core -I$(top_srcdir)/base -I$(top_srcdir)/gui_base -I$(top_srcdir)/glue -I$(top_srcdir)/client/gui $(GLIB_CFLAGS) $(GTK3_CFLAGS) $(GTK_CFLAGS) $(LIBPEAS_CFLAGS) |
|
| 9 | 9 |
libnntpgrab_plugin_counter_gtk_la_LDFLAGS = -module -no-undefined -avoid-version |
| 10 | 10 |
libnntpgrab_plugin_counter_gtk_la_LIBADD = $(GLIB_LIBS) $(GIO_LIBS) $(GTK3_LIBS) $(GTK_LIBS) $(LIBEAS_LIBS) $(top_srcdir)/gui_base/libnntpgrab_gui_base.la $(top_srcdir)/glue/libnntpgrab_glue.la |
| 11 | 11 |
|
| trunk/client/gui/plugins/counter/counter_plugin_gtk.ui (revision 1913) | ||
|---|---|---|
| 1 | 1 |
|
| 2 | 2 |
|
| 3 |
|
|
| 3 |
|
|
| 4 | 4 |
|
| 5 | 5 |
|
| 6 | 6 |
|
| 7 | 7 |
|
| 8 |
|
|
| 8 |
|
|
| 9 | 9 |
|
| 10 |
|
|
| 10 |
|
|
| 11 | 11 |
|
| 12 |
|
|
| 12 |
|
|
| 13 | 13 |
|
| 14 | 14 |
|
| 15 | 15 |
|
| ... | ... | |
| 17 | 17 |
|
| 18 | 18 |
|
| 19 | 19 |
|
| 20 |
|
|
| 20 |
|
|
| 21 |
|
|
| 22 |
|
|
| 21 | 23 |
|
| 22 | 24 |
|
| 23 | 25 |
|
| ... | ... | |
| 137 | 139 |
|
| 138 | 140 |
|
| 139 | 141 |
|
| 142 |
|
|
| 143 |
|
|
| 144 |
|
|
| 145 |
|
|
| 146 |
|
|
| 147 |
|
|
| 148 |
|
|
| 149 |
|
|
| 150 |
|
|
| 151 |
|
|
| 152 |
|
|
| 153 |
|
|
| 154 |
|
|
| 140 | 155 |
|
| 141 | 156 |
|
| 142 | 157 |
|
| ... | ... | |
| 158 | 173 |
|
| 159 | 174 |
|
| 160 | 175 |
|
| 161 |
|
|
| 162 | 176 |
|
| 163 | 177 |
|
| 164 | 178 |
|
| trunk/client/gui/main.c (revision 1913) | ||
|---|---|---|
| 58 | 58 |
void auto_import_initialize(void); |
| 59 | 59 |
void autoshutdown_initialize(void); |
| 60 | 60 |
void gui_plugins_initialize(void); |
| 61 |
void gui_plugins_cleanup(void); |
|
| 61 | 62 |
|
| 62 | 63 |
// auto_import.c |
| 63 | 64 |
void disable_auto_import(void); |
| ... | ... | |
| 727 | 728 |
nntpgrab_gui_base_tray_destroy(); |
| 728 | 729 |
} |
| 729 | 730 |
|
| 731 |
/* Unload the GUI plugins before cleaning up the NNTPGrabGlue */ |
|
| 732 |
gui_plugins_cleanup(); |
|
| 733 |
|
|
| 730 | 734 |
if (glue) {
|
| 731 | 735 |
// Always try to disable the auto import even if it isn't in use |
| 732 | 736 |
if (initialized) {
|
Also available in: Unified diff
NNTPGrab

