core dump fixes, debug code add.

git-svn-id: http://svn.code.sf.net/p/xqf/code/trunk@35 d2ac09be-c843-0410-8b1f-f8a84130e0ec
This commit is contained in:
Bill Adams 2001-01-08 05:04:52 +00:00 committed by evilbill
parent adcb0dc047
commit 97ae8ca047
12 changed files with 397 additions and 186 deletions

View File

@ -1,3 +1,18 @@
Feb 07, 2001: Bill Adams <bill@evil.inetarena.com>
-Fixed the core dumps (for the most part) for real.
The only time I have seen a core dump at this point
is when updating a master list where there are not
any servers already in the list. However, once
you have a list of servers, you should be able to
update/refresh at will without any problems.
-Lots of debugging code with the debug(...) call. If
you want lots of output, use -d 3, to see the servers
it is parsing use -d 4. For an insane amount of output
use -d 7. Debug levels greater than three will
will have so much output that it will most likely
slow down the program.
-Added a fair number of comments to the code.
Jan 31, 2001: Bill Adams <bill@evil.inetarena.com>
-Made it so OSP game types show up correctly.

5
xqf/TODO Normal file
View File

@ -0,0 +1,5 @@
- Multiple Favorites
- More general server filters so one can filter based on any server var.
- Redial feature to connect to your favorite busy server.

View File

@ -32,6 +32,23 @@ void debug(int level, char *fmt, ...)
fprintf(stderr, "\n");
}
void debug_cmd(int level, char *argv[], char *fmt, ...)
{
va_list argp;
int i;
if( level > debug_level ) return;
fprintf(stderr, "debug(%d): ", level);
va_start(argp, fmt);
vfprintf(stderr, fmt, argp);
va_end(argp);
fprintf(stderr, " EXEC> ");
for (i = 0; argv[i]; ++i)
fprintf (stderr, "%s ", argv[i]);
fprintf(stderr, "\n");
}
void set_debug_level (int level)
{
debug_level = level;

View File

@ -21,6 +21,7 @@
#define DEFAULT_DEBUG_LEVEL 0
void debug(int, char *, ...);
void debug_cmd(int, char *[], char *, ...);
void set_debug_level (int);
int get_debug_level (void);
int debug_level;

View File

@ -113,23 +113,30 @@ void apply_filters (unsigned mask, struct server *s) {
}
GSList *build_filtered_list (unsigned mask, GSList *servers) {
struct server *s;
/*
build_filtered_list -- Return a list of servers that pass the filter
requirements. Called from server_clist_setlist() and
server_clist_build_filtered().
*/
GSList *build_filtered_list (unsigned mask, GSList *server_list) {
struct server *server;
GSList *list = NULL;
unsigned i;
int n;
while (servers) {
s = (struct server *) servers->data;
apply_filters (mask | FILTER_PLAYER_MASK, s); /* in filter.c */
while (server_list) {
server = (struct server *) server_list->data;
apply_filters (mask | FILTER_PLAYER_MASK, server); /* in filter.c */
if ((s->filters & mask) == mask) {
list = g_slist_prepend (list, s);
server_ref (s);
if ((server->filters & mask) == mask) {
list = g_slist_prepend (list, server);
debug (6, "build_filtered_list() -- Server %lx added to list", server);
server_ref (server);
}
servers = servers->next;
server_list = server_list->next;
}
list = g_slist_reverse (list);

View File

@ -653,76 +653,78 @@ static struct player *un_parse_player (char *token[], int n) {
#endif
static void quake_parse_server (char *token[], int n, struct server *s) {
static void quake_parse_server (char *token[], int n, struct server *server) {
/*
This does both Quake (?) and Unreal servers
*/
int poqs;
int offs;
poqs = (s->type == Q1_SERVER || s->type == H2_SERVER);
/* debug (6, "quake_parse_server: Parse %s", server->name); */
poqs = (server->type == Q1_SERVER || server->type == H2_SERVER);
if ((poqs && n != 10) || (!poqs && n != 8))
return;
#ifdef QSTAT23
if (*(token[2])) { /* if name is not empty */
if (s->type != Q3_SERVER) {
s->name = g_strdup (token[2]);
if (server->type != Q3_SERVER) {
server->name = g_strdup (token[2]);
}
else {
s->name = g_malloc (strlen (token[2]) + 1);
q3_unescape (s->name, token[2]);
server->name = g_malloc (strlen (token[2]) + 1);
q3_unescape (server->name, token[2]);
}
}
#else
if (*(token[2])) /* if name is not empty */
s->name = g_strdup (token[2]);
server->name = g_strdup (token[2]);
#endif
offs = (poqs)? 5 : 3;
if (*(token[offs])) /* if map is not empty */
s->map = g_strdup (token[offs]);
server->map = g_strdup (token[offs]);
s->maxplayers = strtoush (token[offs + 1]);
s->curplayers = strtoush (token[offs + 2]);
server->maxplayers = strtoush (token[offs + 1]);
server->curplayers = strtoush (token[offs + 2]);
s->ping = strtosh (token[offs + 3]);
s->retries = strtosh (token[offs + 4]);
server->ping = strtosh (token[offs + 3]);
server->retries = strtosh (token[offs + 4]);
}
static void qw_analyze_serverinfo (struct server *s) {
static void qw_analyze_serverinfo (struct server *server) {
char **info_ptr;
long n;
if ((games[s->type].flags & GAME_SPECTATE) != 0)
s->flags |= SERVER_SPECTATE;
/* debug( 6, "qw_analyze_serverinfo: Analyze %s", server->name ); */
if ((games[server->type].flags & GAME_SPECTATE) != 0)
server->flags |= SERVER_SPECTATE;
for (info_ptr = s->info; info_ptr && *info_ptr; info_ptr += 2) {
for (info_ptr = server->info; info_ptr && *info_ptr; info_ptr += 2) {
if (strcmp (*info_ptr, "*gamedir") == 0) {
s->game = info_ptr[1];
server->game = info_ptr[1];
}
else if (strcmp (*info_ptr, "*cheats") == 0) {
s->flags |= SERVER_CHEATS;
server->flags |= SERVER_CHEATS;
}
else if (strcmp (*info_ptr, "maxspectators") == 0) {
n = strtol (info_ptr[1], NULL, 10);
if (n <= 0)
s->flags &= ~SERVER_SPECTATE;
server->flags &= ~SERVER_SPECTATE;
}
else if (strcmp (*info_ptr, "needpass") == 0) {
n = strtol (info_ptr[1], NULL, 10);
if ((n & 1) != 0)
s->flags |= SERVER_PASSWORD;
server->flags |= SERVER_PASSWORD;
if ((n & 2) != 0)
s->flags |= SERVER_SP_PASSWORD;
server->flags |= SERVER_SP_PASSWORD;
}
}
}
#ifdef QSTAT_HAS_UNREAL_SUPPORT
static void un_analyze_serverinfo (struct server *s) {
char **info_ptr;

View File

@ -65,47 +65,61 @@ static int userver_hash_func (const char *hostname, unsigned short port) {
}
/*
server_new -- Create (malloc) a new server structure with
all of the values set at zero except the reference count which
should be at one.
*/
static struct server *server_new (struct host *h, unsigned short port,
enum server_type type) {
struct server *s;
enum server_type type) {
struct server *server;
if (port == 0 || type == UNKNOWN_SERVER)
return NULL;
s = g_malloc0 (sizeof (struct server));
server = g_malloc0 (sizeof (struct server));
debug (6, "server_new() -- Server %lx", server);
server_ref (server);
s->host = h;
host_ref (h);
server->host = h;
host_ref (h); /* Increse the refernece count on the host struct */
s->port = port;
s->type = type;
s->ping = -1;
s->retries = -1;
server->port = port;
server->type = type;
server->ping = -1;
server->retries = -1;
return s;
return server;
}
static struct userver *userver_new (const char *hostname, unsigned short port,
enum server_type type) {
struct userver *s;
struct userver *userver;
if (port == 0 || type == UNKNOWN_SERVER)
return NULL;
s = g_malloc0 (sizeof (struct userver));
userver = g_malloc0 (sizeof (struct userver));
userver_ref (userver); /* baa -- Needed? FIX ME */
userver->hostname = g_strdup (hostname);
userver->port = port;
userver->type = type;
s->hostname = g_strdup (hostname);
s->port = port;
s->type = type;
return s;
return userver;
}
/*
server_add -- See if a host/port is in our list. If it is not
then add one. If it is then we increase the reference count.
*/
struct server *server_add (struct host *h, unsigned short port,
enum server_type type) {
struct server *s;
enum server_type type) {
struct server *server;
GSList *ptr;
int node;
@ -116,28 +130,33 @@ struct server *server_add (struct host *h, unsigned short port,
port = games[type].default_port;
node = server_hash_func (h, port);
debug (6, "server_add() -- Add/Get a server");
if (!servers.nodes) {
servers.nodes = g_malloc0 (sizeof (GSList *) * servers.num);
}
else {
/* Go through each of the servers in the list (each node)
and see if we have a matching (by reference) entry.
*/
for (ptr = servers.nodes[node]; ptr; ptr = ptr->next) {
s = (struct server *) ptr->data;
if (s->host == h && s->port == port) {
server_ref (s); /* baa -- added Dec-27, 2000 CORE FIX? */
return s;
server = (struct server *) ptr->data;
if (server->host == h && server->port == port) {
server_ref (server); /* baa -- added Dec-27, 2000 CORE FIX? */
return server;
}
}
}
s = server_new (h, port, type);
if (s) {
servers.nodes[node] = g_slist_prepend (servers.nodes[node], s);
server = server_new (h, port, type);
if (server) {
servers.nodes[node] = g_slist_prepend (servers.nodes[node], server);
if (games[type].analyze_serverinfo)
(*games[type].analyze_serverinfo) (s);
(*games[type].analyze_serverinfo) (server);
}
return s;
return server;
}
@ -208,20 +227,28 @@ void server_free_info (struct server *s) {
}
void server_unref (struct server *s) {
void server_unref (struct server *server) {
int node;
if (!s)
if (!server)
return;
s->ref_count--;
server->ref_count--;
if (s->ref_count <= 0) {
node = server_hash_func (s->host, s->port);
servers.nodes[node] = g_slist_remove (servers.nodes[node], s);
server_free_info (s);
host_unref (s->host);
g_free (s);
debug (6, "server_unref() -- Server %lx ref now at %d",
server, server->ref_count);
if (server->ref_count <= 0) {
node = server_hash_func (server->host, server->port);
servers.nodes[node] = g_slist_remove (servers.nodes[node], server);
/*
Oops, it seems that we were freeing the server info before
freeing the host info. Bad. To free the host info w/o a memory
leak we need to do that before freeing the server info. --baa
*/
host_unref (server->host);
server_free_info (server);
g_free (server);
}
}
@ -245,6 +272,7 @@ void userver_unref (struct userver *s) {
GSList *server_list_copy (GSList *list) {
debug (3, "server_list_copy() -- list %ld copying all servers", list);
g_slist_foreach (list, (GFunc) server_ref, NULL);
return g_slist_copy (list);
}
@ -256,20 +284,20 @@ GSList *userver_list_copy (GSList *list) {
}
GSList *server_list_append_list (GSList *list, GSList *servers,
enum server_type type) {
struct server *s;
GSList *server_list_append_list (GSList *list, GSList *server_list,
enum server_type type) {
struct server *server;
GSList *add = NULL;
while (servers) {
s = (struct server *) servers->data;
if (type == UNKNOWN_SERVER || type == s->type) {
if (g_slist_find (list, s) == NULL) {
add = g_slist_prepend (add, s);
server_ref (s);
debug (6, "server_list_append_list() -- list %lx", list);
while (server_list) {
server = (struct server *) server_list->data;
if (type == UNKNOWN_SERVER || type == server->type) {
if (g_slist_find (list, server) == NULL) {
add = g_slist_prepend (add, server);
server_ref (server);
}
}
servers = g_slist_next (servers);
server_list = g_slist_next (server_list);
}
return g_slist_concat (list, g_slist_reverse (add));
@ -324,20 +352,26 @@ int uservers_total (void) {
}
/*
all_servers -- Get a list of all servers. This is called from
two functions source.c:free_masters and statistics.c:collect_statistics
both of which call server_free_list afterwards.
*/
GSList *all_servers (void) {
GSList *list = NULL;
GSList *tmp;
struct server *s;
struct server *server;
int i;
if (!servers.nodes)
return NULL;
debug (6, "all_servers() -- Get all servers");
for (i = 0; i < servers.num; i++) {
for (tmp = servers.nodes[i]; tmp; tmp = tmp->next) {
s = (struct server *) tmp->data;
list = g_slist_prepend (list, s);
server_ref (s);
server = (struct server *) tmp->data;
list = g_slist_prepend (list, server);
server_ref (server);
}
}
@ -390,18 +424,19 @@ int parse_address (char *str, char **addr, unsigned short *port) {
struct server *userver_set_host (struct userver *us, struct host *h) {
struct server *s;
struct server *server;
if (!us || !h) return NULL;
if (us->s) return us->s;
s = server_add (h, us->port, us->type);
if (s) {
us->s = s;
server_ref (s);
/* Since server_add increases the reference count for us,
we do not do it here. */
server = server_add (h, us->port, us->type);
if (server) {
us->s = server;
}
return s;
return server;
}
@ -429,7 +464,8 @@ void server_lists_intersect (GSList **list1, GSList **list2) {
GSList *list3 = NULL;
GSList *tmp;
struct server *s;
debug (6, "server_lists_intersect() -- ");
for (tmp = *list1; tmp; tmp = tmp->next) {
s = (struct server *) tmp->data;
if (g_slist_find (*list2, s)) {

View File

@ -22,7 +22,7 @@
#include <glib.h>
#include "xqf.h"
#include "debug.h"
extern struct server *server_add (struct host *h, unsigned short port,
enum server_type type);
@ -56,26 +56,31 @@ extern void server_list_fprintf (FILE *f, GSList *servers);
extern void userver_list_fprintf (FILE *f, GSList *uservers);
static inline void server_ref (struct server *s) {
if (s) s->ref_count++;
static inline void server_ref (struct server *server) {
if (server){
server->ref_count++;
debug (6, "server_ref() -- Server %lx now at %d", server, server->ref_count);
}
}
static inline void userver_ref (struct userver *us) {
if (us) us->ref_count++;
}
static inline GSList *server_list_prepend (GSList *list, struct server *s) {
if (g_slist_find (list, s) == NULL) {
list = g_slist_prepend (list, s);
server_ref (s);
static inline GSList *server_list_prepend (GSList *list, struct server *server) {
if (g_slist_find (list, server) == NULL) {
debug (6, "server_list_prepend() -- Server %lx", server);
list = g_slist_prepend (list, server);
server_ref (server);
}
return list;
}
static inline GSList *server_list_append (GSList *list, struct server *s) {
if (g_slist_find (list, s) == NULL) {
list = g_slist_append (list, s);
server_ref (s);
static inline GSList *server_list_append (GSList *list, struct server *server) {
if (g_slist_find (list, server) == NULL) {
debug (6, "server_list_append() -- Server %lx", server);
list = g_slist_append (list, server);
server_ref (server);
}
return list;
}
@ -106,6 +111,7 @@ static inline GSList *userver_list_remove (GSList *list, struct userver *us) {
static inline void server_list_free (GSList *list) {
if (list) {
debug (6, "server_list_free() -- list %lx", list );
g_slist_foreach (list, (GFunc) server_unref, NULL);
g_slist_free (list);
}

View File

@ -356,6 +356,7 @@ static void master_add_server (struct master *m, char *str,
struct server *s;
struct userver *us;
debug (6, "master_add_server() -- Master %lx", m);
if (parse_address (str, &addr, &port)) {
h = host_add (addr);
if (h) { /* IP address */

View File

@ -395,6 +395,7 @@ GSList *server_clist_selected_servers (void) {
GSList *list = NULL;
struct server *s;
debug (6, "server_clist_selected_servers() --");
while (rows) {
s = (struct server *) gtk_clist_get_row_data (
server_clist, (int) rows->data);
@ -405,17 +406,22 @@ GSList *server_clist_selected_servers (void) {
return list;
}
/*
server_clist_all_servers -- Return all servers that are in the server
clist widget. It returns a new list. Note that the prepend function
adds one to the reference count.
*/
GSList *server_clist_all_servers (void) {
GSList *list = NULL;
struct server *s;
struct server *server;
int row;
debug (6, "server_clist_all_servers() -- ");
for (row = 0; row < server_clist->rows; row++) {
s = (struct server *) gtk_clist_get_row_data (server_clist, row);
list = server_list_prepend (list, s);
server = (struct server *) gtk_clist_get_row_data (server_clist, row);
list = server_list_prepend (list, server);
}
debug (7, "server_clist_all_servers() -- Return list %lx", list);
return g_slist_reverse (list);
}
@ -490,7 +496,7 @@ void server_clist_redraw (void) {
void server_clist_set_list (GSList *servers) {
GSList *list;
struct server *s;
struct server *server;
int row;
GSList *filtered;
@ -502,11 +508,17 @@ void server_clist_set_list (GSList *servers) {
if (filtered) {
for (list = filtered; list; list = list->next) {
s = (struct server *) list->data;
row = server_clist_refresh_row (s, -1);
gtk_clist_set_row_data_full (server_clist, row, s,
(GtkDestroyNotify) server_unref);
server_ref (s);
server = (struct server *) list->data;
row = server_clist_refresh_row (server, -1);
gtk_clist_set_row_data_full (server_clist, row, server,
(GtkDestroyNotify) server_unref);
/*
Because the build_filtered_list add a reference count
to the server structure and because we are going
to free that list, we DO NOT need to add a reference
count to the server structure.
*/
/* server_ref (server); */
}
server_list_free (filtered);
@ -522,48 +534,68 @@ void server_clist_set_list (GSList *servers) {
}
void server_clist_build_filtered (GSList *servers, int update) {
void server_clist_build_filtered (GSList *server_list, int update) {
/* This gets called whenever a user clicks the filter button */
GSList *delete;
GSList *add;
GSList *tmp;
struct server *s;
struct server *server;
int row;
debug (6, "server_clist_build_filterd() -- Update? %d", update);
delete = server_clist_all_servers ();
add = build_filtered_list (cur_filter, servers); /* in filter.c */
add = build_filtered_list (cur_filter, server_list); /* in filter.c */
server_lists_intersect (&delete, &add);
gtk_clist_freeze (server_clist);
/*
If there are entries in the server clist, we want to first remove
them. Be sure to decrement the reference count as we will
be adding them back in later.
*/
if (delete) {
debug (7, "server_clist_build_filtered() -- Got Delete %lx", delete);
for (tmp = delete; tmp; tmp = tmp->next) {
s = (struct server *) tmp->data;
row = gtk_clist_find_row_from_data (server_clist, s);
server = (struct server *) tmp->data;
row = gtk_clist_find_row_from_data (server_clist, server);
if (row >= 0) {
gtk_clist_remove (server_clist, row);
debug (3, "server_clist_build_filtered() -- Delete server %lx", server);
}
/*
Allways unref the server because the list returned
to us had the count incremented by prepend.
*/
}
server_list_free (delete);
}
if (update) {
for (row = 0; row < server_clist->rows; row++) {
s = (struct server *) gtk_clist_get_row_data (server_clist, row);
server_clist_refresh_row (s, row);
server = (struct server *) gtk_clist_get_row_data (server_clist, row);
server_clist_refresh_row (server, row);
}
}
/*
Now we want to add all of the servers that we
got from the build_fiter_list function. Note that
the said function adds one to the reference count
for us and since we free that list after we put
the data in the clist, we do NOT need to
do a reference count in this fuction. --baa
*/
if (add) {
for (tmp = add; tmp; tmp = tmp->next) {
s = (struct server *) tmp->data;
row = server_clist_refresh_row (s, -1);
gtk_clist_set_row_data_full (server_clist, row, s,
(GtkDestroyNotify) server_unref);
server_ref (s);
server = (struct server *) tmp->data;
row = server_clist_refresh_row (server, -1);
gtk_clist_set_row_data_full (server_clist, row, server,
(GtkDestroyNotify) server_unref);
/*server_ref (server);*/
}
server_list_free (add);
}

View File

@ -42,7 +42,7 @@
#include "dialogs.h"
#include "host.h"
#include "dns.h"
#include "debug.h"
static void stat_next (struct stat_job *job);
@ -50,6 +50,9 @@ static void stat_next (struct stat_job *job);
static int failed (char *name, char *arg) {
fprintf (stderr, "%s(%s) failed: %s\n", name, (arg)? arg : "",
g_strerror (errno));
debug (0, "%s(%s) failed: %s\n", name, (arg)? arg : "", g_strerror (errno));
return TRUE;
}
@ -57,6 +60,7 @@ static int failed (char *name, char *arg) {
static void stat_free_conn (struct stat_conn *conn) {
struct stat_job *job;
debug (3, "stat_free_conn() -- Conn %lx", conn);
if (!conn || !conn->job)
return;
@ -112,6 +116,8 @@ static int parse_master_output (char *str, struct stat_conn *conn) {
struct host *h;
int len;
debug (6, "parse_master_output() --");
n = tokenize_bychar (str, token, 8, QSTAT_DELIM);
if (n >= 3) {
@ -164,7 +170,12 @@ static int parse_master_output (char *str, struct stat_conn *conn) {
s->type = conn->master->type;
server_free_info (s);
}
/*
o When the "conn" is freed, it will call the function
to free the list returned here
*/
conn->servers = server_list_prepend (conn->servers, s);
}
host_unref (h);
@ -283,7 +294,7 @@ static char **parse_serverinfo (char *token[], int n) {
static struct server *parse_server (char *token[], int n, time_t refreshed,
int saved) {
struct host *h;
struct server *s;
struct server *server;
enum server_type type;
char *addr;
unsigned short port;
@ -304,55 +315,68 @@ static struct server *parse_server (char *token[], int n, time_t refreshed,
if (!h)
return NULL;
s = server_add (h, port, type);
server = server_add (h, port, type);
s->flt_mask &= ~FILTER_SERVER_MASK;
debug (6, "parse_server() -- server %lx retreived", server);
s->refreshed = refreshed;
server->flt_mask &= ~FILTER_SERVER_MASK;
server->refreshed = refreshed;
if (n == 3) {
if (strcmp (token[2], "DOWN") == 0) {
s->retries = MAX_RETRIES;
s->ping = MAX_PING + 1; /* DOWN */
server->retries = MAX_RETRIES;
server->ping = MAX_PING + 1; /* DOWN */
}
else {
s->retries = MAX_RETRIES;
s->ping = MAX_PING; /* TIMEOUT */
server->retries = MAX_RETRIES;
server->ping = MAX_PING; /* TIMEOUT */
}
if (s->players) {
g_slist_foreach (s->players, (GFunc) g_free, NULL);
g_slist_free (s->players);
s->players = NULL;
s->flags &= ~PLAYER_GROUP_MASK;
s->flt_mask &= ~FILTER_PLAYER_MASK;
if (server->players) {
g_slist_foreach (server->players, (GFunc) g_free, NULL);
g_slist_free (server->players);
server->players = NULL;
server->flags &= ~PLAYER_GROUP_MASK;
server->flt_mask &= ~FILTER_PLAYER_MASK;
}
s->curplayers = 0;
server->curplayers = 0;
}
else {
if (s->type == QW_SERVER || type == QW_SERVER)
s->type = type; /* the real type of server (QW <-> Q2) */
/* We did get some information */
if (server->type == QW_SERVER || type == QW_SERVER)
server->type = type; /* the real type of server (QW <-> Q2) */
if (games[s->type].parse_server) {
server_free_info (s);
if (games[server->type].parse_server) {
/*
We have a function to parse the server information,
so first we free all of the data elements of this
structure but not the structure its self. This
is because the *_analyse functions should assign values
to each of the elemets.
*/
server_free_info (server);
s->retries = MAX_RETRIES;
s->ping = MAX_PING; /* TIMEOUT */
server->retries = MAX_RETRIES;
server->ping = MAX_PING; /* TIMEOUT */
(*games[s->type].parse_server) (token, n, s);
/* Actually parse the info with the given function. The mapping
and functions are in game.c
*/
(*games[server->type].parse_server) (token, n, server);
if (s->ping > MAX_PING) {
if (!saved || s->ping != MAX_PING + 1)
s->ping = MAX_PING;
if (server->ping > MAX_PING) {
if (!saved || server->ping != MAX_PING + 1)
server->ping = MAX_PING;
}
if (s->retries > maxretries)
s->retries = maxretries;
if (server->retries > maxretries)
server->retries = maxretries;
}
}
return s;
return server;
}
@ -396,7 +420,7 @@ static void parse_qstat_record_part2 (GSList *strings, struct server *s) {
static void parse_qstat_record (struct stat_conn *conn) {
struct server *s;
struct server *server;
char *token[16];
int n;
GSList *list;
@ -407,27 +431,40 @@ static void parse_qstat_record (struct stat_conn *conn) {
job = conn->job;
/* Debug before tokenizing. */
debug (4, "parse_qstat_record() -- Conn %lx: %s", conn, conn->strings->data);
n = tokenize_bychar ((char *) conn->strings->data, token, 16, QSTAT_DELIM);
if (n < 3)
return; /* error, try to recover */
s = parse_server (token, n, time (NULL), FALSE);
if (s) {
server = parse_server (token, n, time (NULL), FALSE);
if (server) {
job->need_redraw = TRUE;
/*
o The list here is freed when the job is freed.
o The parse_server call above increments the ref
count as does the prepend below. So we need to decrement it
one just for fun.
*/
server_unref (server);
job->delayed.queued_servers =
server_list_prepend (job->delayed.queued_servers, s);
server_list_prepend (job->delayed.queued_servers, server);
job->progress.done++;
parse_qstat_record_part2 (conn->strings->next, s);
debug (6, "parse_qstat_record() -- Server %lx in delayed list %lx.", server, job->delayed.queued_servers);
parse_qstat_record_part2 (conn->strings->next, server);
for (list = job->server_handlers; list; list = list->next)
(* (server_func) list->data) (job, s);
(* (server_func) list->data) (job, server);
}
}
void parse_saved_server (GSList *strings) {
struct server *s;
struct server *server;
char *token[16];
int n;
time_t refreshed;
@ -442,17 +479,17 @@ void parse_saved_server (GSList *strings) {
return;
strings = strings->next;
debug (3, "parse_saved_server() -- ");
n = tokenize_bychar ((char *) strings->data, token, 16, QSTAT_DELIM);
if (n < 3)
return;
s = parse_server (token, n, refreshed, TRUE);
server = parse_server (token, n, refreshed, TRUE);
if (s) {
server_ref (s);
parse_qstat_record_part2 (strings->next, s);
server_unref (s);
if (server) {
server_ref (server);
parse_qstat_record_part2 (strings->next, server);
server_unref (server);
}
}
@ -466,12 +503,19 @@ static void adjust_pointers (GSList *list, gpointer new, gpointer old) {
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);
conn->job->servers = NULL;
stat_free_conn (conn);
}
/*
stat_server_input_callback -- as data is returned from the qstat
process, this gets called. Sometimes there are multiple lines
so the results have to be looped over.
*/
static void stat_servers_input_callback (struct stat_conn *conn, int fd,
GdkInputCondition condition) {
struct stat_job *job = conn->job;
@ -479,7 +523,7 @@ static void stat_servers_input_callback (struct stat_conn *conn, int fd,
int blocked = FALSE;
char *tmp;
int res;
/* debug (3, "stat_servers_input_callback() -- Conn %lx", conn); */
while (1) {
first_used = 0;
blocked = FALSE;
@ -507,6 +551,7 @@ static void stat_servers_input_callback (struct stat_conn *conn, int fd,
return;
}
if (res == 0) { /* EOF */
debug (3, "stat_servers_input_callback() -- Conn %ld Sub Process Done with server list %lx", conn, conn->job->servers);
stat_servers_update_done (conn);
stat_next (job);
return;
@ -572,8 +617,14 @@ static void set_nonblock (int fd) {
}
/*
start_qstat -- Fork and run qstat with the given command line
options. Returns a "conn?"
*/
static struct stat_conn *start_qstat (struct stat_job *job, char *argv[],
GdkInputFunction input_callback, struct master *m) {
struct stat_conn *conn;
pid_t pid;
int pipefds[2];
@ -581,14 +632,9 @@ static struct stat_conn *start_qstat (struct stat_job *job, char *argv[],
QSTAT_DELIM_STR
"ERROR" QSTAT_DELIM_STR
"command not found\n";
#ifdef DEBUG
int i;
fprintf (stderr, "exec(): ");
for (i = 0; argv[i]; ++i)
fprintf (stderr, "%s ", argv[i]);
fprintf (stderr, "\n");
#endif
debug (3, "start_qstat() -- Job %lx Setting up/forking pipes to qstat", job);
debug_cmd (3, argv, "start_qstat() -- Job %lx", job);
if (pipe (pipefds) < 0) {
failed ("pipe", NULL);
@ -651,7 +697,7 @@ static void stat_close (struct stat_job *job, int killed) {
dns_set_callback (NULL, NULL);
dns_cancel_requests ();
debug (3, "stat_close() -- Job %lx Killed? %d", job, killed);
while (job->cons)
stat_free_conn ((struct stat_conn *) job->cons->data);
@ -679,6 +725,7 @@ static struct stat_conn *stat_update_master_qstat (struct stat_job *job,
struct stat_conn *conn;
char *cmd = NULL;
debug (3, "stat_upate_master_qstat() -- Master %lx", m);
if (!m)
return NULL;
@ -722,6 +769,15 @@ static struct stat_conn *stat_update_master_qstat (struct stat_job *job,
} /* if (m->url) */
if (get_debug_level() > 3){
char **argptr = argv;
fprintf (stderr, "stat_update_master_qstat: EXEC> ");
while (*argptr)
fprintf (stderr, "%s ", *argptr++);
fprintf (stderr, "\n");
}
conn = start_qstat (job, argv,
(GdkInputFunction) stat_master_input_callback, m);
if (cmd)
@ -747,7 +803,14 @@ static struct stat_conn *stat_open_conn_qstat (struct stat_job *job) {
if (!job->servers)
return NULL;
/*
The g_slist_reverse does not allocate any new
lists or memory. However, it means that job->servers
will point to a different member.
*/
debug (6, "stat_open_conn_qstat() -- server list was %lx", job->servers );
job->servers = g_slist_reverse (job->servers);
debug (6, "stat_open_conn_qstat() -- server list now %lx", job->servers );
argv[argi++] = QSTAT_EXEC;
@ -871,7 +934,7 @@ static void stat_update_masters (struct stat_job *job) {
#ifdef DEBUG
fprintf (stderr, "stat_update_masters() -- freecons: %d\n", freecons);
#endif
debug (3, "stat_update_masters() -- freecons: %d", freecons);
tmp = job->masters;
while (tmp && freecons > 0) {
@ -970,7 +1033,7 @@ static void stat_name_resolved_callback (char *id, struct host *h,
return;
list = job->names;
debug (6, "stat_name_resolved_callback() --");
while (list) {
us = (struct userver *) list->data;
if (strcmp (us->hostname, id) == 0) {
@ -986,6 +1049,11 @@ static void stat_name_resolved_callback (char *id, struct host *h,
server_free_info (us->s);
}
/*
o When the job is freed, the list will
be freed as well. This will take care of
the reference counting.
*/
job->servers = server_list_prepend (job->servers, us->s);
}
@ -1069,12 +1137,12 @@ static void stat_next (struct stat_job *job) {
struct host *h;
#ifdef DEBUG
fprintf (stderr, "stat_next\n");
fprintf (stderr, "stat_next() -- \n");
#endif
job->progress.done = 0;
if (job->masters) {
debug (3, "stat_next() -- Job %lx Have job->masters", job );
job->state = STAT_UPDATE_SOURCE;
move_q2masters_to_top (&job->masters);
@ -1112,6 +1180,7 @@ static void stat_next (struct stat_job *job) {
}
if (job->names) {
debug (3, "stat_next() -- Job %lx job->names", job );
job->state = STAT_RESOLVE_NAMES;
for (list = job->names; list; list = list->next) {
@ -1140,6 +1209,7 @@ static void stat_next (struct stat_job *job) {
if (job->servers) {
debug (3, "stat_next() -- Servers: Job %lx server list %lx", job, job->servers );
if (!job->need_refresh) {
stat_close (job, FALSE);
return;
@ -1156,13 +1226,16 @@ static void stat_next (struct stat_job *job) {
if (!stat_open_conn_qstat (job)) {
/* It's very bad, stop everything. */
debug (1, "job_next() -- Error! Could not stat_open_conn_qstat()");
stat_close (job, TRUE);
}
return;
}
if (job->hosts) {
debug (3, "stat_next() -- Job %lx job->hosts", job);
job->state = STAT_RESOLVE_HOSTS;
dns_set_callback (stat_host_resolved_callback, job);
@ -1177,6 +1250,8 @@ static void stat_next (struct stat_job *job) {
return;
}
debug (3, "stat_next() -- Job %lx Job Done, Closing the job...", job);
stat_close (job, FALSE);
}
@ -1187,6 +1262,7 @@ void stat_start (struct stat_job *job) {
fprintf (stderr, "stat_start()\n");
#endif
debug (3, "stat_start() -- Job %lx", job);
if (job->delayed.refresh_handler) {
job->delayed.timeout_id = gtk_timeout_add (1000,
job->delayed.refresh_handler, job);
@ -1201,7 +1277,7 @@ void stat_stop (struct stat_job *job) {
#ifdef DEBUG
fprintf (stderr, "stat_stop()\n");
#endif
debug (3, "stat_stop() -- Job %lx", job);
stat_close (job, TRUE);
}
@ -1211,6 +1287,7 @@ struct stat_job *stat_job_create (GSList *masters, GSList *names,
struct stat_job *job;
job = g_malloc (sizeof (struct stat_job));
debug (3, "stat_job_create() -- New Job %lx Server List %lx", job, servers);
job->masters = masters;
job->hosts = hosts;
job->servers = servers;
@ -1248,6 +1325,8 @@ struct stat_job *stat_job_create (GSList *masters, GSList *names,
void stat_job_free (struct stat_job *job) {
debug (3, "stat_job_free() -- Job %lx server list %lx", job, job->servers);
if (job->masters) g_slist_free (job->masters);
if (job->servers) server_list_free (job->servers);
if (job->hosts) host_list_free (job->hosts);

View File

@ -541,6 +541,8 @@ static void stat_lists (GSList *masters, GSList *names, GSList *servers,
if (stat_process || (!masters && !names && !servers && !hosts))
return;
debug (7, "stat_lists() -- Server List %lx", servers);
stat_process = stat_job_create (masters, names, servers, hosts);
stat_process->delayed.refresh_handler = (GtkFunction) stat_lists_refresh;
@ -560,11 +562,12 @@ static void stat_lists (GSList *masters, GSList *names, GSList *servers,
}
static void stat_one_server (struct server *s) {
static void stat_one_server (struct server *server) {
GSList *list;
if (!stat_process && s) {
list = server_list_prepend (NULL, s);
debug (6, "stat_one_server() -- Server %lx", server);
if (!stat_process && server) {
list = server_list_prepend (NULL, server);
stat_lists (NULL, NULL, list, NULL);
}
}
@ -756,6 +759,7 @@ static void launch_callback (GtkWidget *widget, enum launch_mode mode) {
char *demo = NULL;
struct condef *con = NULL;
debug (6, "launc_callback() --");
if (stat_process || !cur_server ||
(games[cur_server->type].flags & GAME_CONNECT) == 0) {
return;
@ -892,9 +896,13 @@ static void refresh_callback (GtkWidget *widget, gpointer data) {
if (stat_process)
return;
debug (7, "refresh_callback() -- Get Server List");
servers = server_clist_all_servers ();
uservers = userver_list_copy (cur_userver_list);
debug (7, "refresh_callback() -- server list %lx", servers);
if (servers || uservers) {
stat_lists (NULL, uservers, servers, NULL);
}
@ -993,6 +1001,8 @@ static void add_server_callback (GtkWidget *widget, gpointer data) {
struct userver *us = NULL;
enum server_type type;
debug (6, "add_server_callback() -- ");
if (stat_process)
return;