From 87f6008da6f23a673f85c427cd9ea03f25a69321 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Thu, 30 Jan 2003 23:03:52 +0000 Subject: [PATCH] db_dump svn path=/trunk/boinc/; revision=849 --- checkin_notes | 21 ++ db/db.h | 20 +- db/db_mysql.C | 93 +++++- db/mysql_util.C | 3 +- db/mysql_util.h | 2 +- db/schema.sql | 19 +- doc/stripchart.html | 25 ++ doc/stripchart_data.html | 13 + html/user/team_create_action.php | 6 +- lib/util.C | 61 +++- lib/util.h | 2 + sched/Makefile.in | 10 +- sched/db_dump.C | 471 +++++++++++++++++++++++++++++-- todo | 2 + 14 files changed, 707 insertions(+), 41 deletions(-) create mode 100644 doc/stripchart.html create mode 100644 doc/stripchart_data.html diff --git a/checkin_notes b/checkin_notes index e5a2cceff4..cb05de0d5d 100755 --- a/checkin_notes +++ b/checkin_notes @@ -3043,3 +3043,24 @@ David Jan 29 2003 sched/ db_dump.C (new) Makefile.in + +David Jan 30 2003 + - continued work on db_dump + - added doc for db_dump + - added create_time field to team table + + db/ + db.h + db_mysql.C + mysql_util.C,h + doc/ + db_dump.html (new) + stripchart.html (new) + stripchart_data.html (new) + html_user/ + team_create_action.php + lib/ + util.C,h + sched/ + Makefile.in + db_dump.C diff --git a/db/db.h b/db/db.h index 6f132c4b2f..7fab1c995a 100644 --- a/db/db.h +++ b/db/db.h @@ -122,6 +122,7 @@ struct USER { struct TEAM { int id; + unsigned int create_time; int userid; // User ID of team founder char name[256]; char name_lc[256]; // Team name in lowercase (used for searching) @@ -129,8 +130,10 @@ struct TEAM { int type; // Team type (see above) char name_html[256]; char description[MAX_BLOB_SIZE]; - int nusers; + int nusers; // UNDEFINED BY DEFAULT char country[256]; + double total_credit; // UNDEFINED BY DEFAULT + double expavg_credit; // UNDEFINED BY DEFAULT }; struct HOST { @@ -322,18 +325,33 @@ extern int db_app_version_enum(APP_VERSION&); extern int db_user_new(USER&); extern int db_user(int, USER&); extern int db_user_update(USER&); +extern int db_user_count(int&); extern int db_user_lookup_auth(USER&); extern int db_user_lookup_email_addr(USER&); +extern int db_user_enum_id(USER&); +extern int db_user_enum_total_credit(USER&); +extern int db_user_enum_expavg_credit(USER&); +extern int db_user_enum_teamid(USER&); extern int db_team(int, TEAM&); extern int db_team_new(TEAM&); extern int db_team_update(TEAM&); +extern int db_team_count(int&); extern int db_team_lookup_name(TEAM&); extern int db_team_lookup_name_lc(TEAM&); +extern int db_team_enum(TEAM&); +extern int db_team_enum_id(TEAM&); +extern int db_team_enum_total_credit(TEAM&); +extern int db_team_enum_expavg_credit(TEAM&); extern int db_host_new(HOST& p); extern int db_host(int, HOST&); extern int db_host_update(HOST&); +extern int db_host_count(int&); +extern int db_host_enum_id(HOST&); +extern int db_host_enum_userid(HOST&); +extern int db_host_enum_total_credit(HOST&); +extern int db_host_enum_expavg_credit(HOST&); extern int db_workunit_new(WORKUNIT& p); extern int db_workunit(int id, WORKUNIT&); diff --git a/db/db_mysql.C b/db/db_mysql.C index 5322dd0736..4e94ae8e8b 100644 --- a/db/db_mysql.C +++ b/db/db_mysql.C @@ -173,11 +173,12 @@ void BOINC_MYSQL_DB::struct_to_str(void* vp, char* q, int type) { case TYPE_TEAM: tp = (TEAM*)vp; sprintf(q, - "id=%d, userid=%d, name='%s', " + "id=%d, create_time=%d, userid=%d, name='%s', " "name_lc='%s', url='%s', " "type=%d, name_html='%s', description='%s', nusers=%d, " - "country='%s'", + "country='%s', total_credit=%f, expavg_credit=%f", tp->id, + tp->create_time, tp->userid, tp->name, tp->name_lc, @@ -186,7 +187,9 @@ void BOINC_MYSQL_DB::struct_to_str(void* vp, char* q, int type) { tp->name_html, tp->description, tp->nusers, - tp->country + tp->country, + tp->total_credit, + tp->expavg_credit ); break; case TYPE_HOST: @@ -352,6 +355,7 @@ void BOINC_MYSQL_DB::row_to_struct(MYSQL_ROW& r, void* vp, int type) { tp = (TEAM*)tp; memset(tp, 0, sizeof(TEAM)); tp->id = atoi(r[i++]); + tp->create_time = atoi(r[i++]); tp->userid = atoi(r[i++]); strcpy2(tp->name, r[i++]); strcpy2(tp->name_lc, r[i++]); @@ -360,6 +364,8 @@ void BOINC_MYSQL_DB::row_to_struct(MYSQL_ROW& r, void* vp, int type) { strcpy2(tp->description, r[i++]); tp->nusers = atoi(r[i++]); strcpy2(tp->country, r[i++]); + tp->total_credit = atof(r[i++]); + tp->expavg_credit = atof(r[i++]); break; case TYPE_HOST: hp = (HOST*)vp; @@ -557,6 +563,10 @@ int db_user_lookup_auth(USER& p) { return boinc_db.db_lookup(&p, TYPE_USER, buf); } +int db_user_count(int& n) { + return boinc_db.db_count(&n, "*", TYPE_USER); +} + int db_user_lookup_email_addr(USER& p) { char buf[256]; @@ -564,6 +574,30 @@ int db_user_lookup_email_addr(USER& p) { return boinc_db.db_lookup(&p, TYPE_USER, buf); } +int db_user_enum_id(USER& p) { + static ENUM e; + return boinc_db.db_enum(e, &p, TYPE_TEAM, "order by id"); +} +int db_user_enum_total_credit(USER& p) { + static ENUM e; + return boinc_db.db_enum(e, &p, TYPE_TEAM, "order by total_credit desc"); +} + +int db_user_enum_expavg_credit(USER& p) { + static ENUM e; + return boinc_db.db_enum(e, &p, TYPE_USER, "order by expavg_credit desc"); +} + +int db_user_enum_teamid(USER& p) { + static ENUM e; + char buf[256]; + + if (!e.active) { + sprintf(buf, "where teamid=%d", p.teamid); + } + return boinc_db.db_enum(e, &p, TYPE_USER, buf); +} + ////////// TEAM ///////// int db_team(int i, TEAM& p) { @@ -578,6 +612,10 @@ int db_team_update(TEAM& p) { return boinc_db.db_update(&p, TYPE_TEAM); } +int db_team_count(int& n) { + return boinc_db.db_count(&n, "*", TYPE_TEAM); +} + int db_team_lookup_name(TEAM& p) { char buf[256]; @@ -592,6 +630,26 @@ int db_team_lookup_name_lc(TEAM& p) { return boinc_db.db_lookup(&p, TYPE_TEAM, buf); } +int db_team_enum(TEAM& p) { + static ENUM e; + return boinc_db.db_enum(e, &p, TYPE_TEAM); +} + +int db_team_enum_id(TEAM& p) { + static ENUM e; + return boinc_db.db_enum(e, &p, TYPE_TEAM, "order by id"); +} + +int db_team_enum_total_credit(TEAM& p) { + static ENUM e; + return boinc_db.db_enum(e, &p, TYPE_TEAM, "order by total_credit desc"); +} + +int db_team_enum_expavg_credit(TEAM& p) { + static ENUM e; + return boinc_db.db_enum(e, &p, TYPE_TEAM, "order by expavg_credit desc"); +} + ////////// HOST ///////// int db_host_new(HOST& p) { @@ -602,10 +660,39 @@ int db_host(int i, HOST& p) { return boinc_db.db_lookup_id(i, &p, TYPE_HOST); } +int db_host_count(int& n) { + return boinc_db.db_count(&n, "*", TYPE_HOST); +} + int db_host_update(HOST& p) { return boinc_db.db_update(&p, TYPE_HOST); } +int db_host_enum_id(HOST& p) { + static ENUM e; + return boinc_db.db_enum(e, &p, TYPE_HOST, "order by id"); +} + +int db_host_enum_userid(HOST& p) { + static ENUM e; + char buf[256]; + + if (!e.active) { + sprintf(buf, "where userid=%d", p.userid); + } + return boinc_db.db_enum(e, &p, TYPE_HOST, buf); +} + +int db_host_enum_total_credit(HOST& p) { + static ENUM e; + return boinc_db.db_enum(e, &p, TYPE_HOST, "order by total_credit desc"); +} + +int db_host_enum_expavg_credit(HOST& p) { + static ENUM e; + return boinc_db.db_enum(e, &p, TYPE_HOST, "order by expavg_credit desc"); +} + ////////// WORKUNIT ///////// int db_workunit_new(WORKUNIT& p) { diff --git a/db/mysql_util.C b/db/mysql_util.C index e30840821b..355f7d4853 100644 --- a/db/mysql_util.C +++ b/db/mysql_util.C @@ -192,7 +192,8 @@ int MYSQL_DB::db_query_int(int* ip, char* query) { int MYSQL_DB::db_count(int* np, char* what, int type, char* clause) { char buf[MAX_QUERY_LEN]; - sprintf(buf, "select count(%s) from %s %s", what, table_name[type], clause); + sprintf(buf, "select count(%s) from %s ", what, table_name[type]); + if (clause) strcat(buf, clause); return db_query_int(np, buf); } diff --git a/db/mysql_util.h b/db/mysql_util.h index d73905fcf9..788cf66a4f 100644 --- a/db/mysql_util.h +++ b/db/mysql_util.h @@ -49,6 +49,6 @@ public: int db_enum(ENUM&, void*, int, char* clause=0, int limit=0); int db_enum_field(ENUM&, int, char*, char*); int db_query_int(int*, char*); - int db_count(int*, char*, int, char*); + int db_count(int*, char*, int, char* clause=0); int db_query(char*); }; diff --git a/db/schema.sql b/db/schema.sql index 5b6f5a7812..8988904c33 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -49,20 +49,21 @@ create table user ( expavg_time double not null, global_prefs blob, project_prefs blob, - teamid integer not null, + teamid integer not null, primary key (id) ); create table team ( - id integer not null auto_increment, - userid integer not null, - name varchar(254) not null, - name_lc varchar(254), - url varchar(254), - type integer not null, - name_html varchar(254), + id integer not null auto_increment, + create_time integer not null, + userid integer not null, + name varchar(254) not null, + name_lc varchar(254), + url varchar(254), + type integer not null, + name_html varchar(254), description blob, - nusers integer not null, + nusers integer not null, /* temp */ country varchar(254), total_credit double not null, /* temp */ expavg_credit double not null, /* temp */ diff --git a/doc/stripchart.html b/doc/stripchart.html new file mode 100644 index 0000000000..f7d657ec2b --- /dev/null +++ b/doc/stripchart.html @@ -0,0 +1,25 @@ +Stripcharts +

Stripcharts

+ +

Goals

+

+Stripcharts is a system for recording and displaying +time-varying system load and performance information. +The basic idea: + +

+Looking at these graphs can be a major help in tracking +down problems in complex server systems. + +

+Stripcharts is independent of BOINC, +but it's especially helpful for diagnosing performance +problems in BOINC servers. diff --git a/doc/stripchart_data.html b/doc/stripchart_data.html new file mode 100644 index 0000000000..026c8c1f73 --- /dev/null +++ b/doc/stripchart_data.html @@ -0,0 +1,13 @@ +Stripchar data +

Stripchar data

+ + diff --git a/html/user/team_create_action.php b/html/user/team_create_action.php index fe0f91958c..1155b1393e 100644 --- a/html/user/team_create_action.php +++ b/html/user/team_create_action.php @@ -16,8 +16,9 @@ echo "You must specify a name for your team."; } else { $query = sprintf( - "insert into team (userid, name, name_lc, url, type, name_html, description, nusers) values(%d, '%s', '%s', '%s', %d, '%s', '%s', %d)", + "insert into team (userid, create_time, name, name_lc, url, type, name_html, description, nusers) values(%d, '%s', '%s', '%s', %d, '%s', '%s', %d)", $user->id, + time(), $HTTP_POST_VARS["name"], strtolower($HTTP_POST_VARS["name"]), $HTTP_POST_VARS["url"], @@ -69,6 +70,5 @@ page_tail(); } } -} + } ?> - diff --git a/lib/util.C b/lib/util.C index 9d167e071b..0ea9a32697 100755 --- a/lib/util.C +++ b/lib/util.C @@ -140,7 +140,7 @@ int parse_command_line(char* p, char** argv) { } else { if (space) { *pp++ = p; - argc++; + argc++; space = false; } } @@ -180,3 +180,62 @@ int lock_file(char* filename) { double drand() { return (double)rand()/(double)RAND_MAX; } + +static char x2c(char *what) { + register char digit; + + digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0')); + digit *= 16; + digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0')); + return(digit); +} + +static void c2x(char *what) { + char buf[3]; + char num = atoi(what); + char d1 = num / 16; + char d2 = num % 16; + int abase1, abase2; + if (d1 < 10) abase1 = 48; + else abase1 = 55; + if (d2 < 10) abase2 = 48; + else abase2 = 55; + buf[0] = d1+abase1; + buf[1] = d2+abase2; + buf[2] = 0; + + strcpy(what, buf); +} + +void unescape_url(char *url) { + register int x,y; + + for(x=0,y=0;url[y];++x,++y) { + if((url[x] = url[y]) == '%') { + url[x] = x2c(&url[y+1]); + y+=2; + } + } + url[x] = '\0'; +} + +void escape_url(char *in, char*out) { + int x, y; + for (x=0, y=0; in[x]; ++x) { + if (isalnum(in[x])) { + out[y] = in[x]; + ++y; + } else { + out[y] = '%'; + ++y; + out[y] = 0; + char buf[256]; + sprintf(buf, "%d", (char)in[x]); + c2x(buf); + strcat(out, buf); + y += 2; + } + } + out[y] = 0; +} + diff --git a/lib/util.h b/lib/util.h index a910c42c95..e5a34af1d2 100755 --- a/lib/util.h +++ b/lib/util.h @@ -25,6 +25,8 @@ extern void boinc_sleep( int seconds ); extern int parse_command_line( char *, char ** ); extern int lock_file(char*); extern double drand(); +extern void unescape_url(char *url); +extern void escape_url(char *in, char*out); #ifndef max #define max(a,b) (((a) > (b)) ? (a) : (b)) diff --git a/sched/Makefile.in b/sched/Makefile.in index ad94c66cfa..9f6c5e2f18 100644 --- a/sched/Makefile.in +++ b/sched/Makefile.in @@ -110,8 +110,11 @@ RESULT_RETRY_OBJS = \ ../RSAEuro/source/rsaeuro.a DB_DUMP_OBJS = \ - ../db/db_mysql.fcgi.o \ - ../db/mysql_util.fcgi.o \ + ../db/db_mysql.o \ + ../db/mysql_util.o \ + ../lib/parse.o \ + ../lib/util.o \ + config.o \ db_dump.o FCGI_OBJS = \ @@ -176,6 +179,9 @@ file_deleter: $(FILE_DELETER_OBJS) assimilator: $(ASSIMILATOR_OBJS) $(CC) $(ASSIMILATOR_OBJS) $(MYSQL_LIBS) $(CLIBS) -o assimilator +db_dump: $(DB_DUMP_OBJS) + $(CC) $(DB_DUMP_OBJS) $(MYSQL_LIBS) $(CLIBS) -o db_dump + fcgi: $(FCGI_OBJS) $(CC) $(FCGI_OBJS) $(MYSQL_LIBS) $(CLIBS) $(FCGI_LIBS) \ -o fcgi diff --git a/sched/db_dump.C b/sched/db_dump.C index 827438578b..be650bc990 100644 --- a/sched/db_dump.C +++ b/sched/db_dump.C @@ -17,31 +17,214 @@ // Contributor(s): // -// db_dump: dump parts of database in XML form +// db_dump: dump database views in XML format +// +// usage: db_dump [-dir path] [-update_teams] // files: +// NOTE: the goal is to make the full DB available (view *_id files) +// to those who want it, +// while allowing those who want to see only a particular row, +// or the highest-ranked rows, to get this info with limited transfer // -// team_totalcredit_N.xml N = 0, 1, ... -// team_avgcredit_N.xml N = 0, 1, ... -// user_totalcredit_N.xml N = 0, 1, ... -// user_avgcredit_N.xml N = 0, 1, ... -// user_team_N.xml N = team ID -// host_user_N.xml N = user ID -// host_totalcredit_N.xml N = 0, 1, ... -// host_avgcredit_N.xml N = 0, 1, ... +// +// tables.xml +// for each table (team, user, host): +// total number of records +// number of records per file for summary files +// number of records per file for detailed files +// team_total_credit_N.xml +// list of teams by decreasing total credit (summary) +// team_expavg_credit_N.xml +// team_id_N.xml +// teams by ID (detailed, including list of user summaries) +// user_total_credit_N.xml +// list of users by total credit (summary) +// user_expavg_credit_N.xml +// user_id_N.xml +// users by ID (detailed, including list of host summaries) +// host_total_credit_N.xml +// hosts by decreasing total credit (summary) +// host_expavg_credit_N.xml +// host_id_N.xml +// hosts by ID (detailed) + +// NOTE: for now we're using verbose XML tag names. +// We may change to short tag names to save bandwidth. #include +#include #include "db.h" +#include "util.h" #include "config.h" -void write_team(TEAM& team, FILE* f) { +#define NRECS_PER_FILE_SUMMARY 1000 +#define NRECS_PER_FILE_DETAIL 100 + +// fill in the nusers, total_credit and expavg_credit fields +// of the team table. +// This may take a while; don't do it often +// +int update_teams() { + TEAM team; + USER user; + int retval; + + while (!db_team_enum(team)) { + team.nusers = 0; + team.total_credit = 0; + team.expavg_credit = 0; + user.teamid = team.id; + while (!db_user_enum_teamid(user)) { + team.nusers++; + team.total_credit += user.total_credit; + team.expavg_credit += user.expavg_credit; + } + retval = db_team_update(team); + if (retval) return retval; + } + return 0; +} + +void write_host(HOST& host, FILE* f, bool detail) { fprintf(f, - "" + "\n" + " %d\n" + " %d\n" + " %f\n" + " %f\n" + " %s\n" + " %s\n" + " %s\n" + " %s\n", + host.id, + host.userid, + host.total_credit, + host.expavg_credit, + host.p_vendor, + host.p_model, + host.os_name, + host.os_version + ); + if (detail) { + fprintf(f, + " %d\n" + " %d\n" + " %d\n" + " %f\n" + " %f\n" + " %f\n" + " %f\n" + " %f\n" + " %f\n" + " %f\n" + " %f\n" + " %f\n" + " %f\n", + host.create_time, + host.timezone, + host.p_ncpus, + host.p_fpops, + host.p_iops, + host.p_membw, + host.m_nbytes, + host.m_cache, + host.m_swap, + host.d_total, + host.d_free, + host.n_bwup, + host.n_bwdown + ); + } + fprintf(f, + "\n" ); } -void team_totalcredit() { +void write_user(USER& user, FILE* f, bool detail) { + HOST host; + fprintf(f, + "\n" + " %d\n" + " %s\n" + " %f\n" + " %f\n" + " %d\n", + user.id, + user.name, + user.total_credit, + user.expavg_credit, + user.teamid + ); + if (detail) { + host.userid = user.id; + while (!db_host_enum_userid(host)) { + write_host(host, f, false); + } + } + fprintf(f, + "\n" + ); +} + +void write_team(TEAM& team, FILE* f, bool detail) { + USER user; + char buf[MAX_BLOB_SIZE*2]; + + fprintf(f, + "\n" + " %d\n" + " %s\n" + " %f\n" + " %f\n" + " %d\n", + team.id, + team.name, + team.total_credit, + team.expavg_credit, + team.nusers + ); + if (detail) { + fprintf(f, + " %d\n", + team.create_time + ); + if (strlen(team.url)) { + fprintf(f, + " %s\n", + team.url + ); + } + if (strlen(team.name_html)) { + escape_url(team.name_html, buf); + fprintf(f, + "%s\n", + buf + ); + } + if (strlen(team.description)) { + escape_url(team.description, buf); + fprintf(f, + "%s\n", + buf + ); + } + fprintf(f, + " %s\n", + team.country + ); + user.teamid = team.id; + while (!db_user_enum_teamid(user)) { + write_user(user, f, false); + } + } + fprintf(f, + "\n" + ); +} + +void team_total_credit() { TEAM team; FILE* f; int nfile=0, nrec; @@ -49,24 +232,248 @@ void team_totalcredit() { while (!db_team_enum_total_credit(team)) { if (!f) { - sprintf(buf, "team_totalcredit_%d", nf); + sprintf(buf, "team_total_credit_%d", nfile); f = fopen(buf, "w"); - nf++; + nfile++; nrec = 0; } - write_team(team, f); + write_team(team, f, false); nrec++; - if (nrec == NRECS_PER_FILE) { + if (nrec == NRECS_PER_FILE_SUMMARY) { fclose(f); f = 0; } } } -main() { - CONFIG config; - int retval; +void team_expavg_credit() { + TEAM team; + FILE* f; + int nfile=0, nrec; + char buf[256]; + while (!db_team_enum_expavg_credit(team)) { + if (!f) { + sprintf(buf, "team_expavg_credit_%d", nfile); + f = fopen(buf, "w"); + nfile++; + nrec = 0; + } + write_team(team, f, false); + nrec++; + if (nrec == NRECS_PER_FILE_SUMMARY) { + fclose(f); + f = 0; + } + } +} + +void team_id() { + TEAM team; + FILE* f; + int nfile=0, nrec; + char buf[256]; + + while (!db_team_enum_id(team)) { + if (!f) { + sprintf(buf, "team_id_%d", nfile); + f = fopen(buf, "w"); + nfile++; + nrec = 0; + } + write_team(team, f, true); + nrec++; + if (nrec == NRECS_PER_FILE_DETAIL) { + fclose(f); + f = 0; + } + } +} + +void user_total_credit() { + USER user; + FILE* f; + int nfile=0, nrec; + char buf[256]; + + while (!db_user_enum_total_credit(user)) { + if (!f) { + sprintf(buf, "user_total_credit_%d", nfile); + f = fopen(buf, "w"); + nfile++; + nrec = 0; + } + write_user(user, f, false); + nrec++; + if (nrec == NRECS_PER_FILE_SUMMARY) { + fclose(f); + f = 0; + } + } +} + +void user_expavg_credit() { + USER user; + FILE* f; + int nfile=0, nrec; + char buf[256]; + + while (!db_user_enum_expavg_credit(user)) { + if (!f) { + sprintf(buf, "user_expavg_credit_%d", nfile); + f = fopen(buf, "w"); + nfile++; + nrec = 0; + } + write_user(user, f, false); + nrec++; + if (nrec == NRECS_PER_FILE_SUMMARY) { + fclose(f); + f = 0; + } + } +} + +void user_id() { + USER user; + FILE* f; + int nfile=0, nrec; + char buf[256]; + + while (!db_user_enum_id(user)) { + if (!f) { + sprintf(buf, "user_id_%d", nfile); + f = fopen(buf, "w"); + nfile++; + nrec = 0; + } + write_user(user, f, true); + nrec++; + if (nrec == NRECS_PER_FILE_DETAIL) { + fclose(f); + f = 0; + } + } +} + +void host_total_credit() { + HOST host; + FILE* f; + int nfile=0, nrec; + char buf[256]; + + while (!db_host_enum_total_credit(host)) { + if (!f) { + sprintf(buf, "host_total_credit_%d", nfile); + f = fopen(buf, "w"); + nfile++; + nrec = 0; + } + write_host(host, f, false); + nrec++; + if (nrec == NRECS_PER_FILE_SUMMARY) { + fclose(f); + f = 0; + } + } +} +void host_expavg_credit() { + HOST host; + FILE* f; + int nfile=0, nrec; + char buf[256]; + + while (!db_host_enum_expavg_credit(host)) { + if (!f) { + sprintf(buf, "host_expavg_credit_%d", nfile); + f = fopen(buf, "w"); + nfile++; + nrec = 0; + } + write_host(host, f, false); + nrec++; + if (nrec == NRECS_PER_FILE_SUMMARY) { + fclose(f); + f = 0; + } + } +} + +void host_id() { + HOST host; + FILE* f; + int nfile=0, nrec; + char buf[256]; + + while (!db_host_enum_id(host)) { + if (!f) { + sprintf(buf, "host_id_%d", nfile); + f = fopen(buf, "w"); + nfile++; + nrec = 0; + } + write_host(host, f, true); + nrec++; + if (nrec == NRECS_PER_FILE_DETAIL) { + fclose(f); + f = 0; + } + } +} + +int tables_file() { + int nusers, nteams, nhosts; + int retval; + FILE* f; + + f = fopen("tables.xml", "w"); + if (!f) return -1; + retval = db_user_count(nusers); + if (retval) return retval; + retval = db_team_count(nteams); + if (retval) return retval; + retval = db_host_count(nhosts); + if (retval) return retval; + fprintf(f, + "\n" + " %d\n" + " %d\n" + " %d\n" + " %d\n" + " %d\n" + " %d\n" + " %d\n" + " %d\n" + " %d\n" + "\n", + nusers, + NRECS_PER_FILE_SUMMARY, + NRECS_PER_FILE_DETAIL, + nteams, + NRECS_PER_FILE_SUMMARY, + NRECS_PER_FILE_DETAIL, + nhosts, + NRECS_PER_FILE_SUMMARY, + NRECS_PER_FILE_DETAIL + ); + fclose(f); + return 0; +} + +int main(int argc, char** argv) { + CONFIG config; + int retval, i; + bool do_update_teams = false; + char dir[256]; + + strcpy(dir, ""); + for (i=1; i