diff options
author | Don Anderson <dda@ddanderson.com> | 2011-03-31 07:44:57 -0400 |
---|---|---|
committer | Don Anderson <dda@ddanderson.com> | 2011-03-31 07:44:57 -0400 |
commit | 8d2fdaa95502171653c7bbf153761ee9da72345d (patch) | |
tree | 4ad20fdcd39dd8f6d602b114e8fb10aedcdc5777 | |
parent | 840a648121921c1879b2fb0b489071a2b4878d99 (diff) | |
download | mongo-8d2fdaa95502171653c7bbf153761ee9da72345d.tar.gz |
Added ex_access.py, and added typemaps, etc. to make it all work.
This changeset also includes configure and Make.base changes to
force -g on for setup.py, and to *disable* -O if debug is enabled.
That's probably not wanted in the release tree, but is essential
for debugging SWIG.
refs #31
--HG--
extra : rebase_source : d6eb4ffab30aa8901b73467e038cb82168308545
-rw-r--r-- | .hgignore | 1 | ||||
-rw-r--r-- | build_posix/Make.base | 6 | ||||
-rw-r--r-- | build_posix/configure.ac | 6 | ||||
-rwxr-xr-x | examples/python/ex_access.py | 44 | ||||
-rw-r--r-- | lang/python/wiredtiger.i | 206 | ||||
-rw-r--r-- | src/include/wiredtiger.in | 66 |
6 files changed, 291 insertions, 38 deletions
diff --git a/.hgignore b/.hgignore index 4c2acd1f6e7..862f32c8f54 100644 --- a/.hgignore +++ b/.hgignore @@ -16,3 +16,4 @@ ^src/server ^test/bt/(CONFIG|__rand|__wt.bdb|__wt.run|__wt.wt|db|t|vgout\..*) /tags$ +~$ diff --git a/build_posix/Make.base b/build_posix/Make.base index a25e63a2a10..925c9dd772c 100644 --- a/build_posix/Make.base +++ b/build_posix/Make.base @@ -26,7 +26,11 @@ prototype.chk: $(libwiredtiger_a_SOURCES) @(cd ../dist && sh s_prototypes) && touch $@ if PYTHON +if DEBUG +PY_SETUP_DEBUG = -g +wiredtiger_wrap_o_CFLAGS = -g +endif all-local: ../lang/python/_wiredtiger.so endif ../lang/python/_wiredtiger.so: libwiredtiger.a ../lang/python/wiredtiger.i - @(cd ../lang/python ; python setup.py build_ext -f -i) + @(cd ../lang/python ; python setup.py build_ext -f -i $(PY_SETUP_DEBUG)) diff --git a/build_posix/configure.ac b/build_posix/configure.ac index ab13e625e3f..c1dc0c41324 100644 --- a/build_posix/configure.ac +++ b/build_posix/configure.ac @@ -32,7 +32,10 @@ if test "$GCC" = "yes"; then # # If we're using gcc, change the optimization to -O3, unless we're # doing a small build, in which case we use -Os. - if test "$db_cv_enable_smallbuild" = "yes"; then + if test "$db_cv_enable_debug" = "yes"; then + # don't touch for debugging + : + elif test "$db_cv_enable_smallbuild" = "yes"; then CFLAGS=`echo "$CFLAGS" | sed 's/-O./-Os /g'` else CFLAGS=`echo "$CFLAGS" | sed 's/-O./-O3 /g'` @@ -61,6 +64,7 @@ if test "$db_cv_enable_debug" = "yes"; then CFLAGS=`echo "$CFLAGS" | sed 's/-g//g'` CFLAGS="$CFLAGS -g" fi +AM_CONDITIONAL(DEBUG, test "$db_cv_enable_debug" = "yes") # Python API if test "$db_cv_enable_python" = "yes"; then diff --git a/examples/python/ex_access.py b/examples/python/ex_access.py new file mode 100755 index 00000000000..5fb0abdbc9e --- /dev/null +++ b/examples/python/ex_access.py @@ -0,0 +1,44 @@ +#!/usr/bin/env PYTHONPATH=../../lang/python:../../lang/python/src python +# +# See the file LICENSE for redistribution information. +# +# Copyright (c) 2008-2011 WiredTiger, Inc. +# All rights reserved. +# +# ex_access.py +# demonstrates how to create and access a simple table. +# + +import wiredtiger +import sys + +home = 'WT_TEST' + +try: + conn = wiredtiger.wiredtiger_open(home, None, 'create') + print('connected: ' + `conn`); + session = conn.open_session(None, None) +except BaseException as e: + print('Error connecting to', (home + ':'), e); + sys.exit(1) + +# Note: further error checking omitted for clarity. + +session.create_table('access', 'key_format=S,value_format=S') +cursor = session.open_cursor('table:access', None, None) + +# Insert a record. +cursor.set_key('key1') +cursor.set_value('value1') + +# TODO: remove try block when cursor.insert works +try: + cursor.insert() +except BaseException as tuple: + print('Error cursor insert: ', tuple); + +for key, value in cursor: + print('Got record: ' + key + ' : ' + value) + +conn.close(None) +sys.exit(0) diff --git a/lang/python/wiredtiger.i b/lang/python/wiredtiger.i index b4723c8bca9..8e6570aa01d 100644 --- a/lang/python/wiredtiger.i +++ b/lang/python/wiredtiger.i @@ -1,13 +1,213 @@ %module wiredtiger /* Set the input argument to point to a temporary variable */ -%typemap(in, numinputs=0) WT_CONNECTION ** (WT_CONNECTION *temp) { +%typemap(in, numinputs=0) WT_CONNECTION ** (WT_CONNECTION *temp = NULL) { $1 = &temp; } -/* Append connection to returned list */ +%typemap(in, numinputs=0) WT_SESSION ** (WT_SESSION *temp = NULL) { + $1 = &temp; +} +%typemap(in, numinputs=0) WT_CURSOR ** (WT_CURSOR *temp = NULL) { + $1 = &temp; +} + +/* Set the return value to the returned connection, session, or cursor */ %typemap(argout) WT_CONNECTION ** { - $result = SWIG_NewPointerObj(SWIG_as_voidptr($1), + $result = SWIG_NewPointerObj(SWIG_as_voidptr(*$1), SWIGTYPE_p_wt_connection, 0); } +%typemap(argout) WT_SESSION ** { + $result = SWIG_NewPointerObj(SWIG_as_voidptr(*$1), + SWIGTYPE_p_wt_session, 0); +} + +%typemap(argout) WT_CURSOR ** { + $result = SWIG_NewPointerObj(SWIG_as_voidptr(*$1), + SWIGTYPE_p_wt_cursor, 0); +} + + +/* Checking for error returns - any error is an exception. + * TODO: need to create a wiredtiger exception, probably language specific + */ +%typemap(out) int { + $result = SWIG_From_int((int)(result)); + if ($1 != 0 && $1 != WT_NOTFOUND) { + SWIG_exception_fail(SWIG_RuntimeError, wiredtiger_strerror($1)); + return NULL; + } +} + +/* + * Extra 'self' elimination. + * The methods we're wrapping look like this: + * struct wt_xxx { + * int method(WT_XXX *, ...otherargs...); + * }; + * as expected SWIG creates: + * wt_xxx.method(WT_XXX *, ...otherargs...); + * so we'd like to eliminate the WT_XXX * and set its value to + * the wt_xxx var. To make life difficult, a typemap with numinputs=0 + * (which we want to use for WT_XXX *) seems to be emitted before + * all other typemaps. SWIG doc claims that adjacent args can be + * typemapped as a single unit, that doesn't work here, I guess these two + * args are apparently not considered adjacent. Furthermore, + * there's no way to create an extra stack variable for them + * to communicate. + * + * Our solution is to use argp1 (a var that will be used used by + * wt_xxx *) as a holder. The holder keeps the address where we want + * stored the computed self value. The 'in' typemap for WT_XXX * sets + * that, and the 'in' typemape for wt_xxx * uses it to store the + * value. prepare_copy_self() and copy_self() encapsulate this + * communication between the two typemaps. + */ +%{ + static void prepare_copy_self(void ***holderp, void **myargp) + { + if (*holderp == NULL) { + *holderp = myargp; + } + } + + static void copy_self(void **holder, void *self) + { + if (holder != NULL) { + *holder = self; + } + } +%} + +// Can't do: $1 = self; , when this typemap is used, we don't always have +// self?? TODO: look at this more, it would clean things up some. +%typemap(in, numinputs=0) WT_CONNECTION *thisconnection, WT_SESSION *thissession, WT_CURSOR *thiscursor %{ + prepare_copy_self((void ***)&argp1, (void **)&$1); +%} + +// For some reason the following three cannot be combined in a single typemap +%typemap(in) struct wt_connection *self (void *argp = 0, int res = 0, void **copy) { + // struct wt_connection * + copy = (void **)argp; + res = SWIG_ConvertPtr($input, &argp,$descriptor, $disown | 0); + if (!SWIG_IsOK(res)) { + SWIG_exception_fail(SWIG_ArgError(res), "in method '" "$symname" "', argument " "$argnum" " of type '" "$type" "'"); + } + $1 = ($ltype)(argp); + copy_self(copy, $1); +} + +%typemap(in) struct wt_session *self (void *argp = 0, int res = 0, void **copy) { + // struct wt_session * + copy = (void **)argp; + res = SWIG_ConvertPtr($input, &argp,$descriptor, $disown | 0); + if (!SWIG_IsOK(res)) { + SWIG_exception_fail(SWIG_ArgError(res), "in method '" "$symname" "', argument " "$argnum" " of type '" "$type" "'"); + } + $1 = ($ltype)(argp); + copy_self(copy, $1); +} + +%typemap(in) struct wt_cursor *self (void *argp = 0, int res = 0, void **copy) { + // struct wt_cursor * + copy = (void **)argp; + res = SWIG_ConvertPtr($input, &argp,$descriptor, $disown | 0); + if (!SWIG_IsOK(res)) { + SWIG_exception_fail(SWIG_ArgError(res), "in method '" "$symname" "', argument " "$argnum" " of type '" "$type" "'"); + } + $1 = ($ltype)(argp); + copy_self(copy, $1); +} + +/* WT_CURSOR customization. + * We want our own 'next' function for wt_cursor, so we can + * implement iterable. Since nobody but use will use + * the 'real' version, we'll remove it to avoid confusion. + */ +%ignore next(WT_CURSOR *); + +/* We create an artificial return type for next, and use the typemap to + * convert it to its final value (a python tuple). That consolidates + * the return code. + * TODO: no need to do this anymore? + */ +%{ +typedef struct IterNextValue { + PyObject *pyobj; + int ret; +} IterNextValue; +%} + +%typemap(out) IterNextValue { + if ($1.ret != 0) { + if ($1.ret == WT_NOTFOUND) { + PyErr_SetString(PyExc_StopIteration, "No more data for cursor"); + } + else { + PyErr_SetString(PyExc_RuntimeError, wiredtiger_strerror($1.ret)); + } + $1.pyobj = NULL; + } + $result = $1.pyobj; +} + +/* Implement the iterable contract for wt_cursor */ +%extend wt_cursor { + struct wt_cursor *__iter__() { + return $self; + } + + IterNextValue next() { + // TODO: handle arbitrary types, not just strings! + char *keyptr = 0; + char *valptr = 0; + IterNextValue result; + int ret; + + result.pyobj = NULL; + ret = self->next(self); +#if 0 + //TODO: for testing until real insertion works + { + // fake some values to test the caller... + static int count = 2; + + if (count-- > 0) { + result.pyobj = Py_BuildValue("(ss)", "foo", "bar"); + result.ret = 0; + return result; + } + else { + ret = EIO; /* TODO!! */ + } + } +#endif + + if (ret == 0) { + ret = self->get_key(self, &keyptr); + } + if (ret == 0) { + ret = self->get_value(self, &valptr); + } + if (ret == 0) { + result.pyobj = Py_BuildValue("(ss)", keyptr, valptr); + } + result.ret = ret; + return result; + } +}; + +/* TODO: +// This typemap handles set_key, set_value. +// Unfortunately, the only way to distinguish between these two +// calls is to look at $symname. +%typemap(in) (WT_CURSOR *, ...) { + int symlen = strlen($symname); + int iskey = (symname == 7); +} +*? + +/*TODO: %varargs(void *arg) wt_cursor.set_key;*/ +%varargs(char *arg) set_key; +%varargs(char *arg) set_value; %include "wiredtiger.h" diff --git a/src/include/wiredtiger.in b/src/include/wiredtiger.in index 3e37ce66667..1976c2d890b 100644 --- a/src/include/wiredtiger.in +++ b/src/include/wiredtiger.in @@ -181,7 +181,7 @@ struct wt_cursor { * @param cursor the cursor handle * @errors */ - int __F(get_key)(WT_CURSOR *cursor, ...); + int __F(get_key)(WT_CURSOR *thiscursor, ...); /*! Get the value for the current record. * @@ -191,7 +191,7 @@ struct wt_cursor { * @param cursor the cursor handle * @errors */ - int __F(get_value)(WT_CURSOR *cursor, ...); + int __F(get_value)(WT_CURSOR *thiscursor, ...); /*! Set the key for the next operation. * @@ -205,7 +205,7 @@ struct wt_cursor { * cursor, and the next operation to access the key will fail. This * simplifies error handling in applications. */ - void __F(set_key)(WT_CURSOR *cursor, ...); + void __F(set_key)(WT_CURSOR *thiscursor, ...); /*! Set the data for the next operation. * @@ -219,7 +219,7 @@ struct wt_cursor { * cursor, and the next operation to access the value will fail. This * simplifies error handling in applications. */ - void __F(set_value)(WT_CURSOR *cursor, ...); + void __F(set_value)(WT_CURSOR *thiscursor, ...); /*! @} */ /*! @name Cursor positioning @@ -233,7 +233,7 @@ struct wt_cursor { * @param cursor the cursor handle * @errors */ - int __F(first)(WT_CURSOR *cursor); + int __F(first)(WT_CURSOR *thiscursor); /*! Move to the last record. * @@ -243,7 +243,7 @@ struct wt_cursor { * @param cursor the cursor handle * @errors */ - int __F(last)(WT_CURSOR *cursor); + int __F(last)(WT_CURSOR *thiscursor); /*! Move to the next record. * @@ -253,7 +253,7 @@ struct wt_cursor { * @param cursor the cursor handle * @errors */ - int __F(next)(WT_CURSOR *cursor); + int __F(next)(WT_CURSOR *thiscursor); /*! Move to the previous record. * @@ -263,7 +263,7 @@ struct wt_cursor { * @param cursor the cursor handle * @errors */ - int __F(prev)(WT_CURSOR *cursor); + int __F(prev)(WT_CURSOR *thiscursor); /*! Search for a record. * @@ -275,7 +275,7 @@ struct wt_cursor { * @param cursor the cursor handle * @errors */ - int __F(search)(WT_CURSOR *cursor); + int __F(search)(WT_CURSOR *thiscursor); /*! Search for a record. * @@ -289,7 +289,7 @@ struct wt_cursor { * found, -1 if a smaller key is found, +1 if a larger key is found * @errors */ - int __F(search_near)(WT_CURSOR *cursor, int *exactp); + int __F(search_near)(WT_CURSOR *thiscursor, int *exactp); /*! @} */ /*! @name Data modification @@ -308,7 +308,7 @@ struct wt_cursor { * @param cursor the cursor handle * @errors */ - int __F(insert)(WT_CURSOR *cursor); + int __F(insert)(WT_CURSOR *thiscursor); /*! Update the current record. The cursor must be positioned on a * record and the value of the record will be updated. If the record @@ -323,7 +323,7 @@ struct wt_cursor { * @param cursor the cursor handle * @errors */ - int __F(update)(WT_CURSOR *cursor); + int __F(update)(WT_CURSOR *thiscursor); /*! Remove the current record. * @@ -333,7 +333,7 @@ struct wt_cursor { * @param cursor the cursor handle * @errors */ - int __F(remove)(WT_CURSOR *cursor); + int __F(remove)(WT_CURSOR *thiscursor); /*! @} */ /*! Close the cursor. @@ -350,7 +350,7 @@ struct wt_cursor { * @configend * @errors */ - int __F(close)(WT_CURSOR *cursor, const char *config); + int __F(close)(WT_CURSOR *thiscursor, const char *config); /* * Protected fields, only to be used by cursor implementations. @@ -407,7 +407,7 @@ struct wt_session { * @configend * @errors */ - int __F(close)(WT_SESSION *session, const char *config); + int __F(close)(WT_SESSION *thissession, const char *config); /*! @name Cursor handles * @{ @@ -468,7 +468,7 @@ struct wt_session { * @param cursorp a pointer to the newly opened cursor * @errors */ - int __F(open_cursor)(WT_SESSION *session, + int __F(open_cursor)(WT_SESSION *thissession, const char *uri, WT_CURSOR *to_dup, const char *config, WT_CURSOR **cursorp); /*! @} */ @@ -522,7 +522,7 @@ struct wt_session { * @configend * @errors */ - int __F(create_table)(WT_SESSION *session, const char *name, + int __F(create_table)(WT_SESSION *thissession, const char *name, const char *config); /*! Rename a table. @@ -537,7 +537,7 @@ struct wt_session { * @configend * @errors */ - int __F(rename_table)(WT_SESSION *session, + int __F(rename_table)(WT_SESSION *thissession, const char *oldname, const char *newname, const char *config); /*! Drop (delete) a table. @@ -551,7 +551,7 @@ struct wt_session { * @configend * @errors */ - int __F(drop_table)(WT_SESSION *session, + int __F(drop_table)(WT_SESSION *thissession, const char *name, const char *config); /*! Truncate a table. @@ -572,7 +572,7 @@ struct wt_session { * @configend * @errors */ - int __F(truncate_table)(WT_SESSION *session, const char *name, + int __F(truncate_table)(WT_SESSION *thissession, const char *name, WT_CURSOR *start, WT_CURSOR *end, const char *config); /*! Verify a table. @@ -588,7 +588,7 @@ struct wt_session { * @configend * @errors */ - int __F(verify_table)(WT_SESSION *session, const char *name, + int __F(verify_table)(WT_SESSION *thissession, const char *name, const char *config); /*! @} */ @@ -623,7 +623,7 @@ struct wt_session { * @configend * @errors */ - int __F(begin_transaction)(WT_SESSION *session, const char *config); + int __F(begin_transaction)(WT_SESSION *thissession, const char *config); /*! Commit the current transaction. * @@ -640,7 +640,7 @@ struct wt_session { * @configend * @errors */ - int __F(commit_transaction)(WT_SESSION *session, const char *config); + int __F(commit_transaction)(WT_SESSION *thissession, const char *config); /*! Roll back the current transaction. * @@ -657,7 +657,7 @@ struct wt_session { * @configend * @errors */ - int __F(rollback_transaction)(WT_SESSION *session, const char *config); + int __F(rollback_transaction)(WT_SESSION *thissession, const char *config); /*! Flush the cache and/or the log and optionally archive log files. * @@ -708,7 +708,7 @@ struct wt_connection { * @configend * @errors */ - int __F(load_extension)(WT_CONNECTION *connection, + int __F(load_extension)(WT_CONNECTION *thisconnection, const char *path, const char *config); /*! Add a new type of cursor. @@ -733,7 +733,7 @@ struct wt_connection { * @configend * @errors */ - int __F(add_cursor_type)(WT_CONNECTION *connection, + int __F(add_cursor_type)(WT_CONNECTION *thisconnection, const char *prefix, WT_CURSOR_TYPE *ctype, const char *config); /*! Add a custom collation function. @@ -757,7 +757,7 @@ struct wt_connection { * @configend * @errors */ - int __F(add_collator)(WT_CONNECTION *connection, + int __F(add_collator)(WT_CONNECTION *thisconnection, const char *name, WT_COLLATOR *collator, const char *config); /*! Add a custom extractor for index keys or column groups. @@ -781,7 +781,7 @@ struct wt_connection { * @configend * @errors */ - int __F(add_extractor)(WT_CONNECTION *connection, const char *name, + int __F(add_extractor)(WT_CONNECTION *thisconnection, const char *name, WT_EXTRACTOR *extractor, const char *config); /*! Close a connection. @@ -796,7 +796,7 @@ struct wt_connection { * @configend * @errors */ - int __F(close)(WT_CONNECTION *connection, const char *config); + int __F(close)(WT_CONNECTION *thisconnection, const char *config); /*! The home directory of the connection. * @@ -806,7 +806,7 @@ struct wt_connection { * @param connection the connection handle * @returns a pointer to a string naming the home directory */ - const char *__F(get_home)(WT_CONNECTION *connection); + const char *__F(get_home)(WT_CONNECTION *thisconnection); /*! Did opening this handle create the database? * @@ -819,7 +819,7 @@ struct wt_connection { * ::wiredtiger_open, true (non-zero) if it was created by opening * this handle. */ - int __F(is_new)(WT_CONNECTION *connection); + int __F(is_new)(WT_CONNECTION *thisconnection); /*! Open a session. * @@ -834,8 +834,8 @@ struct wt_connection { * @param sessionp the new session handle * @errors */ - int __F(open_session)(WT_CONNECTION *connection, - WT_EVENT_HANDLER *errhandler, const char *config, + int __F(open_session)(WT_CONNECTION *thisconnection, + WT_ERROR_HANDLER *errhandler, const char *config, WT_SESSION **sessionp); }; |