Commit 554e4c59 authored by Per Cederqvist's avatar Per Cederqvist

Wrap all file pointers that refer to the database files inside a

"struct dbfile".  Add a database version field to that struct, and
remove the global database format variables.  This allows lyskomd
to have files in different versions open at the same time, so that
it can convert format X to format X+1 on the fly.  (This is more
preparation for bug 1616.)
* src/server/ram-io.h (struct dbfile): New struct.
(dbfile_delete): New function.
(set_output_format): New function.
(dbfile_open_write): New function.
(dbfile_open_read): New function.
(dump_dbfile_stats): New function.
(dbfile_ftell): The argument is now a struct dbfile*, not FILE*.
(dbfile_getc): Ditto.
(dbfile_ungetc): Ditto.
* src/server/ram-io.c (output_format): Moved from ram-output.c and
made static variable.  This defines the output format of all
struct dbfile objects created after a change to the variable.
(nr_dbfile_objects): New static statistics variable.
(nr_dbfile_files): New static statistics variable.
(dbfile_new): New static function.
(dbfile_delete): New function.
(set_output_format): Moved from ram-output.c.
(get_version): Moved from simple-cache.c.  Changed return type to
int.  The argument is an open dbfile, not a file name.  Use
dbfile_getc() instead of getc().
(dbfile_open_read): New function.
(dbfile_open_write): New function.
(dump_dbfile_stats): New function.
(dbfile_ftell): The argument is now a struct dbfile*, not FILE*.
(dbfile_getc): Ditto.
(dbfile_ungetc): Ditto.
* src/server/conference.c: Include ram-io.h, since
local-to-global.h needs it.
* src/server/memory.c: Ditto.
* src/server/person.c: Ditto.
* src/server/prot-a-output.c: Ditto.
* src/server/text.c: Ditto.
* src/server/membership.c: Include ram-io.h.
(read_ranges_postcondition): Set up a dbfile wrapper around stderr
for the report created if check_membership() fails.
* src/server/local-to-global.h, src/server/local-to-global.c
(l2g_read): The fp argument is now a struct dbfile*, not a FILE*.
* src/server/dbck.c (oformat): Removed.  The format is stored
inside the dbfile struct instead.
(main): Report an error message if an attempt to use an undefined
output format is detected.
* src/server/dbck-cache.c: Change all FILE* that refer to the
status files to struct dbfile* in all functions, and made
appropriate changes.  Use fp->format instead of the global
variable oformat or data_file_version.
(get_version): Moved to ram-io.c.
(sync_output_header): Removed the oformat argument.  Use
fp->format instead.  All callers updated.
(cache_sync_all): Use dbfile_open_write() instead of i_fopen(),
and dbfile_delete() instead of i_fclose().
(init_cache): Removed the data_file_version variable, as the
format is now stored inside the dbfile struct.  Use
dbfile_open_read() instead of i_fopen(), and dbfile_delete()
instead of i_fclose().
* doc/lyskomd.texi (Modifying Stored Types): The default database
format is now defined in ram-io.c, and nowhere else.  It is
preferrable if lyskomd is able to convert an old format to a new
one after an upgrade.
* src/server/testsuite/test-l2g.c (main): Added a dbfile wrapper
around stdin in call to l2g_read(), and another around stderr in
call to l2g_write().
* src/server/testsuite/Makefile.am (test_l2g_LDADD): Include
libeintr.a.
* src/server/simple-cache.c: Change all FILE* that refer to the
status files to struct dbfile* in all functions, and made
appropriate changes.
(pre_sync): Use dbfile_delete() instead of i_fclose(), and
dbfile_open_write() instead of i_fopen().
(post_sync): Use dbfile_delete() instead of i_fclose(), and
dbfile_open_read() instead of i_fopen().
(save_one_text): Use dbfile_delete() instead of i_fclose(), and
dbfile_open_read() instead of i_fopen().
(sync_part): Use dbfile_delete() instead of i_fclose().
(init_cache): Removed local variable datafile_version; use
fp->format instead.  Use dbfile_open_read() instead of i_fopen().
Removed call to set_input_format(), as dbfile_open_read() does
the same thing.
(free_all_cache): Use dbfile_delete() instead of i_fclose().
* src/server/ramkomd.c (dump_exit_statistics): Dump dbfile stats.
* src/server/ram-parse.h, src/server/ram-parse.c: Change all
FILE* that refer to the status files to struct dbfile* in all
functions, and made appropriate changes.
(set_input_format): Removed.
* src/server/ram-parse.c (input_format): Removed.  All users
changed to use fp->format instead, so that lyskomd can read files
with different versions at the same time.
(fparse_text_stat_2): Code cleanup.
(fparse_text_stat_0): Use dbfile_ungetc() instead of ungetc().
* src/server/ram-output.h, src/server/ram-output.c: Change all
FILE* that refer to the status files to struct dbfile* in all
functions, and made appropriate changes.
(output_format): Moved to ram-io.c and made static.
(set_output_format): Moved to ram-io.c.
parent 0a162ece
2006-10-19 Per Cederqvist <ceder@lysator.liu.se>
2006-10-20 Per Cederqvist <ceder@lysator.liu.se>
Wrap all file pointers that refer to the database files inside a
"struct dbfile". Add a database version field to that struct, and
remove the global database format variables. This allows lyskomd
to have files in different versions open at the same time, so that
it can convert format X to format X+1 on the fly. (This is more
preparation for bug 1616.)
* src/server/ram-io.h (struct dbfile): New struct.
(dbfile_delete): New function.
(set_output_format): New function.
(dbfile_open_write): New function.
(dbfile_open_read): New function.
(dump_dbfile_stats): New function.
(dbfile_ftell): The argument is now a struct dbfile*, not FILE*.
(dbfile_getc): Ditto.
(dbfile_ungetc): Ditto.
* src/server/ram-io.c (output_format): Moved from ram-output.c and
made static variable. This defines the output format of all
struct dbfile objects created after a change to the variable.
(nr_dbfile_objects): New static statistics variable.
(nr_dbfile_files): New static statistics variable.
(dbfile_new): New static function.
(dbfile_delete): New function.
(set_output_format): Moved from ram-output.c.
(get_version): Moved from simple-cache.c. Changed return type to
int. The argument is an open dbfile, not a file name. Use
dbfile_getc() instead of getc().
(dbfile_open_read): New function.
(dbfile_open_write): New function.
(dump_dbfile_stats): New function.
(dbfile_ftell): The argument is now a struct dbfile*, not FILE*.
(dbfile_getc): Ditto.
(dbfile_ungetc): Ditto.
* src/server/conference.c: Include ram-io.h, since
local-to-global.h needs it.
* src/server/memory.c: Ditto.
* src/server/person.c: Ditto.
* src/server/prot-a-output.c: Ditto.
* src/server/text.c: Ditto.
* src/server/membership.c: Include ram-io.h.
(read_ranges_postcondition): Set up a dbfile wrapper around stderr
for the report created if check_membership() fails.
* src/server/local-to-global.h, src/server/local-to-global.c
(l2g_read): The fp argument is now a struct dbfile*, not a FILE*.
* src/server/dbck.c (oformat): Removed. The format is stored
inside the dbfile struct instead.
(main): Report an error message if an attempt to use an undefined
output format is detected.
* src/server/dbck-cache.c: Change all FILE* that refer to the
status files to struct dbfile* in all functions, and made
appropriate changes. Use fp->format instead of the global
variable oformat or data_file_version.
(get_version): Moved to ram-io.c.
(sync_output_header): Removed the oformat argument. Use
fp->format instead. All callers updated.
(cache_sync_all): Use dbfile_open_write() instead of i_fopen(),
and dbfile_delete() instead of i_fclose().
(init_cache): Removed the data_file_version variable, as the
format is now stored inside the dbfile struct. Use
dbfile_open_read() instead of i_fopen(), and dbfile_delete()
instead of i_fclose().
* doc/lyskomd.texi (Modifying Stored Types): The default database
format is now defined in ram-io.c, and nowhere else. It is
preferrable if lyskomd is able to convert an old format to a new
one after an upgrade.
* src/server/testsuite/test-l2g.c (main): Added a dbfile wrapper
around stdin in call to l2g_read(), and another around stderr in
call to l2g_write().
* src/server/testsuite/Makefile.am (test_l2g_LDADD): Include
libeintr.a.
* src/server/simple-cache.c: Change all FILE* that refer to the
status files to struct dbfile* in all functions, and made
appropriate changes.
(pre_sync): Use dbfile_delete() instead of i_fclose(), and
dbfile_open_write() instead of i_fopen().
(post_sync): Use dbfile_delete() instead of i_fclose(), and
dbfile_open_read() instead of i_fopen().
(save_one_text): Use dbfile_delete() instead of i_fclose(), and
dbfile_open_read() instead of i_fopen().
(sync_part): Use dbfile_delete() instead of i_fclose().
(init_cache): Removed local variable datafile_version; use
fp->format instead. Use dbfile_open_read() instead of i_fopen().
Removed call to set_input_format(), as dbfile_open_read() does
the same thing.
(free_all_cache): Use dbfile_delete() instead of i_fclose().
* src/server/ramkomd.c (dump_exit_statistics): Dump dbfile stats.
* src/server/ram-parse.h, src/server/ram-parse.c: Change all
FILE* that refer to the status files to struct dbfile* in all
functions, and made appropriate changes.
(set_input_format): Removed.
* src/server/ram-parse.c (input_format): Removed. All users
changed to use fp->format instead, so that lyskomd can read files
with different versions at the same time.
(fparse_text_stat_2): Code cleanup.
(fparse_text_stat_0): Use dbfile_ungetc() instead of ungetc().
* src/server/ram-output.h, src/server/ram-output.c: Change all
FILE* that refer to the status files to struct dbfile* in all
functions, and made appropriate changes.
(output_format): Moved to ram-io.c and made static.
(set_output_format): Moved to ram-io.c.
Fixed more missed opportunities to use fparse_set_pos() and
foutput_newline().
......
......@@ -2445,9 +2445,8 @@ version dependent so that they can deal with the new database format.
Update all old functions in @file{ram-parse.c} that are database version
dependent so that they can deal with the new database format.
@item Set the default database format in @file{ram-parse.c} and
@file{ram-output.c}. The variables to change are @code{input_format} and
@file{output_format}, respectively.
@item Set the default database format in @file{ram-io.c}, by changing
@var{output_format}.
@item Don't forget to update the functions in @file{memory.c}
......@@ -2455,6 +2454,11 @@ dependent so that they can deal with the new database format.
@item Add as many test cases as are needed for the dbck conversion.
@item lyskomd should preferrably be able to convert from the previous
to the current format on-the-fly. Converting older formats on-the-fly
is not necessary. If somebody needs to upgrade several steps, they
can use dbck to perform the conversion.
@end enumerate
@menu
......
......@@ -61,6 +61,7 @@
#include "conf-file.h"
#include "param.h"
#include "aux-items.h"
#include "ram-io.h"
#include "local-to-global.h"
#include "server-time.h"
#include "stats.h"
......
This diff is collapsed.
......@@ -76,6 +76,7 @@
#include "kom-errno.h"
#include "manipulate.h"
#include "version-info.h"
#include "ram-io.h"
#include "ram-output.h"
#include "unused.h"
#include "local-to-global.h"
......@@ -132,9 +133,6 @@ static int sflag=0; /* Statistic flag. */
static Pers_no reset_pwd=0; /* Person whose password should be cleared. */
static Pers_no grant_all=0; /* Person which should receive all bits. */
/* The following variable holds the output format */
long oformat=-1; /* Output format */
static long force_output=0; /* Force sync (for conversions) */
/* The following variables hold kom_info modifications */
......@@ -1436,6 +1434,7 @@ main (int argc,
int optc;
int need_rw = 0;
int have_lock = 0;
int oformat = -1;
set_initial_time();
......@@ -1571,6 +1570,17 @@ main (int argc,
if (oformat == 0 && *optarg != '0')
restart_kom("%s: bad output format %s\n", argv[0], optarg);
/* Enumerate all supported output formats here. */
switch (oformat)
{
case 0:
case 1:
case 2:
break;
default:
restart_kom("%s: unsupported output format %d\n",
argv[0], oformat);
}
set_output_format(oformat);
break;
......
......@@ -1172,7 +1172,7 @@ l2g_dump(FILE *file,
Success
l2g_read(FILE *fp, Local_to_global *l2g)
l2g_read(struct dbfile *fp, Local_to_global *l2g)
{
int c;
Local_text_no lno = 0;
......@@ -1267,7 +1267,7 @@ put_ulong(unsigned long l,
}
void
l2g_write(FILE *fp, const Local_to_global *l2g)
l2g_write(struct dbfile *fp, const Local_to_global *l2g)
{
const struct l2g_block_info *binfo;
int ix;
......@@ -1275,8 +1275,8 @@ l2g_write(FILE *fp, const Local_to_global *l2g)
Text_no val;
Local_text_no current = 0;
putc('[', fp);
put_ulong(l2g->first_unused, fp);
putc('[', fp->fp);
put_ulong(l2g->first_unused, fp->fp);
for (binfo = l2g->blocks; binfo < l2g->blocks + l2g->num_blocks; ++binfo)
for (ix = 0; ix < binfo->first_free; ++ix)
......@@ -1285,25 +1285,25 @@ l2g_write(FILE *fp, const Local_to_global *l2g)
key = key_value(binfo, ix);
if (key > current + 3 || current == 0)
{
putc(' ', fp);
put_ulong(key, fp);
putc(':', fp);
put_ulong(val, fp);
putc(' ', fp->fp);
put_ulong(key, fp->fp);
putc(':', fp->fp);
put_ulong(val, fp->fp);
current = key;
}
else
{
while (++current < key)
{
putc(',', fp);
putc('0', fp);
putc(',', fp->fp);
putc('0', fp->fp);
}
putc(',', fp);
put_ulong(val, fp);
putc(',', fp->fp);
put_ulong(val, fp->fp);
}
}
putc(']', fp);
putc(']', fp->fp);
}
......
......@@ -77,11 +77,11 @@ void l2g_delete_global_in_sorted(Local_to_global *l2g, Text_no tno);
void l2g_dump(FILE *file, const Local_to_global *l2g);
/* Write an external representation of the mapping to ``file''. */
void l2g_write(FILE *file, const Local_to_global *l2g);
void l2g_write(struct dbfile *file, const Local_to_global *l2g);
/* Initialize the mapping from the representation found in ``file''.
``l2g'' must already be constructed. */
Success l2g_read(FILE *file, Local_to_global *l2g);
Success l2g_read(struct dbfile *file, Local_to_global *l2g);
/* Dump global usage statistics to ``file''. */
void dump_l2g_stats(FILE *file);
......
......@@ -65,6 +65,7 @@
#include "kom-memory.h"
#include "conf-file.h"
#include "param.h"
#include "ram-io.h"
#include "local-to-global.h"
#include "server-time.h"
......@@ -1469,13 +1470,17 @@ read_ranges_postcondition(Membership *m,
/* Check that the membership is correct. Otherwise log all info. */
if (check_membership(ACTPERS, conf_c, m) > 0 && log_no < 40)
{
struct dbfile stderr_wrapper;
stderr_wrapper.fp = stderr;
stderr_wrapper.format = 2;
kom_log("%s(): (%d) Person %lu has a corrupt membership:\n",
func, ++log_no, (unsigned long)ACTPERS);
kom_log("Dump of data follows: <original membership>"
"<updated membership>\n");
foutput_membership(stderr, save);
foutput_membership(&stderr_wrapper, save);
putc('\n', stderr);
foutput_membership(stderr, m);
foutput_membership(&stderr_wrapper, m);
putc('\n', stderr);
ret = -1;
}
......
......@@ -45,6 +45,7 @@
#include "server/smalloc.h"
#include "log.h"
#include "lyskomd.h"
#include "ram-io.h"
#include "local-to-global.h"
static int person_cnt = 0;
......
......@@ -72,6 +72,7 @@
#include "conf-file.h"
#include "param.h"
#include "aux-items.h"
#include "ram-io.h"
#include "local-to-global.h"
#include "kom-memory.h"
#include "server-time.h"
......
......@@ -55,6 +55,7 @@
#include "lyskomd.h"
#include "conf-file.h"
#include "param.h"
#include "ram-io.h"
#include "local-to-global.h"
void
......
......@@ -39,21 +39,143 @@
#include "lyskomd.h"
#include "log.h"
/* The native output format is defined here. */
static int output_format = 2;
static long nr_dbfile_objects = 0;
static long nr_dbfile_files = 0;
static struct dbfile *
dbfile_new(void)
{
struct dbfile *res = smalloc(sizeof(struct dbfile));
res->fp = NULL;
res->format = output_format;
++nr_dbfile_objects;
return res;
}
int
dbfile_delete(struct dbfile *obj)
{
int rv = 0;
int errno_save = errno;
if (obj->fp != NULL)
{
rv = i_fclose(obj->fp);
errno_save = errno;
--nr_dbfile_files;
}
sfree(obj);
errno = errno_save;
--nr_dbfile_objects;
return rv;
}
void
set_output_format(int fmt)
{
output_format = fmt;
switch (fmt)
{
case 0:
case 1:
case 2:
break;
default:
restart_kom("unknown output format selected: %d\n", fmt);
break;
}
}
static int
get_version(struct dbfile *fp)
{
int version;
fparse_set_pos(fp, 5);
if (dbfile_getc(fp) == '\n')
{
return 0;
}
version = fparse_long(fp);
return version;
}
struct dbfile *
dbfile_open_read(const char *filename)
{
struct dbfile *res = dbfile_new();
res->fp = i_fopen(filename, "rb");
if (res->fp == NULL)
{
int saved_errno = errno;
dbfile_delete(res);
errno = saved_errno;
return NULL;
}
++nr_dbfile_files;
res->format = get_version(res);
switch(res->format)
{
case 0:
case 1:
case 2:
break;
default:
restart_kom("unknown input format selected: %d\n", res->format);
break;
}
return res;
}
struct dbfile *
dbfile_open_write(const char *filename)
{
struct dbfile *res = dbfile_new();
if (res == NULL)
return NULL;
if ((res->fp = i_fopen(filename, "wb")) == NULL)
{
int saved_errno = errno;
dbfile_delete(res);
errno = saved_errno;
return NULL;
}
++nr_dbfile_files;
return res;
}
void
dump_dbfile_stats(FILE *fp)
{
fprintf(fp, "---%s:\n\tExisting dbfile objects: %ld\n",
__FILE__, nr_dbfile_objects);
fprintf(fp, "\tExisting dbfile files: %ld\n", nr_dbfile_files);
}
long
dbfile_ftell(FILE *fp)
dbfile_ftell(struct dbfile *fp)
{
return ftell(fp);
return ftell(fp->fp);
}
int
dbfile_getc(FILE *fp)
dbfile_getc(struct dbfile *fp)
{
return getc(fp);
return getc(fp->fp);
}
int
dbfile_ungetc(FILE *fp,
dbfile_ungetc(struct dbfile *fp,
int c)
{
return ungetc(c, fp);
return ungetc(c, fp->fp);
}
......@@ -22,11 +22,46 @@
* Please report bugs at http://bugzilla.lysator.liu.se/.
*/
/* Store state needed to access a database status file. There can be
several files opened at the same time, with different formats. This
struct keeps track of the FILE* and format version. */
struct dbfile {
FILE *fp;
int format;
};
/* Close the file referenced by obj (if fp != NULL), and free the
struct dbfile. */
int dbfile_delete(struct dbfile *obj);
/* Set the default output format for all future calls to
dbfile_open_write() (until the next call to
set_output_format()). */
void set_output_format(int new_format);
/* Open the file for writing. */
extern struct dbfile *
dbfile_open_write(const char *filename);
/* Open the file for reading. The file format version will be read
from the file. */
extern struct dbfile *
dbfile_open_read(const char *filename);
/* Dump information about the number of existing dbfile structs and
open dbfile file descriptors to the specified file. */
void
dump_dbfile_stats(FILE *fp);
/* Call ftell() on the file. */
long
dbfile_ftell(FILE *fp);
dbfile_ftell(struct dbfile *fp);
/* Call getc() on the file. */
int
dbfile_getc(FILE *fp);
dbfile_getc(struct dbfile *fp);
/* Call ungetc() on the file. */
int
dbfile_ungetc(FILE *fp, int c);
dbfile_ungetc(struct dbfile *fp, int c);
This diff is collapsed.
......@@ -34,34 +34,31 @@
*/
extern void
foutput_header(FILE *fp, const char *state, int include_timestamp);
foutput_header(struct dbfile *fp, const char *state, int include_timestamp);
extern void
foutput_info(FILE *fp,
foutput_info(struct dbfile *fp,
Info *info);
extern void
foutput_person(FILE *fp,
foutput_person(struct dbfile *fp,
const Person *person);
extern void
foutput_conference(FILE *fp,
foutput_conference(struct dbfile *fp,
Conference *conf_c);
extern void
foutput_text_stat(FILE *fp,
foutput_text_stat(struct dbfile *fp,
Text_stat *t_stat);
/* Needed by debug code in membership.c. */
extern void
foutput_membership(FILE *fp,
foutput_membership(struct dbfile *fp,
Membership *mship);
extern void
foutput_atsign(FILE *fp);
foutput_atsign(struct dbfile *fp);
extern void
foutput_newline(FILE *fp);
extern void
set_output_format(int fmt);
foutput_newline(struct dbfile *fp);
This diff is collapsed.
......@@ -29,116 +29,113 @@
*/
extern unsigned long
fparse_long(FILE *fp);
fparse_long(struct dbfile *fp);
extern void
fskipwhite(FILE *fp);
fskipwhite(struct dbfile *fp);
extern time_t
fparse_time(FILE *fp);
fparse_time(struct dbfile *fp);
extern Success
fparse_info(FILE *fp,
fparse_info(struct dbfile *fp,
Info *info);
extern Success
fparse_conference(FILE *fp,
Conference *result);
fparse_conference(struct dbfile *fp,
Conference *result);
Success
fparse_person(FILE *fp,
Person *person);
fparse_person(struct dbfile *fp,
Person *person);
extern Success
fparse_membership_list(FILE *fp,
Membership_list *result);
fparse_membership_list(struct dbfile *fp,
Membership_list *result);
extern Success
fparse_conf_list(FILE *fp,
Conf_list_old *result);
fparse_conf_list(struct dbfile *fp,
Conf_list_old *result);
extern Success
fparse_mark_list(FILE *fp,
Mark_list *result);
fparse_mark_list(struct dbfile *fp,
Mark_list *result);
extern Success
fparse_text_stat(FILE *fp,
Text_stat *result);
fparse_text_stat(struct dbfile *fp,
Text_stat *result);
extern Success
fparse_info(FILE *fp,
Info *result);
fparse_info(struct dbfile *fp,
Info *result);
extern Success
fparse_string(FILE *fp,
String *result);
fparse_string(struct dbfile *fp,
String *result);
extern Success
fparse_member_list(FILE *fp,
Member_list *result);
fparse_member_list(struct dbfile *fp,
Member_list *result);
extern Success
fparse_member(FILE *fp,
Member *result);
fparse_member(struct dbfile *fp,
Member *result);
extern Success
fparse_mark(FILE *fp,
Mark *result);
fparse_mark(struct dbfile *fp,
Mark *result);
extern Success
fparse_priv_bits(FILE *fp,
Priv_bits *result);
fparse_priv_bits(struct dbfile *fp,
Priv_bits *result);
extern Success
fparse_personal_flags(FILE *fp,
Personal_flags *result);
fparse_personal_flags(struct dbfile *fp,
Personal_flags *result);
extern Success
fparse_conf_type(FILE *fp,
Conf_type *result);
fparse_conf_type(struct dbfile *fp,
Conf_type *result);
extern Success
fparse_who_info(FILE *fp,
Who_info *result);
fparse_who_info(struct dbfile *fp,
Who_info *result);
extern Success
fparse_who_info_list(FILE *fp,
fparse_who_info_list(struct dbfile *fp,
Who_info_list *result);
extern Success
fparse_aux_item_flags(FILE *fp,
fparse_aux_item_flags(struct dbfile *fp,
Aux_item_flags *f);
extern Success
fparse_aux_item_link(FILE *fp,
fparse_aux_item_link(struct dbfile *fp,
Aux_item_link *link);
extern Success
fparse_aux_item(FILE *fp,
fparse_aux_item(struct dbfile *fp,
Aux_item *result);
extern Success
fparse_aux_item_list(FILE *fp,
fparse_aux_item_list(struct dbfile *fp,
Aux_item_list *result);
extern Success
fparse_misc_info(FILE *fp,
fparse_misc_info(struct dbfile *fp,
Misc_info *result);
extern Success
fparse_set_pos(FILE *fp,
fparse_set_pos(struct dbfile *fp,
long offset);
extern void
set_input_format(int fmt);
......@@ -100,6 +100,7 @@
#include "admin.h"
#include "unused.h"
#include "sigflags.h"