summaryrefslogtreecommitdiffstats
path: root/xlators/bindings/python/src/python.c
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/bindings/python/src/python.c')
-rw-r--r--xlators/bindings/python/src/python.c235
1 files changed, 235 insertions, 0 deletions
diff --git a/xlators/bindings/python/src/python.c b/xlators/bindings/python/src/python.c
new file mode 100644
index 00000000000..739ef732900
--- /dev/null
+++ b/xlators/bindings/python/src/python.c
@@ -0,0 +1,235 @@
+/*
+ Copyright (c) 2007 Chris AtLee <chris@atlee.ca>
+ This file is part of GlusterFS.
+
+ GlusterFS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ GlusterFS is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#include <Python.h>
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include "glusterfs.h"
+#include "xlator.h"
+#include "logging.h"
+#include "defaults.h"
+
+typedef struct
+{
+ char *scriptname;
+ PyObject *pXlator;
+ PyObject *pScriptModule;
+ PyObject *pGlusterModule;
+ PyThreadState *pInterp;
+
+ PyObject *pFrameType, *pVectorType, *pFdType;
+} python_private_t;
+
+int32_t
+python_writev (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ struct iovec *vector,
+ int32_t count,
+ off_t offset)
+{
+ python_private_t *priv = (python_private_t *)this->private;
+ gf_log("python", GF_LOG_DEBUG, "In writev");
+ if (PyObject_HasAttrString(priv->pXlator, "writev"))
+ {
+
+ PyObject *retval = PyObject_CallMethod(priv->pXlator, "writev",
+ "O O O i l",
+ PyObject_CallMethod(priv->pFrameType, "from_address", "O&", PyLong_FromVoidPtr, frame),
+ PyObject_CallMethod(priv->pFdType, "from_address", "O&", PyLong_FromVoidPtr, fd),
+ PyObject_CallMethod(priv->pVectorType, "from_address", "O&", PyLong_FromVoidPtr, vector),
+ count,
+ offset);
+ if (PyErr_Occurred())
+ {
+ PyErr_Print();
+ }
+ Py_XDECREF(retval);
+ }
+ else
+ {
+ return default_writev(frame, this, fd, vector, count, offset);
+ }
+ return 0;
+}
+
+struct xlator_fops fops = {
+ .writev = python_writev
+};
+
+struct xlator_mops mops = {
+};
+
+static PyObject *
+AnonModule_FromFile (const char* fname)
+{
+ // Get the builtins
+ PyThreadState* pThread = PyThreadState_Get();
+ PyObject *pBuiltins = pThread->interp->builtins;
+
+ if (PyErr_Occurred())
+ {
+ PyErr_Print();
+ return NULL;
+ }
+
+ // Create a new dictionary for running code in
+ PyObject *pModuleDict = PyDict_New();
+ PyDict_SetItemString(pModuleDict, "__builtins__", pBuiltins);
+ Py_INCREF(pBuiltins);
+
+ // Run the file in the new context
+ FILE* fp = fopen(fname, "r");
+ PyRun_File(fp, fname, Py_file_input, pModuleDict, pModuleDict);
+ fclose(fp);
+ if (PyErr_Occurred())
+ {
+ PyErr_Print();
+ Py_DECREF(pModuleDict);
+ Py_DECREF(pBuiltins);
+ return NULL;
+ }
+
+ // Create an object to hold the new context
+ PyRun_String("class ModuleWrapper(object):\n\tpass\n", Py_single_input, pModuleDict, pModuleDict);
+ if (PyErr_Occurred())
+ {
+ PyErr_Print();
+ Py_DECREF(pModuleDict);
+ Py_DECREF(pBuiltins);
+ return NULL;
+ }
+ PyObject *pModule = PyRun_String("ModuleWrapper()", Py_eval_input, pModuleDict, pModuleDict);
+ if (PyErr_Occurred())
+ {
+ PyErr_Print();
+ Py_DECREF(pModuleDict);
+ Py_DECREF(pBuiltins);
+ Py_XDECREF(pModule);
+ return NULL;
+ }
+
+ // Set the new context's dictionary to the one we used to run the code
+ // inside
+ PyObject_SetAttrString(pModule, "__dict__", pModuleDict);
+ if (PyErr_Occurred())
+ {
+ PyErr_Print();
+ Py_DECREF(pModuleDict);
+ Py_DECREF(pBuiltins);
+ Py_DECREF(pModule);
+ return NULL;
+ }
+
+ return pModule;
+}
+
+int32_t
+init (xlator_t *this)
+{
+ // This is ok to call more than once per process
+ Py_InitializeEx(0);
+
+ if (!this->children) {
+ gf_log ("python", GF_LOG_ERROR,
+ "FATAL: python should have exactly one child");
+ return -1;
+ }
+
+ python_private_t *priv = CALLOC (sizeof (python_private_t), 1);
+ ERR_ABORT (priv);
+
+ data_t *scriptname = dict_get (this->options, "scriptname");
+ if (scriptname) {
+ priv->scriptname = data_to_str(scriptname);
+ } else {
+ gf_log("python", GF_LOG_ERROR,
+ "FATAL: python requires the scriptname parameter");
+ return -1;
+ }
+
+ priv->pInterp = Py_NewInterpreter();
+
+ // Adjust python's path
+ PyObject *syspath = PySys_GetObject("path");
+ PyObject *path = PyString_FromString(GLUSTER_PYTHON_PATH);
+ PyList_Append(syspath, path);
+ Py_DECREF(path);
+
+ gf_log("python", GF_LOG_DEBUG,
+ "Loading gluster module");
+
+ priv->pGlusterModule = PyImport_ImportModule("gluster");
+ if (PyErr_Occurred())
+ {
+ PyErr_Print();
+ return -1;
+ }
+
+ priv->pFrameType = PyObject_GetAttrString(priv->pGlusterModule, "call_frame_t");
+ priv->pFdType = PyObject_GetAttrString(priv->pGlusterModule, "fd_t");
+ priv->pVectorType = PyObject_GetAttrString(priv->pGlusterModule, "iovec");
+
+ gf_log("python", GF_LOG_DEBUG, "Loading script...%s", priv->scriptname);
+
+ priv->pScriptModule = AnonModule_FromFile(priv->scriptname);
+ if (!priv->pScriptModule || PyErr_Occurred())
+ {
+ gf_log("python", GF_LOG_ERROR, "Error loading %s", priv->scriptname);
+ PyErr_Print();
+ return -1;
+ }
+
+ if (!PyObject_HasAttrString(priv->pScriptModule, "xlator"))
+ {
+ gf_log("python", GF_LOG_ERROR, "%s does not have a xlator attribute", priv->scriptname);
+ return -1;
+ }
+ gf_log("python", GF_LOG_DEBUG, "Instantiating translator");
+ priv->pXlator = PyObject_CallMethod(priv->pScriptModule, "xlator", "O&",
+ PyLong_FromVoidPtr, this);
+ if (PyErr_Occurred() || !priv->pXlator)
+ {
+ PyErr_Print();
+ return -1;
+ }
+
+ this->private = priv;
+
+ gf_log ("python", GF_LOG_DEBUG, "python xlator loaded");
+ return 0;
+}
+
+void
+fini (xlator_t *this)
+{
+ python_private_t *priv = (python_private_t*)(this->private);
+ Py_DECREF(priv->pXlator);
+ Py_DECREF(priv->pScriptModule);
+ Py_DECREF(priv->pGlusterModule);
+ Py_DECREF(priv->pFrameType);
+ Py_DECREF(priv->pFdType);
+ Py_DECREF(priv->pVectorType);
+ Py_EndInterpreter(priv->pInterp);
+ return;
+}