diff options
author | Keith Bostic <keith@wiredtiger.com> | 2015-01-06 19:10:41 -0500 |
---|---|---|
committer | Keith Bostic <keith@wiredtiger.com> | 2015-01-06 19:10:41 -0500 |
commit | a02d92f9a546d6c326958cd24c2a0276e9bf72ee (patch) | |
tree | cff7ea367b546dc44910228dc1dc1ca667a97a20 | |
parent | 94ac47877329d2e399ac52a110c2fc31814c815f (diff) | |
parent | d9621cb4ba0d66f4b8a73a417dcc7b0635543c55 (diff) | |
download | mongo-a02d92f9a546d6c326958cd24c2a0276e9bf72ee.tar.gz |
Merge branch 'develop' into mongodb-2.8
-rw-r--r-- | dist/api_err.py | 84 | ||||
-rw-r--r-- | dist/s_string.ok | 2 | ||||
-rw-r--r-- | dist/s_symbols.list | 1 | ||||
-rw-r--r-- | examples/c/ex_all.c | 16 | ||||
-rw-r--r-- | src/conn/api_strerror.c | 77 | ||||
-rw-r--r-- | src/include/extern.h | 2 | ||||
-rw-r--r-- | src/include/wiredtiger.in | 19 | ||||
-rw-r--r-- | src/lsm/lsm_cursor.c | 5 | ||||
-rw-r--r-- | src/os_posix/os_errno.c | 46 | ||||
-rw-r--r-- | src/os_win/os_errno.c | 98 | ||||
-rw-r--r-- | src/os_win/os_ftruncate.c | 7 | ||||
-rw-r--r-- | src/os_win/os_mtx_cond.c | 4 | ||||
-rw-r--r-- | src/os_win/os_rename.c | 4 | ||||
-rw-r--r-- | test/suite/test_config02.py | 2 | ||||
-rw-r--r-- | test/suite/test_config03.py | 6 |
15 files changed, 306 insertions, 67 deletions
diff --git a/dist/api_err.py b/dist/api_err.py index cb2c8cc588e..6c893c9af82 100644 --- a/dist/api_err.py +++ b/dist/api_err.py @@ -78,7 +78,7 @@ for line in open('../src/include/wiredtiger.in', 'r'): tfile.close() compare_srcfile(tmp_file, '../src/include/wiredtiger.in') -# Output the wiredtiger_strerror code. +# Output the wiredtiger_strerror and wiredtiger_sterror_r code. tmp_file = '__tmp' tfile = open(tmp_file, 'w') tfile.write('''/* DO NOT EDIT: automatically built by dist/api_err.py. */ @@ -86,18 +86,22 @@ tfile.write('''/* DO NOT EDIT: automatically built by dist/api_err.py. */ #include "wt_internal.h" /* - * wiredtiger_strerror -- - *\tReturn a string for any error value. + * Historically, there was only the wiredtiger_strerror call because the POSIX + * port didn't need anything more complex; Windows requires memory allocation + * of error strings, so we added the wiredtiger_strerror_r call. Because we + * want wiredtiger_strerror to continue to be as thread-safe as possible, errors + * are split into three categories: WiredTiger constant strings, system constant + * strings and Everything Else, and we check constant strings before Everything + * Else. */ -const char * -wiredtiger_strerror(int error) -{ -\tstatic char errbuf[64]; -\tchar *p; - -\tif (error == 0) -\t\treturn ("Successful return: 0"); +/* + * __wiredtiger_error -- + *\tReturn a constant string for the WiredTiger errors. + */ +static const char * +__wiredtiger_error(int error) +{ \tswitch (error) { ''') @@ -105,19 +109,51 @@ for err in errors: tfile.write('\tcase ' + err.name + ':\n') tfile.write('\t\treturn ("' + err.name + ': ' + err.desc + '");\n') -tfile.write('''\ -\tdefault: -\t\tif (error > 0 && (p = strerror(error)) != NULL) -\t\t\treturn (p); -\t\tbreak; -\t} - -\t/* -\t * !!! -\t * Not thread-safe, but this is never supposed to happen. -\t */ -\t(void)snprintf(errbuf, sizeof(errbuf), "Unknown error: %d", error); -\treturn (errbuf); +tfile.write('''\t} +\treturn (NULL); +} + +/* + * wiredtiger_strerror -- + *\tReturn a string for any error value, non-thread-safe version. + */ +const char * +wiredtiger_strerror(int error) +{ +\tstatic char buf[128]; +\tconst char *p; + +\t/* Check for a constant string. */ +\tif ((p = __wiredtiger_error(error)) != NULL || +\t (p = __wt_strerror(error)) != NULL) +\t\treturn (p); + +\t/* Else, fill in the non-thread-safe static buffer. */ +\tif (wiredtiger_strerror_r(error, buf, sizeof(buf)) != 0) +\t\t(void)snprintf(buf, sizeof(buf), "error return: %d", error); + +\treturn (buf); +} + +/* + * wiredtiger_strerror_r -- + *\tReturn a string for any error value, thread-safe version. + */ +int +wiredtiger_strerror_r(int error, char *buf, size_t buflen) +{ +\tconst char *p; + +\t/* Require at least 2 bytes, printable character and trailing nul. */ +\tif (buflen < 2) +\t\treturn (ENOMEM); + +\t/* Check for a constant string. */ +\tif ((p = __wiredtiger_error(error)) != NULL || +\t (p = __wt_strerror(error)) != NULL) +\t\treturn (snprintf(buf, buflen, "%s", p) > 0 ? 0 : ENOMEM); + +\treturn (__wt_strerror_r(error, buf, buflen)); } ''') tfile.close() diff --git a/dist/s_string.ok b/dist/s_string.ok index db1114b77de..d3717d27331 100644 --- a/dist/s_string.ok +++ b/dist/s_string.ok @@ -181,6 +181,7 @@ KV KVS Kanowski's Kounavis +LANGID LEX LF LIBBZ @@ -437,6 +438,7 @@ btmem btree btrees buf +buflen bufs bufsz builtin diff --git a/dist/s_symbols.list b/dist/s_symbols.list index d3803bc3afa..8f469e94433 100644 --- a/dist/s_symbols.list +++ b/dist/s_symbols.list @@ -8,6 +8,7 @@ wiredtiger_pack_start wiredtiger_pack_str wiredtiger_pack_uint wiredtiger_strerror +wiredtiger_strerror_r wiredtiger_struct_pack wiredtiger_struct_size wiredtiger_struct_unpack diff --git a/examples/c/ex_all.c b/examples/c/ex_all.c index 23e682c5072..31ad812e6f6 100644 --- a/examples/c/ex_all.c +++ b/examples/c/ex_all.c @@ -343,6 +343,22 @@ cursor_ops(WT_SESSION *session) /*! [Display an error] */ } + { + /*! [Display an error thread safe] */ + const char *key = "non-existent key"; + cursor->set_key(cursor, key); + if ((ret = cursor->remove(cursor)) != 0) { + char buf[128]; + + if (wiredtiger_strerror_r(ret, buf, sizeof(buf)) != 0) + (void)snprintf( + buf, sizeof(buf), "error value: %d\n", ret); + fprintf(stderr, "cursor.remove: %s\n", buf); + return (ret); + } + /*! [Display an error thread safe] */ + } + /*! [Close the cursor] */ ret = cursor->close(cursor); /*! [Close the cursor] */ diff --git a/src/conn/api_strerror.c b/src/conn/api_strerror.c index caf536b24f7..396ae7a3e0f 100644 --- a/src/conn/api_strerror.c +++ b/src/conn/api_strerror.c @@ -3,18 +3,22 @@ #include "wt_internal.h" /* - * wiredtiger_strerror -- - * Return a string for any error value. + * Historically, there was only the wiredtiger_strerror call because the POSIX + * port didn't need anything more complex; Windows requires memory allocation + * of error strings, so we added the wiredtiger_strerror_r call. Because we + * want wiredtiger_strerror to continue to be as thread-safe as possible, errors + * are split into three categories: WiredTiger constant strings, system constant + * strings and Everything Else, and we check constant strings before Everything + * Else. */ -const char * -wiredtiger_strerror(int error) -{ - static char errbuf[64]; - char *p; - - if (error == 0) - return ("Successful return: 0"); +/* + * __wiredtiger_error -- + * Return a constant string for the WiredTiger errors. + */ +static const char * +__wiredtiger_error(int error) +{ switch (error) { case WT_ROLLBACK: return ("WT_ROLLBACK: conflict between concurrent operations"); @@ -28,16 +32,49 @@ wiredtiger_strerror(int error) return ("WT_PANIC: WiredTiger library panic"); case WT_RESTART: return ("WT_RESTART: restart the operation (internal)"); - default: - if (error > 0 && (p = strerror(error)) != NULL) - return (p); - break; } + return (NULL); +} + +/* + * wiredtiger_strerror -- + * Return a string for any error value, non-thread-safe version. + */ +const char * +wiredtiger_strerror(int error) +{ + static char buf[128]; + const char *p; + + /* Check for a constant string. */ + if ((p = __wiredtiger_error(error)) != NULL || + (p = __wt_strerror(error)) != NULL) + return (p); + + /* Else, fill in the non-thread-safe static buffer. */ + if (wiredtiger_strerror_r(error, buf, sizeof(buf)) != 0) + (void)snprintf(buf, sizeof(buf), "error return: %d", error); + + return (buf); +} + +/* + * wiredtiger_strerror_r -- + * Return a string for any error value, thread-safe version. + */ +int +wiredtiger_strerror_r(int error, char *buf, size_t buflen) +{ + const char *p; + + /* Require at least 2 bytes, printable character and trailing nul. */ + if (buflen < 2) + return (ENOMEM); + + /* Check for a constant string. */ + if ((p = __wiredtiger_error(error)) != NULL || + (p = __wt_strerror(error)) != NULL) + return (snprintf(buf, buflen, "%s", p) > 0 ? 0 : ENOMEM); - /* - * !!! - * Not thread-safe, but this is never supposed to happen. - */ - (void)snprintf(errbuf, sizeof(errbuf), "Unknown error: %d", error); - return (errbuf); + return (__wt_strerror_r(error, buf, buflen)); } diff --git a/src/include/extern.h b/src/include/extern.h index b80719de7c0..d8ed3f5cef1 100644 --- a/src/include/extern.h +++ b/src/include/extern.h @@ -432,6 +432,8 @@ extern int __wt_dlopen(WT_SESSION_IMPL *session, const char *path, WT_DLH **dlhp extern int __wt_dlsym(WT_SESSION_IMPL *session, WT_DLH *dlh, const char *name, int fail, void *sym_ret); extern int __wt_dlclose(WT_SESSION_IMPL *session, WT_DLH *dlh); extern int __wt_errno(void); +extern const char *__wt_strerror(int error); +extern int __wt_strerror_r(int error, char *buf, size_t buflen); extern int __wt_exist(WT_SESSION_IMPL *session, const char *filename, int *existp); extern void __wt_fallocate_config(WT_SESSION_IMPL *session, WT_FH *fh); extern int __wt_fallocate( WT_SESSION_IMPL *session, WT_FH *fh, wt_off_t offset, wt_off_t len); diff --git a/src/include/wiredtiger.in b/src/include/wiredtiger.in index ee9c58e4278..c8b242b8f14 100644 --- a/src/include/wiredtiger.in +++ b/src/include/wiredtiger.in @@ -2020,15 +2020,26 @@ int wiredtiger_open(const char *home, WT_CONNECTION **connectionp); /*! - * Return information about an error as a string; wiredtiger_strerror is a - * superset of the ISO C99/POSIX 1003.1-2001 function strerror. + * Return information about a WiredTiger error as a string, not thread-safe. * * @snippet ex_all.c Display an error * - * @param err a return value from a WiredTiger, C library or POSIX function + * @param error a return value from a WiredTiger call * @returns a string representation of the error */ -const char *wiredtiger_strerror(int err); +const char *wiredtiger_strerror(int error); + +/*! + * Return information about a WiredTiger error as a string, thread-safe version. + * + * @snippet ex_all.c Display an error thread safe + * + * @param error a return value from a WiredTiger call + * @param buf a buffer of at least \c buflen bytes + * @param buflen the length of the buffer + * @returns zero for success, non-zero to indicate an error. + */ +int wiredtiger_strerror_r(int error, char *buf, size_t buflen); #if !defined(SWIG) /*! diff --git a/src/lsm/lsm_cursor.c b/src/lsm/lsm_cursor.c index 2dfaea1ec3a..52bd3e9373d 100644 --- a/src/lsm/lsm_cursor.c +++ b/src/lsm/lsm_cursor.c @@ -1484,11 +1484,8 @@ __wt_clsm_open(WT_SESSION_IMPL *session, WT_ERR(__wt_cursor_init(cursor, cursor->uri, owner, cfg, cursorp)); if (0) { -err: __wt_lsm_tree_release(session, lsm_tree); - if (clsm != NULL) { - clsm->lsm_tree = NULL; +err: if (clsm != NULL) WT_TRET(__clsm_close(cursor)); - } } return (ret); diff --git a/src/os_posix/os_errno.c b/src/os_posix/os_errno.c index ed3451a9c1c..a58f13583ce 100644 --- a/src/os_posix/os_errno.c +++ b/src/os_posix/os_errno.c @@ -21,3 +21,49 @@ __wt_errno(void) */ return (errno == 0 ? WT_ERROR : errno); } + +/* + * __wt_strerror -- + * POSIX implementation of wiredtiger_strerror. + */ +const char * +__wt_strerror(int error) +{ + const char *p; + + /* + * POSIX errors are non-negative integers; check for 0 explicitly + * in-case the underlying strerror doesn't handle 0, some don't. + */ + if (error == 0) + return ("Successful return: 0"); + if (error > 0 && (p = strerror(error)) != NULL) + return (p); + return (NULL); +} + +/* + * __wt_strerror_r -- + * POSIX implementation of wiredtiger_strerror_r. + */ +int +__wt_strerror_r(int error, char *buf, size_t buflen) +{ + const char *p; + + /* Require at least 2 bytes, printable character and trailing nul. */ + if (buflen < 2) + return (ENOMEM); + + /* + * Check for POSIX errors then fallback to something generic. Copy the + * string into the user's buffer, return success if anything printed. + */ + p = __wt_strerror(error); + if (p != NULL && snprintf(buf, buflen, "%s", p) > 0) + return (0); + + /* Fallback to a generic message, then guess it's a memory problem. */ + return ( + snprintf(buf, buflen, "error return: %d", error) > 0 ? 0 : ENOMEM); +} diff --git a/src/os_win/os_errno.c b/src/os_win/os_errno.c index e321912d829..00ee638fbe3 100644 --- a/src/os_win/os_errno.c +++ b/src/os_win/os_errno.c @@ -8,6 +8,34 @@ #include "wt_internal.h" +static const int windows_error_offset = -29000; + +/* + * __wt_map_error_to_windows_error -- + * Return a negative integer, an encoded Windows error + * Standard C errors are positive integers from 0 - ~200 + * Windows errors are from 0 - 15999 according to the documentation + */ +static DWORD +__wt_map_error_to_windows_error(int error) { + /* Ensure we do not exceed the error range + Also validate he do not get any COM errors + (which are negative integers) + */ + WT_ASSERT(NULL, error > 0 && error > -(windows_error_offset)); + + return (error + -(windows_error_offset)); +} + +/* + * __wt_map_error_to_windows_error -- + * Return a positive integer, a decoded Windows error + */ +static int +__wt_map_windows_error_to_error(DWORD winerr) { + return (winerr + windows_error_offset); +} + /* * __wt_errno -- * Return errno, or WT_ERROR if errno not set. @@ -24,5 +52,73 @@ __wt_errno(void) /* GetLastError should only be called if we hit an actual error */ WT_ASSERT(NULL, err != ERROR_SUCCESS); - return (err == ERROR_SUCCESS ? WT_ERROR : err); + return (err == ERROR_SUCCESS ? + WT_ERROR : __wt_map_windows_error_to_error(err)); +} + +/* + * __wt_strerror -- + * Windows implementation of wiredtiger_strerror. + */ +const char * +__wt_strerror(int error) +{ + const char *p; + + /* + * POSIX errors are non-negative integers; check for 0 explicitly + * in-case the underlying strerror doesn't handle 0, some don't. + */ + if (error == 0) + return ("Successful return: 0"); + if (error > 0 && (p = strerror(error)) != NULL) + return (p); + return (NULL); +} + +/* + * __wt_strerror_r -- + * Windows implementation of wiredtiger_strerror_r. + */ +int +__wt_strerror_r(int error, char *buf, size_t buflen) +{ + DWORD lasterror; + const char *p; + + /* Require at least 2 bytes, printable character and trailing nul. */ + if (buflen < 2) + return (ENOMEM); + + /* + * Check for POSIX errors, Windows errors, then fallback to something + * generic. Copy the string into the user's buffer, return success if + * anything printed. + */ + p = __wt_strerror(error); + if (p != NULL && snprintf(buf, buflen, "%s", p) > 0) + return (0); + + if (error < 0) { + error = __wt_map_error_to_windows_error(error); + + lasterror = FormatMessageA( + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + error, + 0, /* let system choose the correct LANGID */ + buf, + buflen, + NULL); + + if (lasterror != 0) + return (0); + + /* Fall through to the fallback error code */ + } + + /* Fallback to a generic message, then guess it's a memory problem. */ + return ( + snprintf(buf, buflen, "error return: %d", error) > 0 ? 0 : ENOMEM); } diff --git a/src/os_win/os_ftruncate.c b/src/os_win/os_ftruncate.c index e80308536f1..d9b43e4596f 100644 --- a/src/os_win/os_ftruncate.c +++ b/src/os_win/os_ftruncate.c @@ -17,7 +17,6 @@ __wt_ftruncate(WT_SESSION_IMPL *session, WT_FH *fh, wt_off_t len) { WT_DECL_RET; LARGE_INTEGER largeint; - uint32_t lasterror; largeint.QuadPart = len; @@ -32,10 +31,8 @@ __wt_ftruncate(WT_SESSION_IMPL *session, WT_FH *fh, wt_off_t len) return (0); } - lasterror = GetLastError(); - - if (lasterror = ERROR_USER_MAPPED_FILE) + if (GetLastError() == ERROR_USER_MAPPED_FILE) return (EBUSY); - WT_RET_MSG(session, lasterror, "%s SetEndOfFile error", fh->name); + WT_RET_MSG(session, __wt_errno(), "%s SetEndOfFile error", fh->name); } diff --git a/src/os_win/os_mtx_cond.c b/src/os_win/os_mtx_cond.c index 71ea8ed49a2..36de49d1aae 100644 --- a/src/os_win/os_mtx_cond.c +++ b/src/os_win/os_mtx_cond.c @@ -45,7 +45,6 @@ __wt_cond_wait(WT_SESSION_IMPL *session, WT_CONDVAR *cond, long usecs) { WT_DECL_RET; int locked; - int lasterror; int milliseconds; locked = 0; WT_ASSERT(session, usecs >= 0); @@ -82,8 +81,7 @@ __wt_cond_wait(WT_SESSION_IMPL *session, WT_CONDVAR *cond, long usecs) &cond->cond, &cond->mtx, INFINITE); if (ret == 0) { - lasterror = GetLastError(); - if (lasterror == ERROR_TIMEOUT) { + if (GetLastError() == ERROR_TIMEOUT) { ret = 1; } } diff --git a/src/os_win/os_rename.c b/src/os_win/os_rename.c index 8c2784457c4..a0f33843218 100644 --- a/src/os_win/os_rename.c +++ b/src/os_win/os_rename.c @@ -33,13 +33,13 @@ __wt_rename(WT_SESSION_IMPL *session, const char *from, const char *to) */ if ((ret = GetFileAttributesA(to_path)) != INVALID_FILE_ATTRIBUTES) { if ((ret = DeleteFileA(to_path)) == FALSE) { - lasterror = GetLastError(); + lasterror = __wt_errno(); goto err; } } if ((MoveFileA(from_path, to_path)) == FALSE) - lasterror = GetLastError(); + lasterror = __wt_errno(); err: __wt_free(session, from_path); diff --git a/test/suite/test_config02.py b/test/suite/test_config02.py index c4a6d48f8b4..7e3570a1a37 100644 --- a/test/suite/test_config02.py +++ b/test/suite/test_config02.py @@ -147,7 +147,7 @@ class test_config02(wttest.WiredTigerTestCase): dir = 'nondir' self.assertRaisesWithMessage(wiredtiger.WiredTigerError, lambda: wiredtiger.wiredtiger_open(dir, 'create'), - '/No such file or directory/') + '/(No such file or directory|The system cannot find the path specified)/') def test_home_not_writeable(self): if os.name == "nt": diff --git a/test/suite/test_config03.py b/test/suite/test_config03.py index b1cb328e093..3a1bbd76773 100644 --- a/test/suite/test_config03.py +++ b/test/suite/test_config03.py @@ -103,12 +103,12 @@ class test_config03(test_base03.test_base03): if self.s_create == False: successargs = successargs.replace(',create=false,',',create,') expect_fail = True - fail_msg = '/No such file or directory/' + fail_msg = '/(No such file or directory|The system cannot find the file specified)/' elif self.s_create == None: successargs = successargs + 'create=true,' expect_fail = True - fail_msg = '/No such file or directory/' - + fail_msg = '/(No such file or directory|The system cannot find the file specified)/' + if self.s_eviction_target >= self.s_eviction_trigger: # construct args that guarantee that target < trigger # we know that trigger >= 1 |