diff options
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | extension/ChangeLog | 7 | ||||
-rw-r--r-- | extension/select.c | 55 | ||||
-rw-r--r-- | io.c | 11 |
4 files changed, 76 insertions, 4 deletions
@@ -1,3 +1,10 @@ +2014-11-05 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * io.c (retryable): New function to indicate whether I/O can be + retried for this file instead of throwing a hard error. + (get_a_record) Check whether this file is configured for retryable + I/O before returning nonstandard -2. + 2014-11-03 Norihiro Tanaka <noritnk@kcn.ne.jp> * re.c (research): Use dfa superset to improve matching speed. diff --git a/extension/ChangeLog b/extension/ChangeLog index 82ae5b69..5d278f6c 100644 --- a/extension/ChangeLog +++ b/extension/ChangeLog @@ -1,3 +1,10 @@ +2014-11-05 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * select.c (set_retry): New function to set PROCINFO[<name>, "RETRY"]. + (do_set_non_blocking): If called with a file name as opposed to a file + descriptor, call the set_retry function to configure PROCINFO to tell + io.c to retry I/O for temporary failures. + 2014-10-08 Arnold D. Robbins <arnold@skeeve.com> * inplace.c (do_inplace_begin): Use a cast to void in front diff --git a/extension/select.c b/extension/select.c index 9aefaeac..1752ee34 100644 --- a/extension/select.c +++ b/extension/select.c @@ -496,6 +496,53 @@ set_non_blocking(int fd) #endif } +static void +set_retry(const char *name) +{ + static const char suffix[] = "RETRY"; + static awk_array_t procinfo; + static char *subsep; + static size_t subsep_len; + awk_value_t idx, val; + char *s; + size_t len; + + if (!subsep) { + /* initialize cached values for PROCINFO and SUBSEP */ + awk_value_t res; + + if (! sym_lookup("PROCINFO", AWK_ARRAY, & res)) { + procinfo = create_array(); + res.val_type = AWK_ARRAY; + res.array_cookie = procinfo; + if (! sym_update("PROCINFO", & res)) { + warning(ext_id, _("set_non_blocking: could not install PROCINFO array; unable to configure PROCINFO RETRY for `%s'"), name); + return; + } + /* must retrieve it after installing it! */ + if (! sym_lookup("PROCINFO", AWK_ARRAY, & res)) { + warning(ext_id, _("set_non_blocking: sym_lookup(`%s') failed; unable to configure PROCINFO RETRY for `%s'"), "PROCINFO", name); + return; + } + } + procinfo = res.array_cookie; + + if (! sym_lookup("SUBSEP", AWK_STRING, & res)) { + warning(ext_id, _("set_non_blocking: sym_lookup(`%s') failed; unable to configure PROCINFO RETRY for `%s'"), "SUBSEP", name); + return; + } + subsep = strdup(res.str_value.str); + subsep_len = res.str_value.len; + } + + len = strlen(name)+subsep_len+sizeof(suffix)-1; + emalloc(s, char *, len+2, "set_non_blocking"); + sprintf(s, "%s%s%s", name, subsep, suffix); + + if (! set_array_element(procinfo, make_malloced_string(s, len, &idx), make_null_string(&val))) + warning(ext_id, _("set_non_blocking: unable to configure PROCINFO RETRY for `%s'"), name); +} + /* do_set_non_blocking --- Set a file to be non-blocking */ static awk_value_t * @@ -520,8 +567,12 @@ do_set_non_blocking(int nargs, awk_value_t *result) (get_argument(1, AWK_STRING, & cmdtype) || (! cmd.str_value.len && (nargs == 1)))) { const awk_input_buf_t *buf; - if ((buf = get_file(cmd.str_value.str, cmd.str_value.len, cmdtype.str_value.str, cmdtype.str_value.len)) != NULL) - return make_number(set_non_blocking(buf->fd), result); + if ((buf = get_file(cmd.str_value.str, cmd.str_value.len, cmdtype.str_value.str, cmdtype.str_value.len)) != NULL) { + int rc = set_non_blocking(buf->fd); + if (rc == 0) + set_retry(buf->name); + return make_number(rc, result); + } warning(ext_id, _("set_non_blocking: get_file(`%s', `%s') failed"), cmd.str_value.str, cmdtype.str_value.str); } else if (do_lint) { if (nargs < 2) @@ -3425,6 +3425,13 @@ find_longest_terminator: return REC_OK; } +/* return true if PROCINFO[<filename>, "RETRY"] exists */ +static inline int +retryable(IOBUF *iop) +{ + return PROCINFO_node && in_PROCINFO(iop->public.name, "RETRY", NULL); +} + /* Does the I/O error indicate that the operation should be retried later? */ static inline int @@ -3500,7 +3507,7 @@ get_a_record(char **out, /* pointer to pointer to data */ return EOF; } else if (iop->count == -1) { *errcode = errno; - if (errno_io_retry()) + if (errno_io_retry() && retryable(iop)) return -2; iop->flag |= IOP_AT_EOF; return EOF; @@ -3576,7 +3583,7 @@ get_a_record(char **out, /* pointer to pointer to data */ iop->count = iop->public.read_func(iop->public.fd, iop->dataend, amt_to_read); if (iop->count == -1) { *errcode = errno; - if (errno_io_retry()) + if (errno_io_retry() && retryable(iop)) return -2; iop->flag |= IOP_AT_EOF; break; |