# Output C #defines for errors into wiredtiger.in and the associated error # message code in strerror.c. import re, textwrap from dist import compare_srcfile class Error: def __init__(self, name, value, desc, long_desc=None, **flags): self.name = name self.value = value self.desc = desc self.long_desc = long_desc self.flags = flags # We don't want our error returns to conflict with any other package, # so use an uncommon range, specifically, -31,800 to -31,999. # # These numbers cannot change without breaking backward compatibility, # and are listed in error value order. errors = [ Error('WT_ROLLBACK', -31800, 'conflict between concurrent operations', ''' This error is generated when an operation cannot be completed due to a conflict with concurrent operations. The operation may be retried; if a transaction is in progress, it should be rolled back and the operation retried in a new transaction.'''), Error('WT_DUPLICATE_KEY', -31801, 'attempt to insert an existing key', ''' This error is generated when the application attempts to insert a record with the same key as an existing record without the 'overwrite' configuration to WT_SESSION::open_cursor.'''), Error('WT_ERROR', -31802, 'non-specific WiredTiger error', ''' This error is returned when an error is not covered by a specific error return.'''), Error('WT_NOTFOUND', -31803, 'item not found', ''' This error indicates an operation did not find a value to return. This includes cursor search and other operations where no record matched the cursor's search key such as WT_CURSOR::update or WT_CURSOR::remove.'''), Error('WT_PANIC', -31804, 'WiredTiger library panic', ''' This error indicates an underlying problem that requires the application exit and restart. The application can exit immediately when \c WT_PANIC is returned from a WiredTiger interface, no further WiredTiger calls are required.'''), Error('WT_RESTART', -31805, 'restart the operation (internal)', undoc=True), Error('WT_RUN_RECOVERY', -31806, 'recovery must be run to continue', ''' This error is generated when wiredtiger_open is configured to return an error if recovery is required to use the database.'''), Error('WT_CACHE_FULL', -31807, 'operation would overflow cache', ''' This error is only generated when wiredtiger_open is configured to run in-memory, and an insert or update operation requires more than the configured cache size to complete. The operation may be retried; if a transaction is in progress, it should be rolled back and the operation retried in a new transaction.'''), ] # Update the #defines in the wiredtiger.in file. tmp_file = '__tmp' tfile = open(tmp_file, 'w') skip = 0 for line in open('../src/include/wiredtiger.in', 'r'): if not skip: tfile.write(line) if line.count('Error return section: END'): tfile.write(line) skip = 0 elif line.count('Error return section: BEGIN'): tfile.write(' */\n') skip = 1 for err in errors: if 'undoc' in err.flags: tfile.write('/*! @cond internal */\n') tfile.write('/*!%s.%s */\n' % (('\n * ' if err.long_desc else ' ') + err.desc[0].upper() + err.desc[1:], ''.join('\n * ' + l for l in textwrap.wrap( textwrap.dedent(err.long_desc).strip(), 77)) + '\n' if err.long_desc else '')) tfile.write('#define\t%s\t(%d)\n' % (err.name, err.value)) if 'undoc' in err.flags: tfile.write('/*! @endcond */\n') tfile.write('/*\n') tfile.close() compare_srcfile(tmp_file, '../src/include/wiredtiger.in') # 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. */ #include "wt_internal.h" /* * 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 WT_SESSION.strerror method. Because we * want wiredtiger_strerror to continue to be as thread-safe as possible, errors * are split into two categories: WiredTiger's or the system's constant strings * and Everything Else, and we check constant strings before Everything Else. */ /* * __wt_wiredtiger_error -- *\tReturn a constant string for POSIX-standard and WiredTiger errors. */ const char * __wt_wiredtiger_error(int error) { \tconst char *p; \t/* \t * Check for WiredTiger specific errors. \t */ \tswitch (error) { ''') for err in errors: tfile.write('\tcase ' + err.name + ':\n') tfile.write('\t\treturn ("' + err.name + ': ' + err.desc + '");\n') tfile.write('''\t} \t/* \t * POSIX errors are non-negative integers; check for 0 explicitly incase \t * the underlying strerror doesn't handle 0, some historically didn't. \t */ \tif (error == 0) \t\treturn ("Successful return: 0"); \tif (error > 0 && (p = strerror(error)) != NULL) \t\treturn (p); \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]; \treturn (__wt_strerror(NULL, error, buf, sizeof(buf))); } ''') tfile.close() compare_srcfile(tmp_file, '../src/conn/api_strerror.c') # Update the error documentation block. doc = '../src/docs/error-handling.dox' tmp_file = '__tmp' tfile = open(tmp_file, 'w') skip = 0 for line in open(doc, 'r'): if not skip: tfile.write(line) if line.count('IGNORE_BUILT_BY_API_ERR_END'): tfile.write(line) skip = 0 elif line.count('IGNORE_BUILT_BY_API_ERR_BEGIN'): tfile.write('@endif\n\n') skip = 1 for err in errors: if 'undoc' in err.flags: continue tfile.write( '@par ' + err.name.upper() + '\n' + " ".join(err.long_desc.split()) + '\n\n') tfile.close() compare_srcfile(tmp_file, doc)