diff options
author | Eric Blake <ebb9@byu.net> | 2008-12-10 06:15:53 -0700 |
---|---|---|
committer | Eric Blake <ebb9@byu.net> | 2008-12-15 06:02:18 -0700 |
commit | c28c0d455f7e28ee1bac21ab398dbe3d010b502a (patch) | |
tree | a829cee21ee42fbfda5d8cf29fd461497627d5f9 | |
parent | 01c5807a56be04620dbe3ff50f72358ef1ed88ed (diff) | |
download | m4-c28c0d455f7e28ee1bac21ab398dbe3d010b502a.tar.gz |
Use fewer seeks on cached files.
* m4/output.c (m4_tmpfile): Use write, not append mode.
(m4_tmpopen): Add parameter to decide when to skip seeks.
(m4_tmprename, m4_make_diversion, insert_diversion_helper)
(m4_freeze_diversions): Adjust callers.
Signed-off-by: Eric Blake <ebb9@byu.net>
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | m4/output.c | 38 |
2 files changed, 27 insertions, 17 deletions
@@ -1,5 +1,11 @@ 2008-12-15 Eric Blake <ebb9@byu.net> + Use fewer seeks on cached files. + * m4/output.c (m4_tmpfile): Use write, not append mode. + (m4_tmpopen): Add parameter to decide when to skip seeks. + (m4_tmprename, m4_make_diversion, insert_diversion_helper) + (m4_freeze_diversions): Adjust callers. + Cache most recently spilled diversion. * m4/output.c (tmp_file, tmp_file_owner): New variables, for 1-deep cache of spilled diversions. diff --git a/m4/output.c b/m4/output.c index 2f00902c..61ddfbb3 100644 --- a/m4/output.c +++ b/m4/output.c @@ -219,7 +219,7 @@ m4_tmpfile (m4 *context, int divnum) } name = m4_tmpname (divnum); register_temp_file (output_temp_dir, name); - file = fopen_temp (name, O_BINARY ? "ab+" : "a+"); + file = fopen_temp (name, O_BINARY ? "wb+" : "w+"); if (file == NULL) { unregister_temp_file (output_temp_dir, name); @@ -232,33 +232,36 @@ m4_tmpfile (m4 *context, int divnum) } /* Reopen a temporary file for diversion DIVNUM for reading and - writing in a secure temp directory. Exits on failure, so the - return value is always an open file. */ + writing in a secure temp directory. If REREAD, the file is + positioned at offset 0, otherwise the file is positioned at the + end. Exits on failure, so the return value is always an open + file. */ static FILE * -m4_tmpopen (m4 *context, int divnum) +m4_tmpopen (m4 *context, int divnum, bool reread) { const char *name; FILE *file; if (tmp_file_owner == divnum) { - if (fseeko (tmp_file, 0, SEEK_SET) != 0) + if (reread && fseeko (tmp_file, 0, SEEK_SET) != 0) m4_error (context, EXIT_FAILURE, errno, NULL, _("cannot seek to beginning of diversion")); return tmp_file; } name = m4_tmpname (divnum); - file = fopen_temp (name, O_BINARY ? "ab+" : "a+"); + /* We need update mode, to avoid truncation. */ + file = fopen_temp (name, O_BINARY ? "rb+" : "r+"); if (file == NULL) m4_error (context, EXIT_FAILURE, errno, NULL, _("cannot create temporary file for diversion")); else if (set_cloexec_flag (fileno (file), true) != 0) m4_warn (context, errno, NULL, _("cannot protect diversion across forks")); - /* POSIX states that it is undefined whether an append stream starts - at offset 0 or at the end. We want the beginning. */ - else if (fseeko (file, 0, SEEK_SET) != 0) + /* Update mode starts at the beginning of the stream, but sometimes + we want the end. */ + else if (!reread && fseeko (file, 0, SEEK_END) != 0) m4_error (context, EXIT_FAILURE, errno, NULL, - _("cannot seek to beginning of diversion")); + _("cannot seek within diversion")); return file; } @@ -297,7 +300,7 @@ m4_tmpremove (int divnum) /* Transfer the temporary file for diversion OLDNUM to the previously unused diversion NEWNUM. Return an open stream visiting the new - temporary file, exiting on failure. */ + temporary file, positioned at the end, or exit on failure. */ static FILE* m4_tmprename (m4 *context, int oldnum, int newnum) { @@ -325,7 +328,7 @@ m4_tmprename (m4 *context, int oldnum, int newnum) _("cannot create temporary file for diversion")); unregister_temp_file (output_temp_dir, oldname); free (oldname); - return m4_tmpopen (context, newnum); + return m4_tmpopen (context, newnum, false); } @@ -824,7 +827,8 @@ m4_make_diversion (m4 *context, int divnum) { if (!output_diversion->u.file && output_diversion->used) output_diversion->u.file = m4_tmpopen (context, - output_diversion->divnum); + output_diversion->divnum, + false); output_file = output_diversion->u.file; } @@ -931,7 +935,7 @@ insert_diversion_helper (m4 *context, m4_diversion *diversion, bool escaped) { assert (diversion->used); if (!diversion->u.file) - diversion->u.file = m4_tmpopen (context, diversion->divnum); + diversion->u.file = m4_tmpopen (context, diversion->divnum, true); insert_file (context, diversion->u.file, escaped); } @@ -945,7 +949,6 @@ insert_diversion_helper (m4 *context, m4_diversion *diversion, bool escaped) total_buffer_size -= diversion->size; free (diversion->u.buffer); diversion->size = 0; - diversion->used = 0; } else { @@ -953,7 +956,6 @@ insert_diversion_helper (m4 *context, m4_diversion *diversion, bool escaped) { FILE *file = diversion->u.file; diversion->u.file = NULL; - diversion->used = 0; if (m4_tmpclose (file, diversion->divnum) != 0) m4_error (context, 0, errno, NULL, _("cannot clean temporary file for diversion")); @@ -962,6 +964,7 @@ insert_diversion_helper (m4 *context, m4_diversion *diversion, bool escaped) m4_error (context, 0, errno, NULL, _("cannot clean temporary file for diversion")); } + diversion->used = 0; if (!gl_oset_remove (diversion_table, diversion)) assert (false); diversion->u.next = free_list; @@ -1036,7 +1039,8 @@ m4_freeze_diversions (m4 *context, FILE *file) { struct stat file_stat; assert (!diversion->u.file); - diversion->u.file = m4_tmpopen (context, diversion->divnum); + diversion->u.file = m4_tmpopen (context, diversion->divnum, + true); if (fstat (fileno (diversion->u.file), &file_stat) < 0) m4_error (context, EXIT_FAILURE, errno, NULL, _("cannot stat diversion")); |