aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--extension/ChangeLog7
-rw-r--r--extension/select.c55
-rw-r--r--io.c11
4 files changed, 76 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index 4cf75d0f..f37300d0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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)
diff --git a/io.c b/io.c
index 5692a519..6d816da7 100644
--- a/io.c
+++ b/io.c
@@ -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;