Changeset: a6c7dd424a5d for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=a6c7dd424a5d
Added Files:
gdk/shared_memory.c
gdk/shared_memory.h
monetdb5/extras/pyapi/50_pyapi.mal
monetdb5/extras/pyapi/Makefile.ag
monetdb5/extras/pyapi/Tests/All
monetdb5/extras/pyapi/Tests/pyapi_numpy_boolean.malC
monetdb5/extras/pyapi/Tests/pyapi_numpy_boolean.stable.err
monetdb5/extras/pyapi/Tests/pyapi_numpy_boolean.stable.out
monetdb5/extras/pyapi/Tests/pyapi_numpy_numeric_nested.malC
monetdb5/extras/pyapi/Tests/pyapi_numpy_numeric_nested.stable.err
monetdb5/extras/pyapi/Tests/pyapi_numpy_numeric_nested.stable.out
monetdb5/extras/pyapi/Tests/pyapi_pandas.malC
monetdb5/extras/pyapi/Tests/pyapi_pandas.stable.err
monetdb5/extras/pyapi/Tests/pyapi_pandas.stable.out
monetdb5/extras/pyapi/Tests/pyapi_returntypes.malC
monetdb5/extras/pyapi/Tests/pyapi_returntypes.stable.err
monetdb5/extras/pyapi/Tests/pyapi_returntypes.stable.out
monetdb5/extras/pyapi/Tests/pyapi_types_boolean.malC
monetdb5/extras/pyapi/Tests/pyapi_types_boolean.stable.err
monetdb5/extras/pyapi/Tests/pyapi_types_boolean.stable.out
monetdb5/extras/pyapi/Tests/pyapi_types_huge.malC
monetdb5/extras/pyapi/Tests/pyapi_types_huge.stable.err
monetdb5/extras/pyapi/Tests/pyapi_types_huge.stable.out
monetdb5/extras/pyapi/Tests/pyapi_types_numeric.malC
monetdb5/extras/pyapi/Tests/pyapi_types_numeric.stable.err
monetdb5/extras/pyapi/Tests/pyapi_types_numeric.stable.out
monetdb5/extras/pyapi/Tests/pyapi_types_string.malC
monetdb5/extras/pyapi/Tests/pyapi_types_string.stable.err
monetdb5/extras/pyapi/Tests/pyapi_types_string.stable.out
monetdb5/extras/pyapi/connection.c
monetdb5/extras/pyapi/connection.h
monetdb5/extras/pyapi/formatinput.c
monetdb5/extras/pyapi/formatinput.h
monetdb5/extras/pyapi/pyapi.c
monetdb5/extras/pyapi/pyapi.h
monetdb5/extras/pyapi/pyapi.mal
monetdb5/extras/pyapi/pytypes.c
monetdb5/extras/pyapi/pytypes.h
monetdb5/extras/pyapi/type_conversion.c
monetdb5/extras/pyapi/type_conversion.h
monetdb5/extras/pyapi/unicode.c
monetdb5/extras/pyapi/unicode.h
sql/backends/monet5/Tests/pyapi00.sql
sql/backends/monet5/Tests/pyapi00.stable.err
sql/backends/monet5/Tests/pyapi00.stable.out
sql/backends/monet5/Tests/pyapi01.sql
sql/backends/monet5/Tests/pyapi01.stable.err
sql/backends/monet5/Tests/pyapi01.stable.out
sql/backends/monet5/Tests/pyapi02.sql
sql/backends/monet5/Tests/pyapi02.sql.orig
sql/backends/monet5/Tests/pyapi02.stable.err
sql/backends/monet5/Tests/pyapi02.stable.out
sql/backends/monet5/Tests/pyapi03.sql
sql/backends/monet5/Tests/pyapi03.stable.err
sql/backends/monet5/Tests/pyapi03.stable.out
sql/backends/monet5/Tests/pyapi04.sql
sql/backends/monet5/Tests/pyapi04.stable.err
sql/backends/monet5/Tests/pyapi04.stable.out
sql/backends/monet5/Tests/pyapi05.sql
sql/backends/monet5/Tests/pyapi05.stable.err
sql/backends/monet5/Tests/pyapi05.stable.out
sql/backends/monet5/Tests/pyapi06.sql
sql/backends/monet5/Tests/pyapi06.stable.err
sql/backends/monet5/Tests/pyapi06.stable.out
sql/backends/monet5/Tests/pyapi07.sql
sql/backends/monet5/Tests/pyapi07.stable.err
sql/backends/monet5/Tests/pyapi07.stable.out
sql/backends/monet5/Tests/pyapi08.sql
sql/backends/monet5/Tests/pyapi08.sql.orig
sql/backends/monet5/Tests/pyapi08.stable.err
sql/backends/monet5/Tests/pyapi08.stable.out
sql/backends/monet5/Tests/pyapi09.sql
sql/backends/monet5/Tests/pyapi09.stable.err
sql/backends/monet5/Tests/pyapi09.stable.out
sql/backends/monet5/Tests/pyapi10.sql
sql/backends/monet5/Tests/pyapi10.stable.err
sql/backends/monet5/Tests/pyapi10.stable.out
sql/backends/monet5/Tests/pyapi11.sql
sql/backends/monet5/Tests/pyapi11.stable.err
sql/backends/monet5/Tests/pyapi11.stable.out
sql/backends/monet5/Tests/pyapi12.sql
sql/backends/monet5/Tests/pyapi12.stable.err
sql/backends/monet5/Tests/pyapi12.stable.out
sql/backends/monet5/Tests/pyapi13.sql
sql/backends/monet5/Tests/pyapi13.stable.err
sql/backends/monet5/Tests/pyapi13.stable.out
sql/backends/monet5/Tests/pyapi14.sql
sql/backends/monet5/Tests/pyapi14.stable.err
sql/backends/monet5/Tests/pyapi14.stable.out
sql/backends/monet5/Tests/pyapi15.sql
sql/backends/monet5/Tests/pyapi16.sql
sql/backends/monet5/Tests/pyapi16.stable.err
sql/backends/monet5/Tests/pyapi16.stable.out
sql/backends/monet5/Tests/pyapi17.sql
sql/backends/monet5/Tests/pyapi17.stable.err
sql/backends/monet5/Tests/pyapi17.stable.out
sql/backends/monet5/Tests/pyapi18.sql
sql/backends/monet5/Tests/pyapi18.stable.err
sql/backends/monet5/Tests/pyapi18.stable.out
sql/backends/monet5/Tests/pyapi19.sql
sql/backends/monet5/Tests/pyapi19.stable.err
sql/backends/monet5/Tests/pyapi19.stable.out
sql/backends/monet5/Tests/pyapi20.sql
sql/backends/monet5/Tests/pyapi20.stable.err
sql/backends/monet5/Tests/pyapi20.stable.out
sql/backends/monet5/Tests/pyapi21.sql
sql/backends/monet5/Tests/pyapi21.stable.err
sql/backends/monet5/Tests/pyapi21.stable.out
sql/backends/monet5/Tests/pyapi23.sql
sql/backends/monet5/Tests/pyapi23.stable.err
sql/backends/monet5/Tests/pyapi23.stable.out
sql/backends/monet5/Tests/pyapi24.sql
sql/backends/monet5/Tests/pyapi24.stable.err
sql/backends/monet5/Tests/pyapi24.stable.out
sql/backends/monet5/Tests/pyapi25.sql
sql/backends/monet5/Tests/pyapi25.stable.err
sql/backends/monet5/Tests/pyapi25.stable.out
sql/backends/monet5/Tests/pyapi26.sql
sql/backends/monet5/Tests/pyapi26.stable.err
sql/backends/monet5/Tests/pyapi26.stable.out
sql/backends/monet5/Tests/pyapi27.sql
sql/backends/monet5/Tests/pyapi27.stable.err
sql/backends/monet5/Tests/pyapi27.stable.out
Modified Files:
clients/mapiclient/mclient.c
configure.ag
gdk/Makefile.ag
gdk/gdk.h
gdk/gdk_heap.c
monetdb5/extras/Makefile.ag
monetdb5/optimizer/opt_prelude.c
monetdb5/optimizer/opt_prelude.h
monetdb5/optimizer/opt_support.c
sql/backends/monet5/Tests/All
sql/backends/monet5/mal_backend.h
sql/backends/monet5/sql.c
sql/backends/monet5/sql_execute.c
sql/backends/monet5/sql_gencode.c
sql/backends/monet5/sql_result.c
sql/include/sql_catalog.h
sql/server/rel_psm.c
sql/server/sql_parser.y
testing/Mtest.py.in
Branch: pythonudf
Log Message:
Initial branch commit; Python UDFs.
This branch is a clean version of the pyapi branch. It does not have any of the
unnecessary benchmarking code, and does not have any of the monetdblite code.
Only Python UDFs and associated test cases.
diffs (truncated from 15543 to 300 lines):
diff --git a/clients/mapiclient/mclient.c b/clients/mapiclient/mclient.c
--- a/clients/mapiclient/mclient.c
+++ b/clients/mapiclient/mclient.c
@@ -1220,8 +1220,7 @@ static void
TIMERrenderer(MapiHdl hdl)
{
SQLqueryEcho(hdl);
- while (fetch_line(hdl) != 0)
- ;
+ mapi_next_result(hdl);
printf("%s\n", timerHuman());
}
@@ -3270,6 +3269,9 @@ main(int argc, char **argv)
setFormatter("raw");
}
}
+ if (formatter == TIMERformatter) {
+ mapi_cache_limit(mid, 1);
+ }
/* give the user a welcome message with some general info */
if (!has_fileargs && command == NULL && isatty(fileno(stdin))) {
char *lang;
diff --git a/configure.ag b/configure.ag
--- a/configure.ag
+++ b/configure.ag
@@ -223,6 +223,13 @@ AC_ARG_ENABLE(rintegration,
enable_rintegration=$enableval,
enable_rintegration=$dft_rintegration)
+dft_pyintegration=auto
+AC_ARG_ENABLE(pyintegration,
+ AS_HELP_STRING([--enable-pyintegration],
+ [enable support for Python integration into MonetDB
(default=auto)]),
+ enable_pyintegration=$enableval,
+ enable_pyintegration=$dft_pyintegration)
+
dft_odbc=auto
AC_ARG_ENABLE(odbc,
AS_HELP_STRING([--enable-odbc],
@@ -2245,6 +2252,7 @@ AC_SUBST(SPHINXCLIENT_CFLAGS, $SPHINXCLI
AC_SUBST(SPHINXCLIENT_LIBS, $SPHINXCLIENT_LIBS)
AM_CONDITIONAL(HAVE_SPHINXCLIENT, test x"$have_sphinxclient" != xno)
+# R API (R UDFs)
have_libr=no
if test "x$enable_rintegration" != xno; then
case "$enable_rintegration" in
@@ -2280,6 +2288,85 @@ if test "x$enable_rintegration" != xno;
fi
AM_CONDITIONAL(HAVE_LIBR, test x"$have_libr" != xno)
+# Python API (Python UDFs)
+have_libpy=no
+have_libpandas=no
+have_libscipy=no
+if test "x$enable_pyintegration" != xno; then
+ case "$enable_pyintegration" in
+ yes|auto)
+ XPATH="$PATH"
+ ;;
+ /*)
+ XPATH="$enable_pyintegration"
+ enable_pyintegration=yes
+ ;;
+ *)
+ AC_MSG_ERROR([--enable-pyintegration value must be
yes|no|auto|absolute path of python-config])
+ ;;
+ esac
+ AC_PATH_PROG(PYCMD,python-config,,$XPATH)
+ if test "x$PYCMD" = x; then
+ if test "x$enable_pyintegration" = xyes; then
+ AC_MSG_ERROR([python-config library required for Python
integration support])
+ else
+ have_libpy="no"
+ why_have_libpy="(python-config command not found)"
+ enable_pyintegration=no
+ disable_pyintegration="(python-config command not
found)"
+ fi
+ fi
+ PYTHON_CMD=`$PYCMD --exec-prefix`/bin/python
+ NUMPYVER=`$PYTHON_CMD -c "import numpy; print
numpy.__version__.split('.').__getitem__(1) >= 7"`
+ #check numpyconfig.h because autoconf tests includes by compiling a
small C program, and other numpy headers do not compile without Python.h
+ AC_CHECK_HEADER(
+ [numpy/numpyconfig.h],
+ [NUMPYHEADERS=True],
+ [NUMPYHEADERS=`$PYTHON_CMD -c "import numpy, os; print
os.path.isfile(os.path.join(numpy.get_include(), 'numpy/arrayobject.h'))"`]
+ )
+ if [test "x$NUMPYVER" = x] || [test "x$NUMPYVER" = xFalse]; then
+ if test "x$enable_pyintegration" = xyes; then
+ AC_MSG_ERROR([numpy version >= 1.7.0 required for
Python integration support])
+ else
+ have_libpy="no"
+ why_have_libpy="(numpy version >= 1.7.0 not found)"
+ enable_pyintegration=no
+ disable_pyintegration="(numpy version >= 1.7.0 not
found)"
+ fi
+ elif [test "x$NUMPYHEADERS" = xFalse ]; then
+ if test "x$enable_pyintegration" = xyes; then
+ AC_MSG_ERROR([numpy/arrayobject.h not found])
+ else
+ have_libpy="no"
+ why_have_libpy="(numpy/arrayobject.h not found)"
+ enable_pyintegration=no
+ disable_pyintegration="(numpy/arrayobject.h not found)"
+ fi
+ elif libpy_CFLAGS=`\`$PYCMD --exec-prefix\`/bin/python -c "from
distutils.sysconfig import get_python_inc; import numpy; print ' -I' +
get_python_inc() + ' -I' + numpy.get_include();"` && libpy_LIBS=`$PYCMD
--ldflags`; then
+ have_libpy=yes
+ AC_DEFINE(HAVE_LIBPY, 1, [Define if we can link to python])
+ AC_SUBST(libpy_CFLAGS, $libpy_CFLAGS)
+ AC_SUBST(libpy_LIBS, $libpy_LIBS)
+ PANDAS=`$PYTHON_CMD -c "import pandas; print 1"`
+ if [test "x$PANDAS" = x1]; then
+ have_libpandas=yes
+ fi
+ SCIPY=`$PYTHON_CMD -c "import scipy; print 1"`
+ if [test "x$SCIPY" = x1]; then
+ have_libscipy=yes
+ fi
+ fi
+fi
+AM_CONDITIONAL(HAVE_LIBPY, test x"$have_libpy" != xno)
+AM_CONDITIONAL(HAVE_LIBPANDAS, test x"$have_libpandas" != xno)
+AM_CONDITIONAL(HAVE_LIBSCIPY, test x"$have_libscipy" != xno)
+
+AC_CHECK_HEADER([sys/sem.h], [SEMOP=True], [SEMOP=False])
+if [test "x$SEMOP" = "xTrue"]; then
+ AC_CHECK_FUNC(semtimedop, [AC_DEFINE(HAVE_SEMTIMEDOP, 1, [Define if
semtimedop exists])],)
+ AC_CHECK_FUNC(fork, [AC_DEFINE(HAVE_FORK, 1, [Define if fork exists])],
)
+fi
+
# ODBC, only used by ODBC driver
if test "x$enable_odbc" != xno; then
have_unixodbc=auto
@@ -3426,6 +3513,7 @@ for comp in \
'geom ' \
'console ' \
'microhttpd ' \
+ 'pyintegration' \
'rintegration' \
'odbc ' \
'jdbc ' \
diff --git a/gdk/Makefile.ag b/gdk/Makefile.ag
--- a/gdk/Makefile.ag
+++ b/gdk/Makefile.ag
@@ -31,7 +31,7 @@ lib_gdk = {
gdk_unique.c \
gdk_firstn.c \
bat.feps bat1.feps bat2.feps \
- libbat.rc
+ libbat.rc shared_memory.c shared_memory.h
LIBS = ../common/options/libmoptions \
../common/stream/libstream \
../common/utils/libmutils \
diff --git a/gdk/gdk.h b/gdk/gdk.h
--- a/gdk/gdk.h
+++ b/gdk/gdk.h
@@ -641,9 +641,12 @@ typedef enum { GDK_FAIL, GDK_SUCCEED } g
/* Heap storage modes */
typedef enum {
- STORE_MEM = 0, /* load into GDKmalloced memory */
- STORE_MMAP = 1, /* mmap() into virtual memory */
- STORE_PRIV = 2, /* BAT copy of copy-on-write mmap */
+ STORE_MEM = 0, /* load into GDKmalloced memory */
+ STORE_MMAP = 1, /* mmap() into virtual memory */
+ STORE_PRIV = 2, /* BAT copy of copy-on-write mmap */
+ STORE_CMEM = 3, /* Indicates the value is stored in regular C
memory rather than GDK memory.*/
+ STORE_NOWN = 4, /* Indicates that the bat does not own the chunk
of memory and is not in charge of freeing it.*/
+ STORE_MMAPABS = 5, /* mmap() into virtual memory from an absolute
path (not part of dbfarm) */
STORE_INVALID /* invalid value, used to indicate error */
} storage_t;
diff --git a/gdk/gdk_heap.c b/gdk/gdk_heap.c
--- a/gdk/gdk_heap.c
+++ b/gdk/gdk_heap.c
@@ -562,6 +562,9 @@ HEAPfree(Heap *h, int remove)
" " PTRFMT "\n",
h->size, PTRFMTCAST h->base);
GDKfree(h->base);
+ } else if (h->storage == STORE_CMEM) {
+ //heap is stored in regular C memory rather than GDK
memory,so we call free()
+ free(h->base);
} else { /* mapped file, or STORE_PRIV */
gdk_return ret = GDKmunmap(h->base, h->size);
@@ -576,6 +579,16 @@ HEAPfree(Heap *h, int remove)
h->size, (int) ret);
}
}
+#ifdef HAVE_FORK
+ if (h->storage == STORE_MMAPABS) {
+ // heap is stored in a mmap() file, but h->filename points to
the absolute path
+ if (h->filename && unlink(h->filename) < 0 && errno != ENOENT) {
+ perror(h->filename);
+ }
+ GDKfree(h->filename);
+ h->filename = NULL;
+ }
+#endif
h->base = NULL;
if (h->filename) {
if (remove) {
diff --git a/gdk/shared_memory.c b/gdk/shared_memory.c
new file mode 100644
--- /dev/null
+++ b/gdk/shared_memory.c
@@ -0,0 +1,207 @@
+
+#include "shared_memory.h"
+
+#ifdef HAVE_FORK
+
+#include "gdk.h"
+#include "gdk_private.h"
+#include "../monetdb5/mal/mal_exception.h"
+
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sched.h>
+#include <errno.h>
+#include <sys/sem.h>
+#include <time.h>
+
+static size_t shm_unique_id = 1;
+static key_t base_key = 800000000;
+
+str ftok_enhanced(int id, key_t *return_key);
+str init_process_semaphore(int id, int count, int flags, int *semid);
+
+size_t get_unique_id(size_t offset) {
+ size_t id;
+
+ id = shm_unique_id;
+ shm_unique_id += offset;
+ return id;
+}
+
+str snprintf_mmap_file(str file, size_t max, size_t id) {
+ snprintf(file, max, "pymmap%zu", id);
+ return MAL_SUCCEED;
+}
+
+str init_mmap_memory(size_t base_id, size_t id_offset, size_t maxsize, void
***return_ptr, size_t **return_size, char **single_ptr) {
+ char address[100];
+ void *ptr;
+ int fd;
+ size_t size = maxsize;
+ int mod = MMAP_READ | MMAP_WRITE | MMAP_SEQUENTIAL | MMAP_SYNC |
MAP_SHARED;
+ char *path = NULL;
+ snprintf_mmap_file(address, 100, base_id + id_offset);
+
+ /* round up to multiple of GDK_mmap_pagesize with a
+ * minimum of one
+ size = (maxsize + GDK_mmap_pagesize - 1) & ~(GDK_mmap_pagesize - 1);
+ if (size == 0)
+ size = GDK_mmap_pagesize; */
+ fd = GDKfdlocate(NOFARM, address, "wb", "tmp");
+ if (fd < 0) {
+ return createException(MAL, "shared_memory.get", "Failure in
GDKfdlocate(NOFARM, %s, \"wb\", NULL)", address);
+ }
+ close(fd);
+ path = GDKfilepath(NOFARM, BATDIR, address, "tmp");
+ if (path == NULL) {
+ return createException(MAL, "shared_memory.get", "Failure in
GDKfilepath(NOFARM, "BATDIR",%s,\"tmp\")", address);
+ }
+ if (GDKextend(path, size) != GDK_SUCCEED) {
+ return createException(MAL, "shared_memory.get", "Failure in
GDKextend(%s,%zu)", path, size);
+ }
+ ptr = GDKmmap(path, mod, size);
+ if (ptr == NULL) {
+ return createException(MAL, "shared_memory.get", "Failure in
GDKmmap(%s, %d, %zu)", path, mod, size);
+ }
+ GDKfree(path);
+ if (return_ptr != NULL) (*return_ptr)[id_offset] = ptr;
+ if (return_size != NULL) (*return_size)[id_offset] = size;
+ if (single_ptr != NULL) *single_ptr = ptr;
+ return MAL_SUCCEED;
+}
+
+str release_mmap_memory(void *ptr, size_t size, size_t id) {
+ char address[100];
+ char *path;
+ int ret;
+ snprintf_mmap_file(address, 100, id);
+ if (GDKmunmap(ptr, size) != GDK_SUCCEED) {
+ return createException(MAL, "shared_memory.get", "Failure in
GDKmunmap(%p, %zu)", ptr, size);
+ }
+ path = GDKfilepath(NOFARM, BATDIR, address, "tmp");
+ if (path == NULL) {
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list