diff options
author | Fedor Indutny <fedor@indutny.com> | 2016-06-04 14:37:26 -0400 |
---|---|---|
committer | Fedor Indutny <fedor@indutny.com> | 2016-06-04 15:44:18 -0400 |
commit | af170cc9bbfbed228c386b64c1bb945ab4a502ed (patch) | |
tree | 901e5758c4ff05f72826c7e616591c7a548690e8 /src/uv_link_t.c | |
parent | a66bb042e02bd1021a574c32a27fff087ab1c9f4 (diff) | |
download | uv_link_t-af170cc9bbfbed228c386b64c1bb945ab4a502ed.tar.gz |
api: experimental error reporting
Diffstat (limited to 'src/uv_link_t.c')
-rw-r--r-- | src/uv_link_t.c | 65 |
1 files changed, 59 insertions, 6 deletions
diff --git a/src/uv_link_t.c b/src/uv_link_t.c index f83a8a6..3df5264 100644 --- a/src/uv_link_t.c +++ b/src/uv_link_t.c @@ -3,8 +3,27 @@ #include "src/common.h" +static const size_t kErrorPrefixShift = 16; +static const int kErrorValueMask = (1 << kErrorPrefixShift) - 1; +static const unsigned int kErrorPrefixMask = ~kErrorValueMask; + static void uv_link_maybe_close(uv_link_t* link); + +static int uv_link_error(uv_link_t* link, int err) { + if (link == NULL) + return err; + + if (err >= UV_ERRNO_MAX) + return err; + + if (((-err) & kErrorPrefixMask) != 0) + return err; + + return -((-err) | link->err_prefix); +} + + static void uv_link_def_alloc_cb(uv_link_t* link, size_t suggested_size, uv_buf_t* buf) { @@ -32,6 +51,7 @@ int uv_link_init(uv_link_t* link, uv_link_methods_t const* methods) { link->alloc_cb = uv_link_def_alloc_cb; link->read_cb = uv_link_def_read_cb; + link->err_prefix = 1 << kErrorPrefixShift; link->methods = methods; @@ -46,7 +66,7 @@ int uv_link_init(uv_link_t* link, uv_link_methods_t const* methods) { err = (RES); \ if (--link->close_depth == 0) \ uv_link_maybe_close(link); \ - return err; \ + return uv_link_error(link, err); \ } while (0) @@ -55,7 +75,7 @@ int uv_link_propagate_write(uv_link_t* link, uv_link_t* source, uv_stream_t* send_handle, uv_link_write_cb cb, void* arg) { if (link == NULL) - return UV_EFAULT; + return uv_link_error(link, UV_EFAULT); CLOSE_WRAP(link->methods->write(link, source, bufs, nbufs, send_handle, cb, arg)); } @@ -66,21 +86,21 @@ int uv_link_propagate_shutdown(uv_link_t* link, uv_link_shutdown_cb cb, void* arg) { if (link == NULL) - return UV_EFAULT; + return uv_link_error(link, UV_EFAULT); CLOSE_WRAP(link->methods->shutdown(link, source, cb, arg)); } int uv_link_read_start(uv_link_t* link) { if (link == NULL) - return UV_EFAULT; + return uv_link_error(link, UV_EFAULT); CLOSE_WRAP(link->methods->read_start(link)); } int uv_link_read_stop(uv_link_t* link) { if (link == NULL) - return UV_EFAULT; + return uv_link_error(link, UV_EFAULT); CLOSE_WRAP(link->methods->read_stop(link)); } @@ -89,7 +109,7 @@ int uv_link_try_write(uv_link_t* link, const uv_buf_t bufs[], unsigned int nbufs) { if (link == NULL) - return UV_EFAULT; + return uv_link_error(link, UV_EFAULT); CLOSE_WRAP(link->methods->try_write(link, bufs, nbufs)); } @@ -154,6 +174,15 @@ void uv_link_propagate_close(uv_link_t* link, uv_link_t* source, } +static void uv_link_recalculate_prefixes(uv_link_t* link) { + unsigned short prev; + + prev = link->parent->err_prefix >> kErrorPrefixShift; + for (; link != NULL; link = link->child) + link->err_prefix = (++prev) << kErrorPrefixShift; +} + + int uv_link_chain(uv_link_t* from, uv_link_t* to) { if (from->child != NULL || to->parent != NULL) return UV_EINVAL; @@ -170,6 +199,8 @@ int uv_link_chain(uv_link_t* from, uv_link_t* to) { from->alloc_cb = to->methods->alloc_cb_override; from->read_cb = to->methods->read_cb_override; + uv_link_recalculate_prefixes(to); + return 0; } @@ -190,6 +221,24 @@ int uv_link_unchain(uv_link_t* from, uv_link_t* to) { } +const char* uv_link_strerror(uv_link_t* link, int err) { + unsigned int prefix; + int local_err; + + if (err >= UV_ERRNO_MAX) + return uv_strerror(err); + + prefix = (-err) & kErrorPrefixMask; + local_err = -((-err) & kErrorValueMask); + + for (; link != NULL; link = link->parent) + if (prefix == link->err_prefix) + return link->methods->strerror(link, local_err); + + return NULL; +} + + void uv_link_propagate_alloc_cb(uv_link_t* link, size_t suggested_size, uv_buf_t* buf) { @@ -215,6 +264,10 @@ void uv_link_propagate_read_cb(uv_link_t* link, if (link->child != NULL) target = link->child; + /* Prefix errors */ + if (nread < 0) + nread = uv_link_error(link, nread); + target->close_depth++; link->read_cb(target, nread, buf); if (--target->close_depth == 0) |