From fb22c3bb1436f1abd195db208c545d275639e14f Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Wed, 22 Oct 2014 02:19:57 +0200 Subject: [PATCH] fix refresh interruption, fix #40 --- src/stat.c | 181 +++++++++++++++++++++++++++-------------------------- src/stat.h | 8 ++- 2 files changed, 98 insertions(+), 91 deletions(-) diff --git a/src/stat.c b/src/stat.c index d10e59d..5fe7801 100644 --- a/src/stat.c +++ b/src/stat.c @@ -53,6 +53,8 @@ static const char savage_master_header[5] = { 0x7E, 0x41, 0x03, 0x00, 0x00 }; static void stat_next (struct stat_job *job); static void parse_qstat_record (struct stat_conn *conn); +static GSList* stat_buffer_to_strings(gchar buffer[], gsize bufsize); + typedef void (*server_unref_void)(void*); typedef void (*userver_unref_void)(void*); @@ -123,6 +125,17 @@ static void stat_master_update_done( // check if master output is in savage format, if yes parse it and return true. // otherwise return false so the normal parse function can do the work +#if 0 +/* + * needs + * conn->buf = g_malloc (BUFFER_MINSIZE); + * conn->bufsize = BUFFER_MINSIZE; + * but currently + * conn->buf = NULL; + * conn->bufsize = 0; + * + */ + static void parse_savage_master_output (struct stat_conn *conn) { struct stat_job *job = conn->job; @@ -267,6 +280,7 @@ static void parse_savage_master_output (struct stat_conn *conn) } // infinite loop end, next lines are never reached } +#endif /** parse qstat output line str, in ip:port format. return true if @@ -431,6 +445,7 @@ static gboolean stat_master_input_callback (GIOChannel *chan, GIOCondition condi debug_increase_indent(); debug(3,"stat_master_input_callback(%p,%d,...)",conn,chan); +#if 0 #warning ugly hack for savage, make master handling more generic! if(conn->master->type == SAS_SERVER && conn->master->master_type == MASTER_HTTP) { /* if first time, check it */ @@ -448,6 +463,7 @@ static gboolean stat_master_input_callback (GIOChannel *chan, GIOCondition condi } /* if you are here, savage is NOT detected, do your job */ +#endif /* return TRUE when there is nothing (more) to do */ while (1) { first_used = 0; @@ -457,7 +473,7 @@ static gboolean stat_master_input_callback (GIOChannel *chan, GIOCondition condi stat_master_update_done (conn, job, conn->master, SOURCE_ERROR); stat_update_masters (job); debug_decrease_indent(); - return TRUE; + return FALSE; } status = g_io_channel_read_chars(chan, conn->buf + conn->pos, conn->bufsize - conn->pos, &res, &err); @@ -466,12 +482,12 @@ static gboolean stat_master_input_callback (GIOChannel *chan, GIOCondition condi stat_master_update_done (conn, job, conn->master, SOURCE_UP); stat_update_masters (job); debug_decrease_indent(); - return TRUE; + return FALSE; } else if (status == G_IO_STATUS_AGAIN) { debug(3,"stat_master_input_callback -- unavailable"); debug_decrease_indent(); - return TRUE; + return FALSE; } else if (status == G_IO_STATUS_ERROR) { debug(3,"stat_master_input_callback -- error"); @@ -498,7 +514,7 @@ static gboolean stat_master_input_callback (GIOChannel *chan, GIOCondition condi stat_master_update_done (conn, job, conn->master, conn->master->state); stat_update_masters (job); debug_decrease_indent(); - return TRUE; + return FALSE; } first_used = tmp - conn->buf; @@ -820,8 +836,7 @@ static void parse_qstat_record (struct stat_conn *conn) { count as does the prepend below. So we need to decrement it one just for fun. */ - job->delayed.queued_servers = - server_list_prepend (job->delayed.queued_servers, server); + job->delayed.queued_servers = server_list_prepend (job->delayed.queued_servers, server); job->progress.done++; server_unref (server); @@ -829,8 +844,9 @@ static void parse_qstat_record (struct stat_conn *conn) { parse_qstat_record_part2 (conn->strings->next, server); - for (list = job->server_handlers; list; list = list->next) + for (list = job->server_handlers; list; list = list->next) { (* (server_func) list->data) (job, server); + } } } @@ -896,14 +912,6 @@ void parse_saved_server (GSList *strings) { } -static void adjust_pointers (GSList *list, gpointer new, gpointer old) { - while (list) { - list->data = (gpointer) ((char *)new + ((char *)list->data - (char *)old)); - list = list->next; - } -} - - static void stat_servers_update_done (struct stat_conn *conn) { debug (3, "stat_servers_update_done() -- Conn %lx server list %lx", conn, conn->job->servers); server_list_free (conn->job->servers); @@ -911,7 +919,29 @@ static void stat_servers_update_done (struct stat_conn *conn) { stat_free_conn (conn); } +static GSList* stat_buffer_to_strings(gchar buffer[], gsize bufsize) { + GSList *strings = NULL; + gchar token[4096]; + gsize i, last; + for (i = 0, last = 0; i < bufsize; i++) { + if (i - last == 4096) { + return strings; // error : too long line + } + else if (buffer[i] == '\n' || buffer[i] == '\0') { + token[i - last] = '\0'; + + debug(6, "stat_buffer_to_strings - token: %s", token); + + strings = g_slist_append(strings, strdup(token)); + last = i + 1; + } + else { + token[i - last] = buffer[i]; + } + } + return strings; +} /* stat_servers_input_callback -- as data is returned from the qstat @@ -920,38 +950,53 @@ static void stat_servers_update_done (struct stat_conn *conn) { */ static gboolean stat_servers_input_callback (GIOChannel *chan, GIOCondition condition, struct stat_conn *conn) { struct stat_job *job = conn->job; - int first_used = 0; - int blocked = FALSE; - char *tmp; + gchar *buf = g_malloc(sizeof(gchar*) * BUFFER_MINSIZE); gsize res = 0; GError *err = NULL; GIOStatus status; + GSList *strings, *current; - /* debug (3, "stat_servers_input_callback() -- Conn %lx", conn); */ - while (1) { - first_used = 0; - blocked = FALSE; + debug (3, "stat_servers_input_callback() -- Conn %lx", conn); + while (TRUE) { + status = g_io_channel_read_chars(chan, buf, BUFFER_MINSIZE, &res, &err); - if (conn->bufsize - conn->pos < BUFFER_TRESHOLD) { - if (conn->bufsize >= BUFFER_MAXSIZE) { - fprintf (stderr, "server record is too large\n"); - stat_servers_update_done (conn); - stat_next (job); - return TRUE; - } - conn->bufsize += conn->bufsize; - tmp = conn->buf; - conn->buf = g_realloc (conn->buf, conn->bufsize); - adjust_pointers (conn->strings, conn->buf, tmp); + conn->bufsize += res; + + if (conn->buf == NULL) { + conn->buf = g_malloc(sizeof(gchar*) * conn->bufsize); + } + else { + conn->buf = g_realloc(conn->buf, sizeof(gchar*) * conn->bufsize); } - status = g_io_channel_read_chars(chan, conn->buf + conn->pos, conn->bufsize - conn->pos, &res, &err); + strncpy(conn->buf + (conn->bufsize - res), buf, res); + if (status == G_IO_STATUS_EOF) { - debug(3,"stat_servers_input_callback -- eof"); - debug (3, "Conn %ld Sub Process Done with server list %lx", conn, conn->job->servers); + debug(3, "stat_servers_input_callback -- eof"); + debug(3, "Conn %ld Sub Process Done with server list %lx", conn, conn->job->servers); + + strings = stat_buffer_to_strings(conn->buf, conn->bufsize); + current = strings; + + conn->strings = NULL; + + while (current) { + while (strlen(current->data)) { + conn->strings = g_slist_append(conn->strings, strdup(current->data)); + current = current->next; + } + if (conn->strings) { + parse_qstat_record (conn); + g_slist_free (conn->strings); + conn->strings = NULL; + } + current = current->next; + } + g_slist_free(strings); + stat_servers_update_done (conn); stat_next (job); - return TRUE; + return FALSE; } else if (status == G_IO_STATUS_AGAIN) { debug(3,"stat_servers_input_callback -- unavailable"); @@ -959,6 +1004,8 @@ static gboolean stat_servers_input_callback (GIOChannel *chan, GIOCondition cond } else if (status == G_IO_STATUS_ERROR) { debug(3,"stat_servers_input_callback -- error"); + + failed ("read", NULL); stat_servers_update_done (conn); stat_next (job); @@ -966,54 +1013,7 @@ static gboolean stat_servers_input_callback (GIOChannel *chan, GIOCondition cond } /* G_IO_STATUS_NORMAL */ - debug(3,"stat_servers_input_callback -- chars read"); - tmp = conn->buf + conn->pos; - conn->pos += res; - - while (res && (tmp = memchr (tmp, '\n', res)) != NULL) { - debug(3,"stat_servers_input_callback -- parse new line"); - *tmp++ = '\0'; - - if (conn->buf[conn->lastnl] == '\0') { - debug(3,"stat_servers_input_callback -- blocked"); - blocked = TRUE; - - parse_qstat_record (conn); - - g_slist_free (conn->strings); - conn->strings = NULL; - - first_used = conn->lastnl + 1; - } - else { - conn->strings = g_slist_append (conn->strings, conn->buf + conn->lastnl); - } - - conn->lastnl = tmp - conn->buf; - res = conn->buf + conn->pos - tmp; - } - - if (first_used) { - if (first_used == conn->pos) { - conn->pos = 0; - conn->lastnl = 0; - } - else { - tmp = conn->buf + first_used; - g_memmove (conn->buf, conn->buf + first_used, conn->pos - first_used); - conn->pos -= first_used; - conn->lastnl -= first_used; - adjust_pointers (conn->strings, conn->buf, tmp); - } - } - - if (blocked) { - debug(3,"stat_servers_input_callback -- if blocked"); - g_source_remove (conn->tag); - - debug(3,"stat_servers_input_callback -- new watch"); - conn->tag = g_io_add_watch (conn->chan, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI, conn->input_callback, conn); - } + /* loop */ } // infinite loop end, next lines are never read } @@ -1049,8 +1049,10 @@ static struct stat_conn *new_file_conn (struct stat_job *job, const char* file, conn->chan = g_io_channel_unix_new (conn->fd); conn->pos = 0; conn->lastnl = 0; +#if 0 conn->first = TRUE; conn->is_savage = FALSE; +#endif conn->strings = NULL; conn->servers = NULL; @@ -1106,16 +1108,18 @@ static struct stat_conn *start_qstat (struct stat_job *job, char *argv[], GIOFun conn = g_malloc (sizeof (struct stat_conn)); - conn->buf = g_malloc (BUFFER_MINSIZE); - conn->bufsize = BUFFER_MINSIZE; + conn->buf = NULL; + conn->bufsize = 0; conn->tmpfile = NULL; conn->pid = pid; conn->fd = pipefds[0]; conn->chan = g_io_channel_unix_new (conn->fd); conn->pos = 0; conn->lastnl = 0; +#if 0 conn->first = TRUE; conn->is_savage = FALSE; +#endif conn->strings = NULL; conn->servers = NULL; @@ -1525,7 +1529,8 @@ out: } -#define MAX_SERVERS_IN_CMDLINE 8 +// THD #define MAX_SERVERS_IN_CMDLINE 8 +#define MAX_SERVERS_IN_CMDLINE 1 static struct stat_conn *stat_open_conn_qstat (struct stat_job *job) { struct server *s = NULL; diff --git a/src/stat.h b/src/stat.h index db71e22..e4b4975 100644 --- a/src/stat.h +++ b/src/stat.h @@ -55,8 +55,8 @@ struct stat_conn { guint tag; GIOFunc input_callback; - char *buf; - int bufsize; + gchar *buf; + gsize bufsize; int pos; int lastnl; @@ -70,9 +70,11 @@ struct stat_conn { char *tmpfile; +#if 0 // UGLY HACKS gboolean first; // marker for savage check header - gboolean is_savage; // true if file is in savage format + boolean is_savage; // true if file is in savage format +#endif }; struct delayed_refresh {