summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/tdb/Makefile.in1
-rwxr-xr-xlib/tdb/autogen.sh2
-rw-r--r--lib/tdb/pytdb.c517
-rw-r--r--lib/tdb/python.mk8
-rw-r--r--lib/tdb/python/tests/simple.py38
-rw-r--r--lib/tdb/tdb.i328
-rw-r--r--lib/tdb/tdb.mk16
-rw-r--r--lib/tdb/tdb.py344
-rw-r--r--lib/tevent/Makefile.in81
-rwxr-xr-xlib/tevent/autogen.sh16
-rw-r--r--lib/tevent/build_macros.m414
-rw-r--r--lib/tevent/config.mk59
-rw-r--r--lib/tevent/configure.ac40
-rw-r--r--lib/tevent/events.i54
-rw-r--r--lib/tevent/events.py94
-rw-r--r--lib/tevent/events_wrap.c (renamed from lib/tdb/tdb_wrap.c)1178
-rw-r--r--lib/tevent/libtalloc.m47
-rw-r--r--lib/tevent/libtevent.m451
-rw-r--r--lib/tevent/pkg.m4156
-rw-r--r--lib/tevent/rules.mk21
-rw-r--r--lib/tevent/tests.py31
-rw-r--r--lib/tevent/testsuite.c145
-rw-r--r--lib/tevent/tevent.c310
-rw-r--r--lib/tevent/tevent.h98
-rw-r--r--lib/tevent/tevent.mk59
-rw-r--r--lib/tevent/tevent.pc.in11
-rw-r--r--lib/tevent/tevent_aio.c567
-rw-r--r--lib/tevent/tevent_debug.c83
-rw-r--r--lib/tevent/tevent_epoll.c482
-rw-r--r--lib/tevent/tevent_internal.h158
-rw-r--r--lib/tevent/tevent_liboop.c288
-rw-r--r--lib/tevent/tevent_s4.c108
-rw-r--r--lib/tevent/tevent_select.c302
-rw-r--r--lib/tevent/tevent_signal.c291
-rw-r--r--lib/tevent/tevent_standard.c607
-rw-r--r--lib/tevent/tevent_timed.c230
-rw-r--r--lib/tevent/tevent_util.c86
-rw-r--r--lib/tevent/tevent_util.h117
-rw-r--r--lib/util/debug.h3
-rw-r--r--lib/util/xfile.h2
40 files changed, 5206 insertions, 1797 deletions
diff --git a/lib/tdb/Makefile.in b/lib/tdb/Makefile.in
index 9915d88264..df1b02be6a 100644
--- a/lib/tdb/Makefile.in
+++ b/lib/tdb/Makefile.in
@@ -23,7 +23,6 @@ SHLD_FLAGS = @SHLD_FLAGS@
PACKAGE_VERSION = @PACKAGE_VERSION@
PICFLAG = @PICFLAG@
SHLIBEXT = @SHLIBEXT@
-SWIG = swig
PYTHON = @PYTHON@
PYTHON_CONFIG = @PYTHON_CONFIG@
PYTHON_BUILD_TARGET = @PYTHON_BUILD_TARGET@
diff --git a/lib/tdb/autogen.sh b/lib/tdb/autogen.sh
index 88ac4cfcf7..bf84eeee19 100755
--- a/lib/tdb/autogen.sh
+++ b/lib/tdb/autogen.sh
@@ -9,8 +9,6 @@ autoheader $IPATHS || exit 1
rm -rf autom4te.cache
-swig -O -Wall -python -keyword tdb.i # Ignore errors for now
-
echo "Now run ./configure and then make."
exit 0
diff --git a/lib/tdb/pytdb.c b/lib/tdb/pytdb.c
new file mode 100644
index 0000000000..b7087c4bcc
--- /dev/null
+++ b/lib/tdb/pytdb.c
@@ -0,0 +1,517 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Swig interface to tdb.
+
+ Copyright (C) 2004-2006 Tim Potter <tpot@samba.org>
+ Copyright (C) 2007-2008 Jelmer Vernooij <jelmer@samba.org>
+
+ ** NOTE! The following LGPL license applies to the tdb
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <Python.h>
+#ifdef HAVE_FSTAT
+#undef HAVE_FSTAT
+#endif
+
+/* Include tdb headers */
+#include <stdint.h>
+#include <signal.h>
+#include <tdb.h>
+#include <fcntl.h>
+#include <stdbool.h>
+
+typedef struct {
+ PyObject_HEAD
+ TDB_CONTEXT *ctx;
+ bool closed;
+} PyTdbObject;
+
+PyAPI_DATA(PyTypeObject) PyTdb;
+
+static void PyErr_SetTDBError(TDB_CONTEXT *tdb)
+{
+ PyErr_SetObject(PyExc_RuntimeError,
+ Py_BuildValue("(i,s)", tdb_error(tdb), tdb_errorstr(tdb)));
+}
+
+static TDB_DATA PyString_AsTDB_DATA(PyObject *data)
+{
+ TDB_DATA ret;
+ ret.dptr = (unsigned char *)PyString_AsString(data);
+ ret.dsize = PyString_Size(data);
+ return ret;
+}
+
+static PyObject *PyString_FromTDB_DATA(TDB_DATA data)
+{
+ if (data.dptr == NULL && data.dsize == 0) {
+ return Py_None;
+ } else {
+ PyObject *ret = PyString_FromStringAndSize((const char *)data.dptr,
+ data.dsize);
+ free(data.dptr);
+ return ret;
+ }
+}
+
+#define PyErr_TDB_ERROR_IS_ERR_RAISE(ret, tdb) \
+ if (ret != 0) { \
+ PyErr_SetTDBError(tdb); \
+ return NULL; \
+ }
+
+static PyObject *py_tdb_open(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+ char *name;
+ int hash_size = 0, tdb_flags = TDB_DEFAULT, flags = O_RDWR, mode = 0600;
+ TDB_CONTEXT *ctx;
+ PyTdbObject *ret;
+ const char *kwnames[] = { "name", "hash_size", "tdb_flags", "flags", "mode", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|iiii", (char **)kwnames, &name, &hash_size, &tdb_flags, &flags, &mode))
+ return NULL;
+
+ ctx = tdb_open(name, hash_size, tdb_flags, flags, mode);
+ if (ctx == NULL) {
+ PyErr_SetFromErrno(PyExc_IOError);
+ return NULL;
+ }
+
+ ret = PyObject_New(PyTdbObject, &PyTdb);
+ ret->ctx = ctx;
+ ret->closed = false;
+ return (PyObject *)ret;
+}
+
+static PyObject *obj_transaction_cancel(PyTdbObject *self)
+{
+ int ret = tdb_transaction_cancel(self->ctx);
+ PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx);
+ return Py_None;
+}
+
+static PyObject *obj_transaction_commit(PyTdbObject *self)
+{
+ int ret = tdb_transaction_commit(self->ctx);
+ PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx);
+ return Py_None;
+}
+
+static PyObject *obj_transaction_recover(PyTdbObject *self)
+{
+ int ret = tdb_transaction_recover(self->ctx);
+ PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx);
+ return Py_None;
+}
+
+static PyObject *obj_transaction_start(PyTdbObject *self)
+{
+ int ret = tdb_transaction_start(self->ctx);
+ PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx);
+ return Py_None;
+}
+
+static PyObject *obj_reopen(PyTdbObject *self)
+{
+ int ret = tdb_reopen(self->ctx);
+ PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx);
+ return Py_None;
+}
+
+static PyObject *obj_lockall(PyTdbObject *self)
+{
+ int ret = tdb_lockall(self->ctx);
+ PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx);
+ return Py_None;
+}
+
+static PyObject *obj_unlockall(PyTdbObject *self)
+{
+ int ret = tdb_unlockall(self->ctx);
+ PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx);
+ return Py_None;
+}
+
+static PyObject *obj_lockall_read(PyTdbObject *self)
+{
+ int ret = tdb_lockall_read(self->ctx);
+ PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx);
+ return Py_None;
+}
+
+static PyObject *obj_unlockall_read(PyTdbObject *self)
+{
+ int ret = tdb_unlockall_read(self->ctx);
+ PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx);
+ return Py_None;
+}
+
+static PyObject *obj_close(PyTdbObject *self)
+{
+ int ret;
+ if (self->closed)
+ return Py_None;
+ ret = tdb_close(self->ctx);
+ self->closed = true;
+ PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx);
+ return Py_None;
+}
+
+static PyObject *obj_get(PyTdbObject *self, PyObject *args)
+{
+ TDB_DATA key;
+ PyObject *py_key;
+ if (!PyArg_ParseTuple(args, "O", &py_key))
+ return NULL;
+
+ key = PyString_AsTDB_DATA(py_key);
+
+ return PyString_FromTDB_DATA(tdb_fetch(self->ctx, key));
+}
+
+static PyObject *obj_append(PyTdbObject *self, PyObject *args)
+{
+ TDB_DATA key, data;
+ PyObject *py_key, *py_data;
+ int ret;
+ if (!PyArg_ParseTuple(args, "OO", &py_key, &py_data))
+ return NULL;
+
+ key = PyString_AsTDB_DATA(py_key);
+ data = PyString_AsTDB_DATA(py_data);
+
+ ret = tdb_append(self->ctx, key, data);
+ PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx);
+ return Py_None;
+}
+
+static PyObject *obj_firstkey(PyTdbObject *self)
+{
+ return PyString_FromTDB_DATA(tdb_firstkey(self->ctx));
+}
+
+static PyObject *obj_nextkey(PyTdbObject *self, PyObject *args)
+{
+ TDB_DATA key;
+ PyObject *py_key;
+ if (!PyArg_ParseTuple(args, "O", &py_key))
+ return NULL;
+
+ key = PyString_AsTDB_DATA(py_key);
+
+ return PyString_FromTDB_DATA(tdb_nextkey(self->ctx, key));
+}
+
+static PyObject *obj_delete(PyTdbObject *self, PyObject *args)
+{
+ TDB_DATA key;
+ PyObject *py_key;
+ int ret;
+ if (!PyArg_ParseTuple(args, "O", &py_key))
+ return NULL;
+
+ key = PyString_AsTDB_DATA(py_key);
+ ret = tdb_delete(self->ctx, key);
+ PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx);
+ return Py_None;
+}
+
+static PyObject *obj_has_key(PyTdbObject *self, PyObject *args)
+{
+ TDB_DATA key;
+ int ret;
+ PyObject *py_key;
+ if (!PyArg_ParseTuple(args, "O", &py_key))
+ return NULL;
+
+ key = PyString_AsTDB_DATA(py_key);
+ ret = tdb_exists(self->ctx, key);
+ if (ret != TDB_ERR_NOEXIST) {
+ PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx);
+ }
+
+ return (ret == TDB_ERR_NOEXIST)?Py_False:Py_True;
+}
+
+static PyObject *obj_store(PyTdbObject *self, PyObject *args)
+{
+ TDB_DATA key, value;
+ int ret;
+ int flag = TDB_REPLACE;
+ PyObject *py_key, *py_value;
+
+ if (!PyArg_ParseTuple(args, "OO|i", &py_key, &py_value, &flag))
+ return NULL;
+
+ key = PyString_AsTDB_DATA(py_key);
+ value = PyString_AsTDB_DATA(py_value);
+
+ ret = tdb_store(self->ctx, key, value, flag);
+ PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx);
+ return Py_None;
+}
+
+
+typedef struct {
+ PyObject_HEAD
+ TDB_DATA current;
+ PyTdbObject *iteratee;
+} PyTdbIteratorObject;
+
+static PyObject *tdb_iter_next(PyTdbIteratorObject *self)
+{
+ TDB_DATA current;
+ PyObject *ret;
+ if (self->current.dptr == NULL && self->current.dsize == 0)
+ return NULL;
+ current = self->current;
+ self->current = tdb_nextkey(self->iteratee->ctx, self->current);
+ ret = PyString_FromTDB_DATA(current);
+ return ret;
+}
+
+static void tdb_iter_dealloc(PyTdbIteratorObject *self)
+{
+ Py_DECREF(self->iteratee);
+ PyObject_Del(self);
+}
+
+PyTypeObject PyTdbIterator = {
+ .tp_name = "Iterator",
+ .tp_basicsize = sizeof(PyTdbIteratorObject),
+ .tp_iternext = (iternextfunc)tdb_iter_next,
+ .tp_dealloc = (destructor)tdb_iter_dealloc,
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+ .tp_iter = PyObject_SelfIter,
+};
+
+static PyObject *tdb_object_iter(PyTdbObject *self)
+{
+ PyTdbIteratorObject *ret;
+
+ ret = PyObject_New(PyTdbIteratorObject, &PyTdbIterator);
+ ret->current = tdb_firstkey(self->ctx);
+ ret->iteratee = self;
+ Py_INCREF(self);
+ return (PyObject *)ret;
+}
+
+static PyObject *obj_clear(PyTdbObject *self)
+{
+ int ret = tdb_wipe_all(self->ctx);
+ PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx);
+ return Py_None;
+}
+
+static PyMethodDef tdb_object_methods[] = {
+ { "transaction_cancel", (PyCFunction)obj_transaction_cancel, METH_NOARGS,
+ "S.transaction_cancel() -> None\n"
+ "Cancel the currently active transaction." },
+ { "transaction_commit", (PyCFunction)obj_transaction_commit, METH_NOARGS,
+ "S.transaction_commit() -> None\n"
+ "Commit the currently active transaction." },
+ { "transaction_recover", (PyCFunction)obj_transaction_recover, METH_NOARGS,
+ "S.transaction_recover() -> None\n"
+ "Recover the currently active transaction." },
+ { "transaction_start", (PyCFunction)obj_transaction_start, METH_NOARGS,
+ "S.transaction_start() -> None\n"
+ "Start a new transaction." },
+ { "reopen", (PyCFunction)obj_reopen, METH_NOARGS, "Reopen this file." },
+ { "lock_all", (PyCFunction)obj_lockall, METH_NOARGS, NULL },
+ { "unlock_all", (PyCFunction)obj_unlockall, METH_NOARGS, NULL },
+ { "read_lock_all", (PyCFunction)obj_lockall_read, METH_NOARGS, NULL },
+ { "read_unlock_all", (PyCFunction)obj_unlockall_read, METH_NOARGS, NULL },
+ { "close", (PyCFunction)obj_close, METH_NOARGS, NULL },
+ { "get", (PyCFunction)obj_get, METH_VARARGS, "S.fetch(key) -> value\n"
+ "Fetch a value." },
+ { "append", (PyCFunction)obj_append, METH_VARARGS, "S.append(key, value) -> None\n"
+ "Append data to an existing key." },
+ { "firstkey", (PyCFunction)obj_firstkey, METH_NOARGS, "S.firstkey() -> data\n"
+ "Return the first key in this database." },
+ { "nextkey", (PyCFunction)obj_nextkey, METH_NOARGS, "S.nextkey(key) -> data\n"
+ "Return the next key in this database." },
+ { "delete", (PyCFunction)obj_delete, METH_VARARGS, "S.delete(key) -> None\n"
+ "Delete an entry." },
+ { "has_key", (PyCFunction)obj_has_key, METH_VARARGS, "S.has_key(key) -> None\n"
+ "Check whether key exists in this database." },
+ { "store", (PyCFunction)obj_store, METH_VARARGS, "S.store(key, data, flag=REPLACE) -> None"
+ "Store data." },
+ { "iterkeys", (PyCFunction)tdb_object_iter, METH_NOARGS, "S.iterkeys() -> iterator" },
+ { "clear", (PyCFunction)obj_clear, METH_NOARGS, "S.clear() -> None\n"
+ "Wipe the entire database." },
+ { NULL }
+};
+
+static PyObject *obj_get_hash_size(PyTdbObject *self, void *closure)
+{
+ return PyInt_FromLong(tdb_hash_size(self->ctx));
+}
+
+static int obj_set_max_dead(PyTdbObject *self, PyObject *max_dead, void *closure)
+{
+ if (!PyInt_Check(max_dead))
+ return -1;
+ tdb_set_max_dead(self->ctx, PyInt_AsLong(max_dead));
+ return 0;
+}
+
+static PyObject *obj_get_map_size(PyTdbObject *self, void *closure)
+{
+ return PyInt_FromLong(tdb_map_size(self->ctx));
+}
+
+static PyObject *obj_get_flags(PyTdbObject *self, void *closure)
+{
+ return PyInt_FromLong(tdb_get_flags(self->ctx));
+}
+
+static PyObject *obj_get_filename(PyTdbObject *self, void *closure)
+{
+ return PyString_FromString(tdb_name(self->ctx));
+}
+
+static PyGetSetDef tdb_object_getsetters[] = {
+ { (char *)"hash_size", (getter)obj_get_hash_size, NULL, NULL },
+ { (char *)"map_size", (getter)obj_get_map_size, NULL, NULL },
+ { (char *)"flags", (getter)obj_get_flags, NULL, NULL },
+ { (char *)"max_dead", NULL, (setter)obj_set_max_dead, NULL },
+ { (char *)"filename", (getter)obj_get_filename, NULL, (char *)"The filename of this TDB file."},
+ { NULL }
+};
+
+static PyObject *tdb_object_repr(PyTdbObject *self)
+{
+ return PyString_FromFormat("Tdb('%s')", tdb_name(self->ctx));
+}
+
+static void tdb_object_dealloc(PyTdbObject *self)
+{
+ if (!self->closed)
+ tdb_close(self->ctx);
+ PyObject_Del(self);
+}
+
+static PyObject *obj_getitem(PyTdbObject *self, PyObject *key)
+{
+ TDB_DATA tkey, val;
+ if (!PyString_Check(key)) {
+ PyErr_SetString(PyExc_TypeError, "Expected string as key");
+ return NULL;
+ }
+
+ tkey.dptr = (unsigned char *)PyString_AsString(key);
+ tkey.dsize = PyString_Size(key);
+
+ val = tdb_fetch(self->ctx, tkey);
+ if (val.dptr == NULL) {
+ PyErr_SetString(PyExc_KeyError, "No such TDB entry");
+ return NULL;
+ } else {
+ return PyString_FromTDB_DATA(val);
+ }
+}
+
+static int obj_setitem(PyTdbObject *self, PyObject *key, PyObject *value)
+{
+ TDB_DATA tkey, tval;
+ int ret;
+ if (!PyString_Check(key)) {
+ PyErr_SetString(PyExc_TypeError, "Expected string as key");
+ return -1;
+ }
+
+ tkey = PyString_AsTDB_DATA(key);
+
+ if (value == NULL) {
+ ret = tdb_delete(self->ctx, tkey);
+ } else {
+ if (!PyString_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "Expected string as value");
+ return -1;
+ }
+
+ tval = PyString_AsTDB_DATA(value);
+
+ ret = tdb_store(self->ctx, tkey, tval, TDB_REPLACE);
+ }
+
+ if (ret != 0) {
+ PyErr_SetTDBError(self->ctx);
+ return -1;
+ }
+
+ return ret;
+}
+
+static PyMappingMethods tdb_object_mapping = {
+ .mp_subscript = (binaryfunc)obj_getitem,
+ .mp_ass_subscript = (objobjargproc)obj_setitem,
+};
+PyTypeObject PyTdb = {
+ .tp_name = "Tdb",
+ .tp_basicsize = sizeof(PyTdbObject),
+ .tp_methods = tdb_object_methods,
+ .tp_getset = tdb_object_getsetters,
+ .tp_new = py_tdb_open,
+ .tp_doc = "A TDB file",
+ .tp_repr = (reprfunc)tdb_object_repr,
+ .tp_dealloc = (destructor)tdb_object_dealloc,
+ .tp_as_mapping = &tdb_object_mapping,
+ .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_ITER,
+ .tp_iter = (getiterfunc)tdb_object_iter,
+};
+
+static PyMethodDef tdb_methods[] = {
+ { "open", (PyCFunction)py_tdb_open, METH_VARARGS|METH_KEYWORDS, "open(name, hash_size=0, tdb_flags=TDB_DEFAULT, flags=O_RDWR, mode=0600)\n"
+ "Open a TDB file." },
+ { NULL }
+};
+
+void inittdb(void)
+{
+ PyObject *m;
+
+ if (PyType_Ready(&PyTdb) < 0)
+ return;
+
+ if (PyType_Ready(&PyTdbIterator) < 0)
+ return;
+
+ m = Py_InitModule3("tdb", tdb_methods, "TDB is a simple key-value database similar to GDBM that supports multiple writers.");
+ if (m == NULL)
+ return;
+
+ PyModule_AddObject(m, "REPLACE", PyInt_FromLong(TDB_REPLACE));
+ PyModule_AddObject(m, "INSERT", PyInt_FromLong(TDB_INSERT));
+ PyModule_AddObject(m, "MODIFY", PyInt_FromLong(TDB_MODIFY));
+
+ PyModule_AddObject(m, "DEFAULT", PyInt_FromLong(TDB_DEFAULT));
+ PyModule_AddObject(m, "CLEAR_IF_FIRST", PyInt_FromLong(TDB_CLEAR_IF_FIRST));
+ PyModule_AddObject(m, "INTERNAL", PyInt_FromLong(TDB_INTERNAL));
+ PyModule_AddObject(m, "NOLOCK", PyInt_FromLong(TDB_NOLOCK));
+ PyModule_AddObject(m, "NOMMAP", PyInt_FromLong(TDB_NOMMAP));
+ PyModule_AddObject(m, "CONVERT", PyInt_FromLong(TDB_CONVERT));
+ PyModule_AddObject(m, "BIGENDIAN", PyInt_FromLong(TDB_BIGENDIAN));
+ PyModule_AddObject(m, "__docformat__", PyString_FromString("restructuredText"));
+
+ Py_INCREF(&PyTdb);
+ PyModule_AddObject(m, "Tdb", (PyObject *)&PyTdb);
+
+ Py_INCREF(&PyTdbIterator);
+}
diff --git a/lib/tdb/python.mk b/lib/tdb/python.mk
index 12e8217df9..a4e6037993 100644
--- a/lib/tdb/python.mk
+++ b/lib/tdb/python.mk
@@ -1,10 +1,8 @@
[PYTHON::swig_tdb]
-LIBRARY_REALNAME = _tdb.$(SHLIBEXT)
+LIBRARY_REALNAME = tdb.$(SHLIBEXT)
PUBLIC_DEPENDENCIES = LIBTDB DYNCONFIG
-swig_tdb_OBJ_FILES = $(tdbsrcdir)/tdb_wrap.o
+swig_tdb_OBJ_FILES = $(tdbsrcdir)/pytdb.o
-$(eval $(call python_py_module_template,tdb.py,$(tdbsrcdir)/tdb.py))
-
-$(swig_tdb_OBJ_FILES): CFLAGS+=$(CFLAG_NO_UNUSED_MACROS) $(CFLAG_NO_CAST_QUAL)
+$(swig_tdb_OBJ_FILES): CFLAGS+=$(CFLAG_NO_CAST_QUAL)
diff --git a/lib/tdb/python/tests/simple.py b/lib/tdb/python/tests/simple.py
index 7147718c91..d242e665be 100644
--- a/lib/tdb/python/tests/simple.py
+++ b/lib/tdb/python/tests/simple.py
@@ -73,25 +73,13 @@ class SimpleTdbTests(TestCase):
self.tdb.map_size
def test_name(self):
- self.tdb.name
+ self.tdb.filename
def test_iterator(self):
self.tdb["bla"] = "1"
self.tdb["brainslug"] = "2"
self.assertEquals(["bla", "brainslug"], list(self.tdb))
- def test_items(self):
- self.tdb["bla"] = "1"
- self.tdb["brainslug"] = "2"
- self.assertEquals([("bla", "1"), ("brainslug", "2")], self.tdb.items())
-
- def test_iteritems(self):
- self.tdb["bloe"] = "2"
- self.tdb["bla"] = "25"
- i = self.tdb.iteritems()
- self.assertEquals(set([("bla", "25"), ("bloe", "2")]),
- set([i.next(), i.next()]))
-
def test_transaction_cancel(self):
self.tdb["bloe"] = "2"
self.tdb.transaction_start()
@@ -112,39 +100,23 @@ class SimpleTdbTests(TestCase):
i = iter(self.tdb)
self.assertEquals(set(["bloe", "bla"]), set([i.next(), i.next()]))
- def test_keys(self):
- self.tdb["bloe"] = "2"
- self.tdb["bla"] = "25"
- self.assertEquals(["bla", "bloe"], self.tdb.keys())
-
def test_iterkeys(self):
self.tdb["bloe"] = "2"
self.tdb["bla"] = "25"
i = self.tdb.iterkeys()
self.assertEquals(set(["bloe", "bla"]), set([i.next(), i.next()]))
- def test_values(self):
- self.tdb["bloe"] = "2"
- self.tdb["bla"] = "25"
- self.assertEquals(["25", "2"], self.tdb.values())
-
- def test_itervalues(self):
- self.tdb["bloe"] = "2"
- self.tdb["bla"] = "25"
- i = self.tdb.itervalues()
- self.assertEquals(set(["25", "2"]), set([i.next(), i.next()]))
-
def test_clear(self):
self.tdb["bloe"] = "2"
self.tdb["bla"] = "25"
- self.assertEquals(2, len(self.tdb))
+ self.assertEquals(2, len(list(self.tdb)))
self.tdb.clear()
- self.assertEquals(0, len(self.tdb))
+ self.assertEquals(0, len(list(self.tdb)))
def test_len(self):
- self.assertEquals(0, len(self.tdb))
+ self.assertEquals(0, len(list(self.tdb)))
self.tdb["entry"] = "value"
- self.assertEquals(1, len(self.tdb))
+ self.assertEquals(1, len(list(self.tdb)))
if __name__ == '__main__':
diff --git a/lib/tdb/tdb.i b/lib/tdb/tdb.i
deleted file mode 100644
index 4b529913d7..0000000000
--- a/lib/tdb/tdb.i
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
-
- Swig interface to tdb.
-
- Copyright (C) 2004-2006 Tim Potter <tpot@samba.org>
- Copyright (C) 2007 Jelmer Vernooij <jelmer@samba.org>
-
- ** NOTE! The following LGPL license applies to the tdb
- ** library. This does NOT imply that all of Samba is released
- ** under the LGPL
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
-
- This library 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
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-%define DOCSTRING
-"TDB is a simple key-value database similar to GDBM that supports multiple writers."
-%enddef
-
-%module(docstring=DOCSTRING) tdb
-
-%{
-
-/* This symbol is used in both includes.h and Python.h which causes an
- annoying compiler warning. */
-
-#ifdef HAVE_FSTAT
-#undef HAVE_FSTAT
-#endif
-
-/* Include tdb headers */
-#include <stdint.h>
-#include <signal.h>
-#include <tdb.h>
-#include <fcntl.h>
-
-typedef TDB_CONTEXT tdb;
-%}
-
-/* The tdb functions will crash if a NULL tdb context is passed */
-
-%import exception.i
-%import stdint.i
-
-%typemap(check,noblock=1) TDB_CONTEXT* {
- if ($1 == NULL)
- SWIG_exception(SWIG_ValueError,
- "tdb context must be non-NULL");
-}
-
-/* In and out typemaps for the TDB_DATA structure. This is converted to
- and from the Python string type which can contain arbitrary binary
- data.. */
-
-%typemap(in,noblock=1) TDB_DATA {
- if ($input == Py_None) {
- $1.dsize = 0;
- $1.dptr = NULL;
- } else if (!PyString_Check($input)) {
- PyErr_SetString(PyExc_TypeError, "string arg expected");
- return NULL;
- } else {
- $1.dsize = PyString_Size($input);
- $1.dptr = (uint8_t *)PyString_AsString($input);
- }
-}
-
-%typemap(out,noblock=1) TDB_DATA {
- if ($1.dptr == NULL && $1.dsize == 0) {
- $result = Py_None;
- } else {
- $result = PyString_FromStringAndSize((const char *)$1.dptr, $1.dsize);
- free($1.dptr);
- }
-}
-
-/* Treat a mode_t as an unsigned integer */
-typedef int mode_t;
-
-/* flags to tdb_store() */
-%constant int REPLACE = TDB_REPLACE;
-%constant int INSERT = TDB_INSERT;
-%constant int MODIFY = TDB_MODIFY;
-
-/* flags for tdb_open() */
-%constant int DEFAULT = TDB_DEFAULT;
-%constant int CLEAR_IF_FIRST = TDB_CLEAR_IF_FIRST;
-%constant int INTERNAL = TDB_INTERNAL;
-%constant int NOLOCK = TDB_NOLOCK;
-%constant int NOMMAP = TDB_NOMMAP;
-%constant int CONVERT = TDB_CONVERT;
-%constant int BIGENDIAN = TDB_BIGENDIAN;
-
-enum TDB_ERROR {
- TDB_SUCCESS=0,
- TDB_ERR_CORRUPT,
- TDB_ERR_IO,
- TDB_ERR_LOCK,
- TDB_ERR_OOM,
- TDB_ERR_EXISTS,
- TDB_ERR_NOLOCK,
- TDB_ERR_LOCK_TIMEOUT,
- TDB_ERR_NOEXIST,
- TDB_ERR_EINVAL,
- TDB_ERR_RDONLY
-};
-
-%rename(lock_all) tdb_context::lockall;
-%rename(unlock_all) tdb_context::unlockall;
-
-%rename(read_lock_all) tdb_context::lockall_read;
-%rename(read_unlock_all) tdb_context::unlockall_read;
-
-%typemap(default,noblock=1) int tdb_flags {
- $1 = TDB_DEFAULT;
-}
-
-%typemap(default,noblock=1) int flags {
- $1 = O_RDWR;
-}
-
-%typemap(default,noblock=1) int hash_size {
- $1 = 0;
-}
-
-%typemap(default,noblock=1) mode_t mode {
- $1 = 0600;
-}
-
-%typemap(default,noblock=1) int flag {
- $1 = TDB_REPLACE;
-}
-
-%rename(Tdb) tdb_context;
-%feature("docstring") tdb_context "A TDB file.";
-%typemap(out,noblock=1) tdb * {
- /* Throw an IOError exception from errno if tdb_open() returns NULL */
- if ($1 == NULL) {
- PyErr_SetFromErrno(PyExc_IOError);
- SWIG_fail;
- }
- $result = SWIG_NewPointerObj($1, $1_descriptor, 0);
-}
-
-typedef struct tdb_context {
- %extend {
- %feature("docstring") tdb "S.__init__(name,hash_size=0,tdb_flags=TDB_DEFAULT,flags=O_RDWR,mode=0600)\n"
- "Open a TDB file.";
- tdb(const char *name, int hash_size, int tdb_flags, int flags, mode_t mode) {
- return tdb_open(name, hash_size, tdb_flags, flags, mode);
- }
- %feature("docstring") error "S.error() -> int\n"
- "Find last error number returned by operation on this TDB.";
- enum TDB_ERROR error();
- ~tdb() { tdb_close($self); }
- %feature("docstring") close "S.close() -> None\n"
- "Close the TDB file.";
- int close();
- int append(TDB_DATA key, TDB_DATA new_dbuf);
- %feature("docstring") errorstr "S.errorstr() -> errorstring\n"
- "Obtain last error message.";
- const char *errorstr();
- %rename(get) fetch;
- %feature("docstring") fetch "S.fetch(key) -> value\n"
- "Fetch a value.";
- TDB_DATA fetch(TDB_DATA key);
- %feature("docstring") delete "S.delete(key) -> None\n"
- "Delete an entry.";
- int delete(TDB_DATA key);
- %feature("docstring") store "S.store(key, value, flag=TDB_REPLACE) -> None\n"
- "Store an entry.";
- int store(TDB_DATA key, TDB_DATA dbuf, int flag);
- %feature("docstring") exists "S.exists(key) -> bool\n"
- "Check whether key exists in this database.";
- int exists(TDB_DATA key);
- %feature("docstring") firstkey "S.firstkey() -> data\n"
- "Return the first key in this database.";
- TDB_DATA firstkey();
- %feature("docstring") nextkey "S.nextkey(prev) -> data\n"
- "Return the next key in this database.";
- TDB_DATA nextkey(TDB_DATA key);
- %feature("docstring") lockall "S.lockall() -> bool";
- int lockall();
- %feature("docstring") unlockall "S.unlockall() -> bool";
- int unlockall();
- %feature("docstring") unlockall "S.lockall_read() -> bool";
- int lockall_read();
- %feature("docstring") unlockall "S.unlockall_read() -> bool";
- int unlockall_read();
- %feature("docstring") reopen "S.reopen() -> bool\n"
- "Reopen this file.";
- int reopen();
- %feature("docstring") transaction_start "S.transaction_start() -> None\n"
- "Start a new transaction.";
- int transaction_start();
- %feature("docstring") transaction_commit "S.transaction_commit() -> None\n"
- "Commit the currently active transaction.";
- int transaction_commit();
- %feature("docstring") transaction_cancel "S.transaction_cancel() -> None\n"
- "Cancel the currently active transaction.";
- int transaction_cancel();
- int transaction_recover();
- %feature("docstring") hash_size "S.hash_size() -> int";
- int hash_size();
- %feature("docstring") map_size "S.map_size() -> int";
- size_t map_size();
- %feature("docstring") get_flags "S.get_flags() -> int";
- int get_flags();
- %feature("docstring") set_max_dead "S.set_max_dead(int) -> None";
- void set_max_dead(int max_dead);
- %feature("docstring") name "S.name() -> path\n" \
- "Return filename of this TDB file.";
- const char *name();
- }
-
- %pythoncode {
- def __repr__(self):
- return "Tdb('%s')" % self.name()
-
- # Random access to keys, values
- def __getitem__(self, key):
- result = self.get(key)
- if result is None:
- raise KeyError, '%s: %s' % (key, self.errorstr())
- return result
-
- def __setitem__(self, key, item):
- if self.store(key, item) == -1:
- raise IOError, self.errorstr()
-
- def __delitem__(self, key):
- if not self.exists(key):
- raise KeyError, '%s: %s' % (key, self.errorstr())
- self.delete(key)
-
- def __contains__(self, key):
- return self.exists(key) != 0
-
- def has_key(self, key):
- return self.exists(key) != 0
-
- def fetch_uint32(self, key):
- data = self.get(key)
- if data is None:
- return None
- import struct
- return struct.unpack("<L", data)[0]
-
- def fetch_int32(self, key):
- data = self.get(key)
- if data is None:
- return None
- import struct
- return struct.unpack("<l", data)[0]
-
- # Tdb iterator
- class TdbIterator:
- def __init__(self, tdb):
- self.tdb = tdb
- self.key = None
-
- def __iter__(self):
- return self
-
- def next(self):
- if self.key is None:
- self.key = self.tdb.firstkey()
- if self.key is None:
- raise StopIteration
- return self.key
- else:
- self.key = self.tdb.nextkey(self.key)
- if self.key is None:
- raise StopIteration
- return self.key
-
- def __iter__(self):
- return self.TdbIterator(self)
-
- # Implement other dict functions using TdbIterator
-
- def keys(self):
- return [k for k in iter(self)]
-
- def values(self):
- return [self[k] for k in iter(self)]
-
- def items(self):
- return [(k, self[k]) for k in iter(self)]
-
- def __len__(self):
- return len(self.keys())
-
- def clear(self):
- for k in iter(self):
- del(self[k])
-
- def iterkeys(self):
- for k in iter(self):
- yield k
-
- def itervalues(self):
- for k in iter(self):
- yield self[k]
-
- def iteritems(self):
- for k in iter(self):
- yield (k, self[k])
-
- # TODO: any other missing methods for container types
- }
-} tdb;
-
-%pythoncode {
-__docformat__ = 'restructuredText'
-open = Tdb
-}
diff --git a/lib/tdb/tdb.mk b/lib/tdb/tdb.mk
index fa8db6d34c..0254575039 100644
--- a/lib/tdb/tdb.mk
+++ b/lib/tdb/tdb.mk
@@ -33,32 +33,26 @@ clean::
rm -f $(TDB_SONAME) $(TDB_SOLIB) libtdb.a libtdb.$(SHLIBEXT)
rm -f $(ALL_PROGS) tdb.pc
-build-python:: _tdb.$(SHLIBEXT)
+build-python:: tdb.$(SHLIBEXT)
tdb_wrap.o: $(tdbdir)/tdb_wrap.c
$(CC) $(PICFLAG) -c $(tdbdir)/tdb_wrap.c $(CFLAGS) `$(PYTHON_CONFIG) --cflags`
-_tdb.$(SHLIBEXT): libtdb.$(SHLIBEXT) tdb_wrap.o
+tdb.$(SHLIBEXT): libtdb.$(SHLIBEXT) tdb_wrap.o
$(SHLD) $(SHLD_FLAGS) -o $@ tdb_wrap.o -L. -ltdb `$(PYTHON_CONFIG) --ldflags`
install:: installdirs installbin installheaders installlibs \
$(PYTHON_INSTALL_TARGET)
install-python:: build-python
- mkdir -p $(DESTDIR)`$(PYTHON) -c "import distutils.sysconfig; print distutils.sysconfig.get_python_lib(0, prefix='$(prefix)')"` \
- $(DESTDIR)`$(PYTHON) -c "import distutils.sysconfig; print distutils.sysconfig.get_python_lib(1, prefix='$(prefix)')"`
- cp $(tdbdir)/tdb.py $(DESTDIR)`$(PYTHON) -c "import distutils.sysconfig; print distutils.sysconfig.get_python_lib(0, prefix='$(prefix)')"`
- cp _tdb.$(SHLIBEXT) $(DESTDIR)`$(PYTHON) -c "import distutils.sysconfig; print distutils.sysconfig.get_python_lib(1, prefix='$(prefix)')"`
+ mkdir -p $(DESTDIR)`$(PYTHON) -c "import distutils.sysconfig; print distutils.sysconfig.get_python_lib(1, prefix='$(prefix)')"`
+ cp tdb.$(SHLIBEXT) $(DESTDIR)`$(PYTHON) -c "import distutils.sysconfig; print distutils.sysconfig.get_python_lib(1, prefix='$(prefix)')"`
check-python:: build-python $(TDB_SONAME)
$(LIB_PATH_VAR)=. PYTHONPATH=".:$(tdbdir)" $(PYTHON) $(tdbdir)/python/tests/simple.py
-install-swig::
- mkdir -p $(DESTDIR)`$(SWIG) -swiglib`
- cp tdb.i $(DESTDIR)`$(SWIG) -swiglib`
-
clean::
- rm -f _tdb.$(SHLIBEXT)
+ rm -f tdb.$(SHLIBEXT)
installdirs::
mkdir -p $(DESTDIR)$(bindir)
diff --git a/lib/tdb/tdb.py b/lib/tdb/tdb.py
deleted file mode 100644
index 42129d2091..0000000000
--- a/lib/tdb/tdb.py
+++ /dev/null
@@ -1,344 +0,0 @@
-# This file was automatically generated by SWIG (http://www.swig.org).
-# Version 1.3.36
-#
-# Don't modify this file, modify the SWIG interface instead.
-
-"""
-TDB is a simple key-value database similar to GDBM that supports multiple writers.
-"""
-
-import _tdb
-import new
-new_instancemethod = new.instancemethod
-try:
- _swig_property = property
-except NameError:
- pass # Python < 2.2 doesn't have 'property'.
-def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
- if (name == "thisown"): return self.this.own(value)
- if (name == "this"):
- if type(value).__name__ == 'PySwigObject':
- self.__dict__[name] = value
- return
- method = class_type.__swig_setmethods__.get(name,None)
- if method: return method(self,value)
- if (not static) or hasattr(self,name):
- self.__dict__[name] = value
- else:
- raise AttributeError("You cannot add attributes to %s" % self)
-
-def _swig_setattr(self,class_type,name,value):
- return _swig_setattr_nondynamic(self,class_type,name,value,0)
-
-def _swig_getattr(self,class_type,name):
- if (name == "thisown"): return self.this.own()
- method = class_type.__swig_getmethods__.get(name,None)
- if method: return method(self)
- raise AttributeError,name
-
-def _swig_repr(self):
- try: strthis = "proxy of " + self.this.__repr__()
- except: strthis = ""
- return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
-
-import types
-try:
- _object = types.ObjectType
- _newclass = 1
-except AttributeError:
- class _object : pass
- _newclass = 0
-del types
-
-
-def _swig_setattr_nondynamic_method(set):
- def set_attr(self,name,value):
- if (name == "thisown"): return self.this.own(value)
- if hasattr(self,name) or (name == "this"):
- set(self,name,value)
- else:
- raise AttributeError("You cannot add attributes to %s" % self)
- return set_attr
-
-
-REPLACE = _tdb.REPLACE
-INSERT = _tdb.INSERT
-MODIFY = _tdb.MODIFY
-DEFAULT = _tdb.DEFAULT
-CLEAR_IF_FIRST = _tdb.CLEAR_IF_FIRST
-INTERNAL = _tdb.INTERNAL
-NOLOCK = _tdb.NOLOCK
-NOMMAP = _tdb.NOMMAP
-CONVERT = _tdb.CONVERT
-BIGENDIAN = _tdb.BIGENDIAN
-TDB_SUCCESS = _tdb.TDB_SUCCESS
-TDB_ERR_CORRUPT = _tdb.TDB_ERR_CORRUPT
-TDB_ERR_IO = _tdb.TDB_ERR_IO
-TDB_ERR_LOCK = _tdb.TDB_ERR_LOCK
-TDB_ERR_OOM = _tdb.TDB_ERR_OOM
-TDB_ERR_EXISTS = _tdb.TDB_ERR_EXISTS
-TDB_ERR_NOLOCK = _tdb.TDB_ERR_NOLOCK
-TDB_ERR_LOCK_TIMEOUT = _tdb.TDB_ERR_LOCK_TIMEOUT
-TDB_ERR_NOEXIST = _tdb.TDB_ERR_NOEXIST
-TDB_ERR_EINVAL = _tdb.TDB_ERR_EINVAL
-TDB_ERR_RDONLY = _tdb.TDB_ERR_RDONLY
-class Tdb(object):
- """A TDB file."""
- thisown = _swig_property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
- __repr__ = _swig_repr
- def __init__(self, *args, **kwargs):
- """
- S.__init__(name,hash_size=0,tdb_flags=TDB_DEFAULT,flags=O_RDWR,mode=0600)
- Open a TDB file.
- """
- _tdb.Tdb_swiginit(self,_tdb.new_Tdb(*args, **kwargs))
- def error(*args, **kwargs):
- """
- S.error() -> int
- Find last error number returned by operation on this TDB.
- """
- return _tdb.Tdb_error(*args, **kwargs)
-
- __swig_destroy__ = _tdb.delete_Tdb
- def close(*args, **kwargs):
- """
- S.close() -> None
- Close the TDB file.
- """
- return _tdb.Tdb_close(*args, **kwargs)
-
- def errorstr(*args, **kwargs):
- """
- S.errorstr() -> errorstring
- Obtain last error message.
- """
- return _tdb.Tdb_errorstr(*args, **kwargs)
-
- def get(*args, **kwargs):
- """
- S.fetch(key) -> value
- Fetch a value.
- """
- return _tdb.Tdb_get(*args, **kwargs)
-
- def delete(*args, **kwargs):
- """
- S.delete(key) -> None
- Delete an entry.
- """
- return _tdb.Tdb_delete(*args, **kwargs)
-
- def store(*args, **kwargs):
- """
- S.store(key, value, flag=TDB_REPLACE) -> None
- Store an entry.
- """
- return _tdb.Tdb_store(*args, **kwargs)
-
- def exists(*args, **kwargs):
- """
- S.exists(key) -> bool
- Check whether key exists in this database.
- """
- return _tdb.Tdb_exists(*args, **kwargs)
-
- def firstkey(*args, **kwargs):
- """
- S.firstkey() -> data
- Return the first key in this database.
- """
- return _tdb.Tdb_firstkey(*args, **kwargs)
-
- def nextkey(*args, **kwargs):
- """
- S.nextkey(prev) -> data
- Return the next key in this database.
- """
- return _tdb.Tdb_nextkey(*args, **kwargs)
-
- def lock_all(*args, **kwargs):
- """S.lockall() -> bool"""
- return _tdb.Tdb_lock_all(*args, **kwargs)
-
- def unlock_all(*args, **kwargs):
- """S.unlockall() -> bool"""
- return _tdb.Tdb_unlock_all(*args, **kwargs)
-
- def reopen(*args, **kwargs):
- """
- S.reopen() -> bool
- Reopen this file.
- """
- return _tdb.Tdb_reopen(*args, **kwargs)
-
- def transaction_start(*args, **kwargs):
- """
- S.transaction_start() -> None
- Start a new transaction.
- """
- return _tdb.Tdb_transaction_start(*args, **kwargs)
-
- def transaction_commit(*args, **kwargs):
- """
- S.transaction_commit() -> None
- Commit the currently active transaction.
- """
- return _tdb.Tdb_transaction_commit(*args, **kwargs)
-
- def transaction_cancel(*args, **kwargs):
- """
- S.transaction_cancel() -> None
- Cancel the currently active transaction.
- """
- return _tdb.Tdb_transaction_cancel(*args, **kwargs)
-
- def hash_size(*args, **kwargs):
- """S.hash_size() -> int"""
- return _tdb.Tdb_hash_size(*args, **kwargs)
-
- def map_size(*args, **kwargs):
- """S.map_size() -> int"""
- return _tdb.Tdb_map_size(*args, **kwargs)
-
- def get_flags(*args, **kwargs):
- """S.get_flags() -> int"""
- return _tdb.Tdb_get_flags(*args, **kwargs)
-
- def set_max_dead(*args, **kwargs):
- """S.set_max_dead(int) -> None"""
- return _tdb.Tdb_set_max_dead(*args, **kwargs)
-
- def name(*args, **kwargs):
- """
- S.name() -> path
- Return filename of this TDB file.
- """
- return _tdb.Tdb_name(*args, **kwargs)
-
- def __repr__(self):
- return "Tdb('%s')" % self.name()
-
-
- def __getitem__(self, key):
- result = self.get(key)
- if result is None:
- raise KeyError, '%s: %s' % (key, self.errorstr())
- return result
-
- def __setitem__(self, key, item):
- if self.store(key, item) == -1:
- raise IOError, self.errorstr()
-
- def __delitem__(self, key):
- if not self.exists(key):
- raise KeyError, '%s: %s' % (key, self.errorstr())
- self.delete(key)
-
- def __contains__(self, key):
- return self.exists(key) != 0
-
- def has_key(self, key):
- return self.exists(key) != 0
-
- def fetch_uint32(self, key):
- data = self.get(key)
- if data is None:
- return None
- import struct
- return struct.unpack("<L", data)[0]
-
- def fetch_int32(self, key):
- data = self.get(key)
- if data is None:
- return None
- import struct
- return struct.unpack("<l", data)[0]
-
-
- class TdbIterator:
- def __init__(self, tdb):
- self.tdb = tdb
- self.key = None
-
- def __iter__(self):
- return self
-
- def next(self):
- if self.key is None:
- self.key = self.tdb.firstkey()
- if self.key is None:
- raise StopIteration
- return self.key
- else:
- self.key = self.tdb.nextkey(self.key)
- if self.key is None:
- raise StopIteration
- return self.key
-
- def __iter__(self):
- return self.TdbIterator(self)
-
-
-
- def keys(self):
- return [k for k in iter(self)]
-
- def values(self):
- return [self[k] for k in iter(self)]
-
- def items(self):
- return [(k, self[k]) for k in iter(self)]
-
- def __len__(self):
- return len(self.keys())
-
- def clear(self):
- for k in iter(self):
- del(self[k])
-
- def iterkeys(self):
- for k in iter(self):
- yield k
-
- def itervalues(self):
- for k in iter(self):
- yield self[k]
-
- def iteritems(self):
- for k in iter(self):
- yield (k, self[k])
-
-
-
-Tdb.error = new_instancemethod(_tdb.Tdb_error,None,Tdb)
-Tdb.close = new_instancemethod(_tdb.Tdb_close,None,Tdb)
-Tdb.append = new_instancemethod(_tdb.Tdb_append,None,Tdb)
-Tdb.errorstr = new_instancemethod(_tdb.Tdb_errorstr,None,Tdb)
-Tdb.get = new_instancemethod(_tdb.Tdb_get,None,Tdb)
-Tdb.delete = new_instancemethod(_tdb.Tdb_delete,None,Tdb)
-Tdb.store = new_instancemethod(_tdb.Tdb_store,None,Tdb)
-Tdb.exists = new_instancemethod(_tdb.Tdb_exists,None,Tdb)
-Tdb.firstkey = new_instancemethod(_tdb.Tdb_firstkey,None,Tdb)
-Tdb.nextkey = new_instancemethod(_tdb.Tdb_nextkey,None,Tdb)
-Tdb.lock_all = new_instancemethod(_tdb.Tdb_lock_all,None,Tdb)
-Tdb.unlock_all = new_instancemethod(_tdb.Tdb_unlock_all,None,Tdb)
-Tdb.read_lock_all = new_instancemethod(_tdb.Tdb_read_lock_all,None,Tdb)
-Tdb.read_unlock_all = new_instancemethod(_tdb.Tdb_read_unlock_all,None,Tdb)
-Tdb.reopen = new_instancemethod(_tdb.Tdb_reopen,None,Tdb)
-Tdb.transaction_start = new_instancemethod(_tdb.Tdb_transaction_start,None,Tdb)
-Tdb.transaction_commit = new_instancemethod(_tdb.Tdb_transaction_commit,None,Tdb)
-Tdb.transaction_cancel = new_instancemethod(_tdb.Tdb_transaction_cancel,None,Tdb)
-Tdb.transaction_recover = new_instancemethod(_tdb.Tdb_transaction_recover,None,Tdb)
-Tdb.hash_size = new_instancemethod(_tdb.Tdb_hash_size,None,Tdb)
-Tdb.map_size = new_instancemethod(_tdb.Tdb_map_size,None,Tdb)
-Tdb.get_flags = new_instancemethod(_tdb.Tdb_get_flags,None,Tdb)
-Tdb.set_max_dead = new_instancemethod(_tdb.Tdb_set_max_dead,None,Tdb)
-Tdb.name = new_instancemethod(_tdb.Tdb_name,None,Tdb)
-Tdb_swigregister = _tdb.Tdb_swigregister
-Tdb_swigregister(Tdb)
-
-__docformat__ = 'restructuredText'
-open = Tdb
-
-
-
diff --git a/lib/tevent/Makefile.in b/lib/tevent/Makefile.in
new file mode 100644
index 0000000000..9765d35720
--- /dev/null
+++ b/lib/tevent/Makefile.in
@@ -0,0 +1,81 @@
+#!gmake
+#
+# Makefile for tdb directory
+#
+
+CC = @CC@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+includedir = @includedir@
+libdir = @libdir@
+VPATH = @srcdir@:@libreplacedir@
+srcdir = @srcdir@
+builddir = @builddir@
+sharedbuilddir = @sharedbuilddir@
+INSTALLCMD = @INSTALL@
+CPPFLAGS = @CPPFLAGS@ -I$(srcdir)/include -Iinclude -I.
+LDFLAGS = @LDFLAGS@
+EXEEXT = @EXEEXT@
+SHLD = @SHLD@
+SHLD_FLAGS = @SHLD_FLAGS@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PICFLAG = @PICFLAG@
+SHLIBEXT = @SHLIBEXT@
+SWIG = swig
+PYTHON = @PYTHON@
+PYTHON_CONFIG = @PYTHON_CONFIG@
+PYTHON_BUILD_TARGET = @PYTHON_BUILD_TARGET@
+PYTHON_INSTALL_TARGET = @PYTHON_INSTALL_TARGET@
+PYTHON_CHECK_TARGET = @PYTHON_CHECK_TARGET@
+LIB_PATH_VAR = @LIB_PATH_VAR@
+teventdir = @teventdir@
+
+TALLOC_CFLAGS = @TALLOC_CFLAGS@
+TALLOC_LDFLAGS = @TALLOC_CFLAGS@
+TALLOC_LIBS = @TALLOC_LIBS@
+
+TEVENT_CFLAGS = @TEVENT_CFLAGS@
+TEVENT_LDFLAGS = @TEVENT_CFLAGS@
+TEVENT_LIBS = @TEVENT_LIBS@
+
+CFLAGS = $(CPPFLAGS) $(TALLOC_CFLAGS) $(TEVENT_CFLAGS) @CFLAGS@
+LDFLAGS = $(TALLOC_LDFLAGS) $(TEVENT_LDFLAGS) @LDFLAGS@
+LIBS = $(TALLOC_LIBS) $(TEVENT_LIBS) @LIBS@
+
+TEVENT_OBJ = @TEVENT_OBJ@ @LIBREPLACEOBJ@
+
+default: all
+
+include $(teventdir)/tevent.mk
+include $(teventdir)/rules.mk
+
+all:: showflags dirs $(PROGS) $(TEVENT_SOLIB) libtevent.a $(PYTHON_BUILD_TARGET)
+
+install:: all
+$(TEVENT_SOLIB): $(TEVENT_OBJ)
+ $(SHLD) $(SHLD_FLAGS) $(LDFLAGS) $(LIBS) -o $@ $(TEVENT_OBJ) @SONAMEFLAG@$(TEVENT_SONAME)
+
+shared-build: all
+ ${INSTALLCMD} -d $(sharedbuilddir)/lib
+ ${INSTALLCMD} -m 644 libtevent.a $(sharedbuilddir)/lib
+ ${INSTALLCMD} -m 755 $(TEVENT_SOLIB) $(sharedbuilddir)/lib
+ ln -sf $(TEVENT_SOLIB) $(sharedbuilddir)/lib/$(TEVENT_SONAME)
+ ln -sf $(TEVENT_SOLIB) $(sharedbuilddir)/lib/libtevent.so
+ ${INSTALLCMD} -d $(sharedbuilddir)/include
+ ${INSTALLCMD} -m 644 $(srcdir)/tevent.h $(sharedbuilddir)/include
+
+check: test
+
+test:: $(PYTHON_CHECK_TARGET)
+installcheck:: test install
+
+clean::
+ rm -f *.o *.a */*.o
+
+distclean:: clean
+ rm -f config.log config.status include/config.h config.cache
+ rm -f Makefile
+
+realdistclean:: distclean
+ rm -f configure include/config.h.in
diff --git a/lib/tevent/autogen.sh b/lib/tevent/autogen.sh
new file mode 100755
index 0000000000..fec05f54d4
--- /dev/null
+++ b/lib/tevent/autogen.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+rm -rf autom4te.cache
+rm -f configure config.h.in
+
+IPATHS="-I libreplace -I lib/replace -I ../libreplace -I ../replace -I ../../../lib/replace"
+autoconf $IPATHS || exit 1
+autoheader $IPATHS || exit 1
+
+rm -rf autom4te.cache
+
+swig -O -Wall -python -keyword events.i # Ignore errors for now
+
+echo "Now run ./configure and then make."
+exit 0
+
diff --git a/lib/tevent/build_macros.m4 b/lib/tevent/build_macros.m4
new file mode 100644
index 0000000000..c036668cd1
--- /dev/null
+++ b/lib/tevent/build_macros.m4
@@ -0,0 +1,14 @@
+AC_DEFUN(BUILD_WITH_SHARED_BUILD_DIR,
+ [ AC_ARG_WITH([shared-build-dir],
+ [AC_HELP_STRING([--with-shared-build-dir=DIR],
+ [temporary build directory where libraries are installed [$srcdir/sharedbuild]])])
+
+ sharedbuilddir="$srcdir/sharedbuild"
+ if test x"$with_shared_build_dir" != x; then
+ sharedbuilddir=$with_shared_build_dir
+ CFLAGS="$CFLAGS -I$with_shared_build_dir/include"
+ LDFLAGS="$LDFLAGS -L$with_shared_build_dir/lib"
+ fi
+ AC_SUBST(sharedbuilddir)
+ ])
+
diff --git a/lib/tevent/config.mk b/lib/tevent/config.mk
new file mode 100644
index 0000000000..5f9508a44f
--- /dev/null
+++ b/lib/tevent/config.mk
@@ -0,0 +1,59 @@
+##############################
+[MODULE::TEVENT_AIO]
+PRIVATE_DEPENDENCIES = LIBAIO_LINUX
+SUBSYSTEM = LIBTEVENT
+INIT_FUNCTION = s4_events_aio_init
+##############################
+
+TEVENT_AIO_OBJ_FILES = $(libteventsrcdir)/tevent_aio.o
+
+##############################
+[MODULE::TEVENT_EPOLL]
+SUBSYSTEM = LIBTEVENT
+INIT_FUNCTION = s4_events_epoll_init
+##############################
+
+TEVENT_EPOLL_OBJ_FILES = $(libteventsrcdir)/tevent_epoll.o
+
+##############################
+[MODULE::TEVENT_SELECT]
+SUBSYSTEM = LIBTEVENT
+INIT_FUNCTION = s4_events_select_init
+##############################
+
+TEVENT_SELECT_OBJ_FILES = $(libteventsrcdir)/tevent_select.o
+
+##############################
+[MODULE::TEVENT_STANDARD]
+SUBSYSTEM = LIBTEVENT
+INIT_FUNCTION = s4_events_standard_init
+##############################
+
+TEVENT_STANDARD_OBJ_FILES = $(libteventsrcdir)/tevent_standard.o
+
+################################################
+# Start SUBSYSTEM LIBTEVENT
+[LIBRARY::LIBTEVENT]
+PUBLIC_DEPENDENCIES = LIBTALLOC
+OUTPUT_TYPE = MERGED_OBJ
+CFLAGS = -I../lib/tevent
+#
+# End SUBSYSTEM LIBTEVENT
+################################################
+
+LIBTEVENT_OBJ_FILES = $(addprefix $(libteventsrcdir)/, tevent.o tevent_timed.o tevent_signal.o tevent_debug.o tevent_util.o tevent_s4.o)
+
+PUBLIC_HEADERS += $(addprefix $(libteventsrcdir)/, tevent.h tevent_internal.h)
+
+# TODO: Change python stuff to tevent
+[PYTHON::swig_events]
+LIBRARY_REALNAME = samba/_events.$(SHLIBEXT)
+PRIVATE_DEPENDENCIES = LIBTEVENT LIBSAMBA-HOSTCONFIG LIBSAMBA-UTIL
+
+swig_events_OBJ_FILES = $(libteventsrcdir)/events_wrap.o
+
+$(eval $(call python_py_module_template,samba/events.py,$(libteventsrcdir)/events.py))
+
+$(swig_events_OBJ_FILES): CFLAGS+=$(CFLAG_NO_UNUSED_MACROS) $(CFLAG_NO_CAST_QUAL)
+
+PC_FILES += $(libteventsrcdir)/tevent.pc
diff --git a/lib/tevent/configure.ac b/lib/tevent/configure.ac
new file mode 100644
index 0000000000..75719d13b4
--- /dev/null
+++ b/lib/tevent/configure.ac
@@ -0,0 +1,40 @@
+AC_PREREQ(2.50)
+AC_DEFUN([SMB_MODULE_DEFAULT], [echo -n ""])
+AC_DEFUN([SMB_LIBRARY_ENABLE], [echo -n ""])
+AC_DEFUN([SMB_ENABLE], [echo -n ""])
+AC_DEFUN([SMB_EXT_LIB], [echo -n ""])
+AC_INIT(tevent, 1.0.0)
+AC_CONFIG_SRCDIR([tevent.c])
+AC_CONFIG_HEADER(config.h)
+AC_LIBREPLACE_ALL_CHECKS
+
+AC_LD_EXPORT_DYNAMIC
+AC_LD_SONAMEFLAG
+AC_LD_PICFLAG
+AC_LD_SHLIBEXT
+AC_LIBREPLACE_SHLD
+AC_LIBREPLACE_SHLD_FLAGS
+AC_LIBREPLACE_RUNTIME_LIB_PATH_VAR
+
+m4_include(build_macros.m4)
+BUILD_WITH_SHARED_BUILD_DIR
+
+m4_include(pkg.m4)
+m4_include(libtalloc.m4)
+
+m4_include(libtevent.m4)
+AC_PATH_PROGS([PYTHON_CONFIG], [python2.6-config python2.5-config python2.4-config python-config])
+AC_PATH_PROGS([PYTHON], [python2.6 python2.5 python2.4 python])
+
+PYTHON_BUILD_TARGET="build-python"
+PYTHON_INSTALL_TARGET="install-python"
+PYTHON_CHECK_TARGET="check-python"
+AC_SUBST(PYTHON_BUILD_TARGET)
+AC_SUBST(PYTHON_INSTALL_TARGET)
+AC_SUBST(PYTHON_CHECK_TARGET)
+if test -z "$PYTHON_CONFIG"; then
+ PYTHON_BUILD_TARGET=""
+ PYTHON_INSTALL_TARGET=""
+ PYTHON_CHECK_TARGET=""
+fi
+AC_OUTPUT(Makefile events.pc)
diff --git a/lib/tevent/events.i b/lib/tevent/events.i
new file mode 100644
index 0000000000..7a604a9f23
--- /dev/null
+++ b/lib/tevent/events.i
@@ -0,0 +1,54 @@
+/*
+ Unix SMB/CIFS implementation.
+ Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
+
+ This program 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.
+
+ This program 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/>.
+*/
+
+%module(docstring="Event management.",package="samba.events") events;
+
+%import "../../lib/talloc/talloc.i";
+
+%{
+#include "tevent.h"
+typedef struct event_context event;
+%}
+
+typedef struct event_context {
+ %extend {
+ %feature("docstring") event "S.__init__()";
+ event(TALLOC_CTX *mem_ctx) { return event_context_init(mem_ctx); }
+ %feature("docstring") loop_once "S.loop_once() -> int";
+ int loop_once(void);
+ %feature("docstring") loop_wait "S.loop_wait() -> int";
+ int loop_wait(void);
+ }
+} event;
+%talloctype(event);
+
+%typemap(default,noblock=1) struct event_context * {
+ $1 = event_context_init(NULL);
+}
+
+%typemap(default,noblock=1) struct event_context * {
+ $1 = event_context_init(NULL);
+}
+
+struct event_context *event_context_init_byname(TALLOC_CTX *mem_ctx, const char *name);
+
+%feature("docstring") event_backend_list "event_backend_list() -> list";
+const char **event_backend_list(TALLOC_CTX *mem_ctx);
+%feature("docstring") event_set_default_backend "event_set_default_backend(name) -> None";
+%rename(set_default_backend) event_set_default_backend;
+void event_set_default_backend(const char *backend);
diff --git a/lib/tevent/events.py b/lib/tevent/events.py
new file mode 100644
index 0000000000..c15ea8b9e5
--- /dev/null
+++ b/lib/tevent/events.py
@@ -0,0 +1,94 @@
+# This file was automatically generated by SWIG (http://www.swig.org).
+# Version 1.3.36
+#
+# Don't modify this file, modify the SWIG interface instead.
+
+"""
+Event management.
+"""
+
+import _events
+import new
+new_instancemethod = new.instancemethod
+try:
+ _swig_property = property
+except NameError:
+ pass # Python < 2.2 doesn't have 'property'.
+def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
+ if (name == "thisown"): return self.this.own(value)
+ if (name == "this"):
+ if type(value).__name__ == 'PySwigObject':
+ self.__dict__[name] = value
+ return
+ method = class_type.__swig_setmethods__.get(name,None)
+ if method: return method(self,value)
+ if (not static) or hasattr(self,name):
+ self.__dict__[name] = value
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+
+def _swig_setattr(self,class_type,name,value):
+ return _swig_setattr_nondynamic(self,class_type,name,value,0)
+
+def _swig_getattr(self,class_type,name):
+ if (name == "thisown"): return self.this.own()
+ method = class_type.__swig_getmethods__.get(name,None)
+ if method: return method(self)
+ raise AttributeError,name
+
+def _swig_repr(self):
+ try: strthis = "proxy of " + self.this.__repr__()
+ except: strthis = ""
+ return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+import types
+try:
+ _object = types.ObjectType
+ _newclass = 1
+except AttributeError:
+ class _object : pass
+ _newclass = 0
+del types
+
+
+def _swig_setattr_nondynamic_method(set):
+ def set_attr(self,name,value):
+ if (name == "thisown"): return self.this.own(value)
+ if hasattr(self,name) or (name == "this"):
+ set(self,name,value)
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+ return set_attr
+
+
+class event(object):
+ thisown = _swig_property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
+ __repr__ = _swig_repr
+ def __init__(self, *args, **kwargs):
+ """S.__init__()"""
+ _events.event_swiginit(self,_events.new_event(*args, **kwargs))
+ def loop_once(*args, **kwargs):
+ """S.loop_once() -> int"""
+ return _events.event_loop_once(*args, **kwargs)
+
+ def loop_wait(*args, **kwargs):
+ """S.loop_wait() -> int"""
+ return _events.event_loop_wait(*args, **kwargs)
+
+ __swig_destroy__ = _events.delete_event
+event.loop_once = new_instancemethod(_events.event_loop_once,None,event)
+event.loop_wait = new_instancemethod(_events.event_loop_wait,None,event)
+event_swigregister = _events.event_swigregister
+event_swigregister(event)
+
+event_context_init_byname = _events.event_context_init_byname
+
+def event_backend_list(*args):
+ """event_backend_list() -> list"""
+ return _events.event_backend_list(*args)
+
+def set_default_backend(*args, **kwargs):
+ """event_set_default_backend(name) -> None"""
+ return _events.set_default_backend(*args, **kwargs)
+
+
diff --git a/lib/tdb/tdb_wrap.c b/lib/tevent/events_wrap.c
index e997e88572..b8b3a962bc 100644
--- a/lib/tdb/tdb_wrap.c
+++ b/lib/tevent/events_wrap.c
@@ -2480,19 +2480,12 @@ SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int argnum, int flags)
/* -------- TYPES TABLE (BEGIN) -------- */
-#define SWIGTYPE_p_TDB_DATA swig_types[0]
+#define SWIGTYPE_p_TALLOC_CTX swig_types[0]
#define SWIGTYPE_p_char swig_types[1]
-#define SWIGTYPE_p_int swig_types[2]
-#define SWIGTYPE_p_long_long swig_types[3]
-#define SWIGTYPE_p_short swig_types[4]
-#define SWIGTYPE_p_signed_char swig_types[5]
-#define SWIGTYPE_p_tdb_context swig_types[6]
-#define SWIGTYPE_p_unsigned_char swig_types[7]
-#define SWIGTYPE_p_unsigned_int swig_types[8]
-#define SWIGTYPE_p_unsigned_long_long swig_types[9]
-#define SWIGTYPE_p_unsigned_short swig_types[10]
-static swig_type_info *swig_types[12];
-static swig_module_info swig_module = {swig_types, 11, 0, 0, 0, 0};
+#define SWIGTYPE_p_event_context swig_types[2]
+#define SWIGTYPE_p_p_char swig_types[3]
+static swig_type_info *swig_types[5];
+static swig_module_info swig_module = {swig_types, 4, 0, 0, 0, 0};
#define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)
#define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)
@@ -2518,11 +2511,11 @@ static swig_module_info swig_module = {swig_types, 11, 0, 0, 0, 0};
#define SWIG_TypeQuery SWIG_Python_TypeQuery
/*-----------------------------------------------
- @(target):= _tdb.so
+ @(target):= _events.so
------------------------------------------------*/
-#define SWIG_init init_tdb
+#define SWIG_init init_events
-#define SWIG_name "_tdb"
+#define SWIG_name "_events"
#define SWIGVERSION 0x010336
#define SWIG_VERSION SWIGVERSION
@@ -2532,22 +2525,10 @@ static swig_module_info swig_module = {swig_types, 11, 0, 0, 0, 0};
#define SWIG_as_voidptrptr(a) ((void)SWIG_as_voidptr(*a),(void**)(a))
+#include "tevent.h"
+typedef struct event_context event;
-/* This symbol is used in both includes.h and Python.h which causes an
- annoying compiler warning. */
-
-#ifdef HAVE_FSTAT
-#undef HAVE_FSTAT
-#endif
-
-/* Include tdb headers */
-#include <stdint.h>
-#include <signal.h>
-#include <tdb.h>
-#include <fcntl.h>
-
-typedef TDB_CONTEXT tdb;
-
+SWIGINTERN event *new_event(TALLOC_CTX *mem_ctx){ return event_context_init(mem_ctx); }
#define SWIG_From_long PyInt_FromLong
@@ -2558,6 +2539,7 @@ SWIG_From_int (int value)
return SWIG_From_long (value);
}
+SWIGINTERN void delete_event(event *self){ talloc_free(self); }
SWIGINTERN swig_type_info*
SWIG_pchar_descriptor(void)
@@ -2626,294 +2608,40 @@ SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc)
-
-#include <limits.h>
-#if !defined(SWIG_NO_LLONG_MAX)
-# if !defined(LLONG_MAX) && defined(__GNUC__) && defined (__LONG_LONG_MAX__)
-# define LLONG_MAX __LONG_LONG_MAX__
-# define LLONG_MIN (-LLONG_MAX - 1LL)
-# define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL)
-# endif
-#endif
-
-
-SWIGINTERN int
-SWIG_AsVal_double (PyObject *obj, double *val)
-{
- int res = SWIG_TypeError;
- if (PyFloat_Check(obj)) {
- if (val) *val = PyFloat_AsDouble(obj);
- return SWIG_OK;
- } else if (PyInt_Check(obj)) {
- if (val) *val = PyInt_AsLong(obj);
- return SWIG_OK;
- } else if (PyLong_Check(obj)) {
- double v = PyLong_AsDouble(obj);
- if (!PyErr_Occurred()) {
- if (val) *val = v;
- return SWIG_OK;
- } else {
- PyErr_Clear();
- }
- }
-#ifdef SWIG_PYTHON_CAST_MODE
- {
- int dispatch = 0;
- double d = PyFloat_AsDouble(obj);
- if (!PyErr_Occurred()) {
- if (val) *val = d;
- return SWIG_AddCast(SWIG_OK);
- } else {
- PyErr_Clear();
- }
- if (!dispatch) {
- long v = PyLong_AsLong(obj);
- if (!PyErr_Occurred()) {
- if (val) *val = v;
- return SWIG_AddCast(SWIG_AddCast(SWIG_OK));
- } else {
- PyErr_Clear();
- }
- }
- }
-#endif
- return res;
-}
-
-
-#include <float.h>
-
-
-#include <math.h>
-
-
-SWIGINTERNINLINE int
-SWIG_CanCastAsInteger(double *d, double min, double max) {
- double x = *d;
- if ((min <= x && x <= max)) {
- double fx = floor(x);
- double cx = ceil(x);
- double rd = ((x - fx) < 0.5) ? fx : cx; /* simple rint */
- if ((errno == EDOM) || (errno == ERANGE)) {
- errno = 0;
- } else {
- double summ, reps, diff;
- if (rd < x) {
- diff = x - rd;
- } else if (rd > x) {
- diff = rd - x;
- } else {
- return 1;
- }
- summ = rd + x;
- reps = diff/summ;
- if (reps < 8*DBL_EPSILON) {
- *d = rd;
- return 1;
- }
- }
- }
- return 0;
-}
-
-
-SWIGINTERN int
-SWIG_AsVal_long (PyObject *obj, long* val)
-{
- if (PyInt_Check(obj)) {
- if (val) *val = PyInt_AsLong(obj);
- return SWIG_OK;
- } else if (PyLong_Check(obj)) {
- long v = PyLong_AsLong(obj);
- if (!PyErr_Occurred()) {
- if (val) *val = v;
- return SWIG_OK;
- } else {
- PyErr_Clear();
- }
- }
-#ifdef SWIG_PYTHON_CAST_MODE
- {
- int dispatch = 0;
- long v = PyInt_AsLong(obj);
- if (!PyErr_Occurred()) {
- if (val) *val = v;
- return SWIG_AddCast(SWIG_OK);
- } else {
- PyErr_Clear();
- }
- if (!dispatch) {
- double d;
- int res = SWIG_AddCast(SWIG_AsVal_double (obj,&d));
- if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LONG_MIN, LONG_MAX)) {
- if (val) *val = (long)(d);
- return res;
- }
- }
- }
-#endif
- return SWIG_TypeError;
-}
-
-
-SWIGINTERN int
-SWIG_AsVal_int (PyObject * obj, int *val)
-{
- long v;
- int res = SWIG_AsVal_long (obj, &v);
- if (SWIG_IsOK(res)) {
- if ((v < INT_MIN || v > INT_MAX)) {
- return SWIG_OverflowError;
- } else {
- if (val) *val = (int)(v);
- }
- }
- return res;
-}
-
-SWIGINTERN tdb *new_tdb(char const *name,int hash_size,int tdb_flags,int flags,mode_t mode){
- return tdb_open(name, hash_size, tdb_flags, flags, mode);
- }
-SWIGINTERN void delete_tdb(tdb *self){ tdb_close(self); }
-
-SWIGINTERNINLINE PyObject *
-SWIG_FromCharPtrAndSize(const char* carray, size_t size)
-{
- if (carray) {
- if (size > INT_MAX) {
- swig_type_info* pchar_descriptor = SWIG_pchar_descriptor();
- return pchar_descriptor ?
- SWIG_NewPointerObj((char *)(carray), pchar_descriptor, 0) : SWIG_Py_Void();
- } else {
- return PyString_FromStringAndSize(carray, (int)(size));
- }
- } else {
- return SWIG_Py_Void();
- }
-}
-
-
-SWIGINTERNINLINE PyObject *
-SWIG_FromCharPtr(const char *cptr)
-{
- return SWIG_FromCharPtrAndSize(cptr, (cptr ? strlen(cptr) : 0));
-}
-
-
-SWIGINTERNINLINE PyObject*
-SWIG_From_unsigned_SS_long (unsigned long value)
-{
- return (value > LONG_MAX) ?
- PyLong_FromUnsignedLong(value) : PyInt_FromLong((long)(value));
-}
-
-
-SWIGINTERNINLINE PyObject *
-SWIG_From_size_t (size_t value)
-{
- return SWIG_From_unsigned_SS_long ((unsigned long)(value));
-}
-
#ifdef __cplusplus
extern "C" {
#endif
-SWIGINTERN PyObject *_wrap_new_Tdb(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+SWIGINTERN PyObject *_wrap_new_event(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
- char *arg1 = (char *) 0 ;
- int arg2 ;
- int arg3 ;
- int arg4 ;
- mode_t arg5 ;
- int res1 ;
- char *buf1 = 0 ;
- int alloc1 = 0 ;
- int val2 ;
- int ecode2 = 0 ;
- int val3 ;
- int ecode3 = 0 ;
- int val4 ;
- int ecode4 = 0 ;
- int val5 ;
- int ecode5 = 0 ;
- PyObject * obj0 = 0 ;
- PyObject * obj1 = 0 ;
- PyObject * obj2 = 0 ;
- PyObject * obj3 = 0 ;
- PyObject * obj4 = 0 ;
- char * kwnames[] = {
- (char *) "name",(char *) "hash_size",(char *) "tdb_flags",(char *) "flags",(char *) "mode", NULL
- };
- tdb *result = 0 ;
+ TALLOC_CTX *arg1 = (TALLOC_CTX *) 0 ;
+ event *result = 0 ;
- arg2 = 0;
- arg3 = TDB_DEFAULT;
- arg4 = O_RDWR;
- arg5 = 0600;
- if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"O|OOOO:new_Tdb",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
- res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, NULL, &alloc1);
- if (!SWIG_IsOK(res1)) {
- SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_Tdb" "', argument " "1"" of type '" "char const *""'");
- }
- arg1 = (char *)(buf1);
- if (obj1) {
- ecode2 = SWIG_AsVal_int(obj1, &val2);
- if (!SWIG_IsOK(ecode2)) {
- SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "new_Tdb" "', argument " "2"" of type '" "int""'");
- }
- arg2 = (int)(val2);
- }
- if (obj2) {
- ecode3 = SWIG_AsVal_int(obj2, &val3);
- if (!SWIG_IsOK(ecode3)) {
- SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "new_Tdb" "', argument " "3"" of type '" "int""'");
- }
- arg3 = (int)(val3);
- }
- if (obj3) {
- ecode4 = SWIG_AsVal_int(obj3, &val4);
- if (!SWIG_IsOK(ecode4)) {
- SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "new_Tdb" "', argument " "4"" of type '" "int""'");
- }
- arg4 = (int)(val4);
- }
- if (obj4) {
- ecode5 = SWIG_AsVal_int(obj4, &val5);
- if (!SWIG_IsOK(ecode5)) {
- SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "new_Tdb" "', argument " "5"" of type '" "mode_t""'");
- }
- arg5 = (mode_t)(val5);
- }
- result = (tdb *)new_tdb((char const *)arg1,arg2,arg3,arg4,arg5);
- /* Throw an IOError exception from errno if tdb_open() returns NULL */
- if (result == NULL) {
- PyErr_SetFromErrno(PyExc_IOError);
- SWIG_fail;
- }
- resultobj = SWIG_NewPointerObj(result, SWIGTYPE_p_tdb_context, 0);
- if (alloc1 == SWIG_NEWOBJ) free((char*)buf1);
+ arg1 = NULL;
+ if (!SWIG_Python_UnpackTuple(args,"new_event",0,0,0)) SWIG_fail;
+ result = (event *)new_event(arg1);
+ resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_event_context, SWIG_POINTER_NEW | 0 );
return resultobj;
fail:
- if (alloc1 == SWIG_NEWOBJ) free((char*)buf1);
return NULL;
}
-SWIGINTERN PyObject *_wrap_Tdb_error(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_event_loop_once(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
- tdb *arg1 = (tdb *) 0 ;
+ event *arg1 = (event *) 0 ;
void *argp1 = 0 ;
int res1 = 0 ;
PyObject *swig_obj[1] ;
- enum TDB_ERROR result;
+ int result;
if (!args) SWIG_fail;
swig_obj[0] = args;
- res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_tdb_context, 0 | 0 );
+ res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_event_context, 0 | 0 );
if (!SWIG_IsOK(res1)) {
- SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Tdb_error" "', argument " "1"" of type '" "tdb *""'");
+ SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "event_loop_once" "', argument " "1"" of type '" "event *""'");
}
- arg1 = (tdb *)(argp1);
- result = (enum TDB_ERROR)tdb_error(arg1);
+ arg1 = (event *)(argp1);
+ result = (int)event_loop_once(arg1);
resultobj = SWIG_From_int((int)(result));
return resultobj;
fail:
@@ -2921,31 +2649,9 @@ fail:
}
-SWIGINTERN PyObject *_wrap_delete_Tdb(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_event_loop_wait(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
- tdb *arg1 = (tdb *) 0 ;
- void *argp1 = 0 ;
- int res1 = 0 ;
- PyObject *swig_obj[1] ;
-
- if (!args) SWIG_fail;
- swig_obj[0] = args;
- res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_tdb_context, SWIG_POINTER_DISOWN | 0 );
- if (!SWIG_IsOK(res1)) {
- SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_Tdb" "', argument " "1"" of type '" "tdb *""'");
- }
- arg1 = (tdb *)(argp1);
- delete_tdb(arg1);
- resultobj = SWIG_Py_Void();
- return resultobj;
-fail:
- return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Tdb_close(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
- PyObject *resultobj = 0;
- tdb *arg1 = (tdb *) 0 ;
+ event *arg1 = (event *) 0 ;
void *argp1 = 0 ;
int res1 = 0 ;
PyObject *swig_obj[1] ;
@@ -2953,61 +2659,12 @@ SWIGINTERN PyObject *_wrap_Tdb_close(PyObject *SWIGUNUSEDPARM(self), PyObject *a
if (!args) SWIG_fail;
swig_obj[0] = args;
- res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_tdb_context, 0 | 0 );
+ res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_event_context, 0 | 0 );
if (!SWIG_IsOK(res1)) {
- SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Tdb_close" "', argument " "1"" of type '" "tdb *""'");
- }
- arg1 = (tdb *)(argp1);
- result = (int)tdb_close(arg1);
- resultobj = SWIG_From_int((int)(result));
- return resultobj;
-fail:
- return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Tdb_append(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
- PyObject *resultobj = 0;
- tdb *arg1 = (tdb *) 0 ;
- TDB_DATA arg2 ;
- TDB_DATA arg3 ;
- void *argp1 = 0 ;
- int res1 = 0 ;
- PyObject * obj0 = 0 ;
- PyObject * obj1 = 0 ;
- PyObject * obj2 = 0 ;
- char * kwnames[] = {
- (char *) "self",(char *) "key",(char *) "new_dbuf", NULL
- };
- int result;
-
- if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOO:Tdb_append",kwnames,&obj0,&obj1,&obj2)) SWIG_fail;
- res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_tdb_context, 0 | 0 );
- if (!SWIG_IsOK(res1)) {
- SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Tdb_append" "', argument " "1"" of type '" "tdb *""'");
- }
- arg1 = (tdb *)(argp1);
- if (obj1 == Py_None) {
- (&arg2)->dsize = 0;
- (&arg2)->dptr = NULL;
- } else if (!PyString_Check(obj1)) {
- PyErr_SetString(PyExc_TypeError, "string arg expected");
- return NULL;
- } else {
- (&arg2)->dsize = PyString_Size(obj1);
- (&arg2)->dptr = (uint8_t *)PyString_AsString(obj1);
- }
- if (obj2 == Py_None) {
- (&arg3)->dsize = 0;
- (&arg3)->dptr = NULL;
- } else if (!PyString_Check(obj2)) {
- PyErr_SetString(PyExc_TypeError, "string arg expected");
- return NULL;
- } else {
- (&arg3)->dsize = PyString_Size(obj2);
- (&arg3)->dptr = (uint8_t *)PyString_AsString(obj2);
+ SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "event_loop_wait" "', argument " "1"" of type '" "event *""'");
}
- result = (int)tdb_append(arg1,arg2,arg3);
+ arg1 = (event *)(argp1);
+ result = (int)event_loop_wait(arg1);
resultobj = SWIG_From_int((int)(result));
return resultobj;
fail:
@@ -3015,749 +2672,149 @@ fail:
}
-SWIGINTERN PyObject *_wrap_Tdb_errorstr(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_delete_event(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
- tdb *arg1 = (tdb *) 0 ;
+ event *arg1 = (event *) 0 ;
void *argp1 = 0 ;
int res1 = 0 ;
PyObject *swig_obj[1] ;
- char *result = 0 ;
if (!args) SWIG_fail;
swig_obj[0] = args;
- res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_tdb_context, 0 | 0 );
- if (!SWIG_IsOK(res1)) {
- SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Tdb_errorstr" "', argument " "1"" of type '" "tdb *""'");
- }
- arg1 = (tdb *)(argp1);
- result = (char *)tdb_errorstr(arg1);
- resultobj = SWIG_FromCharPtr((const char *)result);
- return resultobj;
-fail:
- return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Tdb_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
- PyObject *resultobj = 0;
- tdb *arg1 = (tdb *) 0 ;
- TDB_DATA arg2 ;
- void *argp1 = 0 ;
- int res1 = 0 ;
- PyObject * obj0 = 0 ;
- PyObject * obj1 = 0 ;
- char * kwnames[] = {
- (char *) "self",(char *) "key", NULL
- };
- TDB_DATA result;
-
- if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO:Tdb_get",kwnames,&obj0,&obj1)) SWIG_fail;
- res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_tdb_context, 0 | 0 );
- if (!SWIG_IsOK(res1)) {
- SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Tdb_get" "', argument " "1"" of type '" "tdb *""'");
- }
- arg1 = (tdb *)(argp1);
- if (obj1 == Py_None) {
- (&arg2)->dsize = 0;
- (&arg2)->dptr = NULL;
- } else if (!PyString_Check(obj1)) {
- PyErr_SetString(PyExc_TypeError, "string arg expected");
- return NULL;
- } else {
- (&arg2)->dsize = PyString_Size(obj1);
- (&arg2)->dptr = (uint8_t *)PyString_AsString(obj1);
- }
- result = tdb_fetch(arg1,arg2);
- if ((&result)->dptr == NULL && (&result)->dsize == 0) {
- resultobj = Py_None;
- } else {
- resultobj = PyString_FromStringAndSize((const char *)(&result)->dptr, (&result)->dsize);
- free((&result)->dptr);
- }
- return resultobj;
-fail:
- return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Tdb_delete(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
- PyObject *resultobj = 0;
- tdb *arg1 = (tdb *) 0 ;
- TDB_DATA arg2 ;
- void *argp1 = 0 ;
- int res1 = 0 ;
- PyObject * obj0 = 0 ;
- PyObject * obj1 = 0 ;
- char * kwnames[] = {
- (char *) "self",(char *) "key", NULL
- };
- int result;
-
- if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO:Tdb_delete",kwnames,&obj0,&obj1)) SWIG_fail;
- res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_tdb_context, 0 | 0 );
+ res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_event_context, SWIG_POINTER_DISOWN | 0 );
if (!SWIG_IsOK(res1)) {
- SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Tdb_delete" "', argument " "1"" of type '" "tdb *""'");
- }
- arg1 = (tdb *)(argp1);
- if (obj1 == Py_None) {
- (&arg2)->dsize = 0;
- (&arg2)->dptr = NULL;
- } else if (!PyString_Check(obj1)) {
- PyErr_SetString(PyExc_TypeError, "string arg expected");
- return NULL;
- } else {
- (&arg2)->dsize = PyString_Size(obj1);
- (&arg2)->dptr = (uint8_t *)PyString_AsString(obj1);
- }
- result = (int)tdb_delete(arg1,arg2);
- resultobj = SWIG_From_int((int)(result));
- return resultobj;
-fail:
- return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Tdb_store(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
- PyObject *resultobj = 0;
- tdb *arg1 = (tdb *) 0 ;
- TDB_DATA arg2 ;
- TDB_DATA arg3 ;
- int arg4 ;
- void *argp1 = 0 ;
- int res1 = 0 ;
- int val4 ;
- int ecode4 = 0 ;
- PyObject * obj0 = 0 ;
- PyObject * obj1 = 0 ;
- PyObject * obj2 = 0 ;
- PyObject * obj3 = 0 ;
- char * kwnames[] = {
- (char *) "self",(char *) "key",(char *) "dbuf",(char *) "flag", NULL
- };
- int result;
-
- arg4 = TDB_REPLACE;
- if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOO|O:Tdb_store",kwnames,&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
- res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_tdb_context, 0 | 0 );
- if (!SWIG_IsOK(res1)) {
- SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Tdb_store" "', argument " "1"" of type '" "tdb *""'");
- }
- arg1 = (tdb *)(argp1);
- if (obj1 == Py_None) {
- (&arg2)->dsize = 0;
- (&arg2)->dptr = NULL;
- } else if (!PyString_Check(obj1)) {
- PyErr_SetString(PyExc_TypeError, "string arg expected");
- return NULL;
- } else {
- (&arg2)->dsize = PyString_Size(obj1);
- (&arg2)->dptr = (uint8_t *)PyString_AsString(obj1);
- }
- if (obj2 == Py_None) {
- (&arg3)->dsize = 0;
- (&arg3)->dptr = NULL;
- } else if (!PyString_Check(obj2)) {
- PyErr_SetString(PyExc_TypeError, "string arg expected");
- return NULL;
- } else {
- (&arg3)->dsize = PyString_Size(obj2);
- (&arg3)->dptr = (uint8_t *)PyString_AsString(obj2);
+ SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_event" "', argument " "1"" of type '" "event *""'");
}
- if (obj3) {
- ecode4 = SWIG_AsVal_int(obj3, &val4);
- if (!SWIG_IsOK(ecode4)) {
- SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Tdb_store" "', argument " "4"" of type '" "int""'");
- }
- arg4 = (int)(val4);
- }
- result = (int)tdb_store(arg1,arg2,arg3,arg4);
- resultobj = SWIG_From_int((int)(result));
+ arg1 = (event *)(argp1);
+ delete_event(arg1);
+ resultobj = SWIG_Py_Void();
return resultobj;
fail:
return NULL;
}
-SWIGINTERN PyObject *_wrap_Tdb_exists(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
- PyObject *resultobj = 0;
- tdb *arg1 = (tdb *) 0 ;
- TDB_DATA arg2 ;
- void *argp1 = 0 ;
- int res1 = 0 ;
- PyObject * obj0 = 0 ;
- PyObject * obj1 = 0 ;
- char * kwnames[] = {
- (char *) "self",(char *) "key", NULL
- };
- int result;
-
- if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO:Tdb_exists",kwnames,&obj0,&obj1)) SWIG_fail;
- res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_tdb_context, 0 | 0 );
- if (!SWIG_IsOK(res1)) {
- SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Tdb_exists" "', argument " "1"" of type '" "tdb *""'");
- }
- arg1 = (tdb *)(argp1);
- if (obj1 == Py_None) {
- (&arg2)->dsize = 0;
- (&arg2)->dptr = NULL;
- } else if (!PyString_Check(obj1)) {
- PyErr_SetString(PyExc_TypeError, "string arg expected");
- return NULL;
- } else {
- (&arg2)->dsize = PyString_Size(obj1);
- (&arg2)->dptr = (uint8_t *)PyString_AsString(obj1);
- }
- result = (int)tdb_exists(arg1,arg2);
- resultobj = SWIG_From_int((int)(result));
- return resultobj;
-fail:
- return NULL;
+SWIGINTERN PyObject *event_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+ PyObject *obj;
+ if (!SWIG_Python_UnpackTuple(args,(char*)"swigregister", 1, 1,&obj)) return NULL;
+ SWIG_TypeNewClientData(SWIGTYPE_p_event_context, SWIG_NewClientData(obj));
+ return SWIG_Py_Void();
}
-
-SWIGINTERN PyObject *_wrap_Tdb_firstkey(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
- PyObject *resultobj = 0;
- tdb *arg1 = (tdb *) 0 ;
- void *argp1 = 0 ;
- int res1 = 0 ;
- PyObject *swig_obj[1] ;
- TDB_DATA result;
-
- if (!args) SWIG_fail;
- swig_obj[0] = args;
- res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_tdb_context, 0 | 0 );
- if (!SWIG_IsOK(res1)) {
- SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Tdb_firstkey" "', argument " "1"" of type '" "tdb *""'");
- }
- arg1 = (tdb *)(argp1);
- result = tdb_firstkey(arg1);
- if ((&result)->dptr == NULL && (&result)->dsize == 0) {
- resultobj = Py_None;
- } else {
- resultobj = PyString_FromStringAndSize((const char *)(&result)->dptr, (&result)->dsize);
- free((&result)->dptr);
- }
- return resultobj;
-fail:
- return NULL;
+SWIGINTERN PyObject *event_swiginit(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+ return SWIG_Python_InitShadowInstance(args);
}
-
-SWIGINTERN PyObject *_wrap_Tdb_nextkey(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+SWIGINTERN PyObject *_wrap_event_context_init_byname(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
PyObject *resultobj = 0;
- tdb *arg1 = (tdb *) 0 ;
- TDB_DATA arg2 ;
- void *argp1 = 0 ;
- int res1 = 0 ;
+ TALLOC_CTX *arg1 = (TALLOC_CTX *) 0 ;
+ char *arg2 = (char *) 0 ;
+ int res2 ;
+ char *buf2 = 0 ;
+ int alloc2 = 0 ;
PyObject * obj0 = 0 ;
- PyObject * obj1 = 0 ;
char * kwnames[] = {
- (char *) "self",(char *) "key", NULL
+ (char *) "name", NULL
};
- TDB_DATA result;
-
- if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO:Tdb_nextkey",kwnames,&obj0,&obj1)) SWIG_fail;
- res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_tdb_context, 0 | 0 );
- if (!SWIG_IsOK(res1)) {
- SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Tdb_nextkey" "', argument " "1"" of type '" "tdb *""'");
- }
- arg1 = (tdb *)(argp1);
- if (obj1 == Py_None) {
- (&arg2)->dsize = 0;
- (&arg2)->dptr = NULL;
- } else if (!PyString_Check(obj1)) {
- PyErr_SetString(PyExc_TypeError, "string arg expected");
- return NULL;
- } else {
- (&arg2)->dsize = PyString_Size(obj1);
- (&arg2)->dptr = (uint8_t *)PyString_AsString(obj1);
- }
- result = tdb_nextkey(arg1,arg2);
- if ((&result)->dptr == NULL && (&result)->dsize == 0) {
- resultobj = Py_None;
- } else {
- resultobj = PyString_FromStringAndSize((const char *)(&result)->dptr, (&result)->dsize);
- free((&result)->dptr);
- }
- return resultobj;
-fail:
- return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Tdb_lock_all(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
- PyObject *resultobj = 0;
- tdb *arg1 = (tdb *) 0 ;
- void *argp1 = 0 ;
- int res1 = 0 ;
- PyObject *swig_obj[1] ;
- int result;
-
- if (!args) SWIG_fail;
- swig_obj[0] = args;
- res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_tdb_context, 0 | 0 );
- if (!SWIG_IsOK(res1)) {
- SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Tdb_lock_all" "', argument " "1"" of type '" "tdb *""'");
- }
- arg1 = (tdb *)(argp1);
- result = (int)tdb_lockall(arg1);
- resultobj = SWIG_From_int((int)(result));
- return resultobj;
-fail:
- return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Tdb_unlock_all(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
- PyObject *resultobj = 0;
- tdb *arg1 = (tdb *) 0 ;
- void *argp1 = 0 ;
- int res1 = 0 ;
- PyObject *swig_obj[1] ;
- int result;
-
- if (!args) SWIG_fail;
- swig_obj[0] = args;
- res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_tdb_context, 0 | 0 );
- if (!SWIG_IsOK(res1)) {
- SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Tdb_unlock_all" "', argument " "1"" of type '" "tdb *""'");
- }
- arg1 = (tdb *)(argp1);
- result = (int)tdb_unlockall(arg1);
- resultobj = SWIG_From_int((int)(result));
- return resultobj;
-fail:
- return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Tdb_read_lock_all(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
- PyObject *resultobj = 0;
- tdb *arg1 = (tdb *) 0 ;
- void *argp1 = 0 ;
- int res1 = 0 ;
- PyObject *swig_obj[1] ;
- int result;
-
- if (!args) SWIG_fail;
- swig_obj[0] = args;
- res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_tdb_context, 0 | 0 );
- if (!SWIG_IsOK(res1)) {
- SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Tdb_read_lock_all" "', argument " "1"" of type '" "tdb *""'");
- }
- arg1 = (tdb *)(argp1);
- result = (int)tdb_lockall_read(arg1);
- resultobj = SWIG_From_int((int)(result));
- return resultobj;
-fail:
- return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Tdb_read_unlock_all(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
- PyObject *resultobj = 0;
- tdb *arg1 = (tdb *) 0 ;
- void *argp1 = 0 ;
- int res1 = 0 ;
- PyObject *swig_obj[1] ;
- int result;
-
- if (!args) SWIG_fail;
- swig_obj[0] = args;
- res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_tdb_context, 0 | 0 );
- if (!SWIG_IsOK(res1)) {
- SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Tdb_read_unlock_all" "', argument " "1"" of type '" "tdb *""'");
- }
- arg1 = (tdb *)(argp1);
- result = (int)tdb_unlockall_read(arg1);
- resultobj = SWIG_From_int((int)(result));
- return resultobj;
-fail:
- return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Tdb_reopen(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
- PyObject *resultobj = 0;
- tdb *arg1 = (tdb *) 0 ;
- void *argp1 = 0 ;
- int res1 = 0 ;
- PyObject *swig_obj[1] ;
- int result;
-
- if (!args) SWIG_fail;
- swig_obj[0] = args;
- res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_tdb_context, 0 | 0 );
- if (!SWIG_IsOK(res1)) {
- SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Tdb_reopen" "', argument " "1"" of type '" "tdb *""'");
- }
- arg1 = (tdb *)(argp1);
- result = (int)tdb_reopen(arg1);
- resultobj = SWIG_From_int((int)(result));
- return resultobj;
-fail:
- return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Tdb_transaction_start(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
- PyObject *resultobj = 0;
- tdb *arg1 = (tdb *) 0 ;
- void *argp1 = 0 ;
- int res1 = 0 ;
- PyObject *swig_obj[1] ;
- int result;
-
- if (!args) SWIG_fail;
- swig_obj[0] = args;
- res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_tdb_context, 0 | 0 );
- if (!SWIG_IsOK(res1)) {
- SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Tdb_transaction_start" "', argument " "1"" of type '" "tdb *""'");
- }
- arg1 = (tdb *)(argp1);
- result = (int)tdb_transaction_start(arg1);
- resultobj = SWIG_From_int((int)(result));
- return resultobj;
-fail:
- return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Tdb_transaction_commit(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
- PyObject *resultobj = 0;
- tdb *arg1 = (tdb *) 0 ;
- void *argp1 = 0 ;
- int res1 = 0 ;
- PyObject *swig_obj[1] ;
- int result;
-
- if (!args) SWIG_fail;
- swig_obj[0] = args;
- res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_tdb_context, 0 | 0 );
- if (!SWIG_IsOK(res1)) {
- SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Tdb_transaction_commit" "', argument " "1"" of type '" "tdb *""'");
- }
- arg1 = (tdb *)(argp1);
- result = (int)tdb_transaction_commit(arg1);
- resultobj = SWIG_From_int((int)(result));
- return resultobj;
-fail:
- return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Tdb_transaction_cancel(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
- PyObject *resultobj = 0;
- tdb *arg1 = (tdb *) 0 ;
- void *argp1 = 0 ;
- int res1 = 0 ;
- PyObject *swig_obj[1] ;
- int result;
-
- if (!args) SWIG_fail;
- swig_obj[0] = args;
- res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_tdb_context, 0 | 0 );
- if (!SWIG_IsOK(res1)) {
- SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Tdb_transaction_cancel" "', argument " "1"" of type '" "tdb *""'");
- }
- arg1 = (tdb *)(argp1);
- result = (int)tdb_transaction_cancel(arg1);
- resultobj = SWIG_From_int((int)(result));
- return resultobj;
-fail:
- return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Tdb_transaction_recover(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
- PyObject *resultobj = 0;
- tdb *arg1 = (tdb *) 0 ;
- void *argp1 = 0 ;
- int res1 = 0 ;
- PyObject *swig_obj[1] ;
- int result;
-
- if (!args) SWIG_fail;
- swig_obj[0] = args;
- res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_tdb_context, 0 | 0 );
- if (!SWIG_IsOK(res1)) {
- SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Tdb_transaction_recover" "', argument " "1"" of type '" "tdb *""'");
- }
- arg1 = (tdb *)(argp1);
- result = (int)tdb_transaction_recover(arg1);
- resultobj = SWIG_From_int((int)(result));
- return resultobj;
-fail:
- return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Tdb_hash_size(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
- PyObject *resultobj = 0;
- tdb *arg1 = (tdb *) 0 ;
- void *argp1 = 0 ;
- int res1 = 0 ;
- PyObject *swig_obj[1] ;
- int result;
-
- if (!args) SWIG_fail;
- swig_obj[0] = args;
- res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_tdb_context, 0 | 0 );
- if (!SWIG_IsOK(res1)) {
- SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Tdb_hash_size" "', argument " "1"" of type '" "tdb *""'");
- }
- arg1 = (tdb *)(argp1);
- result = (int)tdb_hash_size(arg1);
- resultobj = SWIG_From_int((int)(result));
+ struct event_context *result = 0 ;
+
+ arg1 = NULL;
+ if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"O:event_context_init_byname",kwnames,&obj0)) SWIG_fail;
+ res2 = SWIG_AsCharPtrAndSize(obj0, &buf2, NULL, &alloc2);
+ if (!SWIG_IsOK(res2)) {
+ SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "event_context_init_byname" "', argument " "2"" of type '" "char const *""'");
+ }
+ arg2 = (char *)(buf2);
+ result = (struct event_context *)event_context_init_byname(arg1,(char const *)arg2);
+ resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_event_context, 0 | 0 );
+ if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
return resultobj;
fail:
+ if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
return NULL;
}
-SWIGINTERN PyObject *_wrap_Tdb_map_size(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_event_backend_list(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
- tdb *arg1 = (tdb *) 0 ;
- void *argp1 = 0 ;
- int res1 = 0 ;
- PyObject *swig_obj[1] ;
- size_t result;
+ TALLOC_CTX *arg1 = (TALLOC_CTX *) 0 ;
+ char **result = 0 ;
- if (!args) SWIG_fail;
- swig_obj[0] = args;
- res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_tdb_context, 0 | 0 );
- if (!SWIG_IsOK(res1)) {
- SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Tdb_map_size" "', argument " "1"" of type '" "tdb *""'");
- }
- arg1 = (tdb *)(argp1);
- result = tdb_map_size(arg1);
- resultobj = SWIG_From_size_t((size_t)(result));
+ arg1 = NULL;
+ if (!SWIG_Python_UnpackTuple(args,"event_backend_list",0,0,0)) SWIG_fail;
+ result = (char **)event_backend_list(arg1);
+ resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_p_char, 0 | 0 );
return resultobj;
fail:
return NULL;
}
-SWIGINTERN PyObject *_wrap_Tdb_get_flags(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_set_default_backend(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
PyObject *resultobj = 0;
- tdb *arg1 = (tdb *) 0 ;
- void *argp1 = 0 ;
- int res1 = 0 ;
- PyObject *swig_obj[1] ;
- int result;
-
- if (!args) SWIG_fail;
- swig_obj[0] = args;
- res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_tdb_context, 0 | 0 );
- if (!SWIG_IsOK(res1)) {
- SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Tdb_get_flags" "', argument " "1"" of type '" "tdb *""'");
- }
- arg1 = (tdb *)(argp1);
- result = (int)tdb_get_flags(arg1);
- resultobj = SWIG_From_int((int)(result));
- return resultobj;
-fail:
- return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Tdb_set_max_dead(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
- PyObject *resultobj = 0;
- tdb *arg1 = (tdb *) 0 ;
- int arg2 ;
- void *argp1 = 0 ;
- int res1 = 0 ;
- int val2 ;
- int ecode2 = 0 ;
+ char *arg1 = (char *) 0 ;
+ int res1 ;
+ char *buf1 = 0 ;
+ int alloc1 = 0 ;
PyObject * obj0 = 0 ;
- PyObject * obj1 = 0 ;
char * kwnames[] = {
- (char *) "self",(char *) "max_dead", NULL
+ (char *) "backend", NULL
};
- if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO:Tdb_set_max_dead",kwnames,&obj0,&obj1)) SWIG_fail;
- res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_tdb_context, 0 | 0 );
+ if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"O:set_default_backend",kwnames,&obj0)) SWIG_fail;
+ res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, NULL, &alloc1);
if (!SWIG_IsOK(res1)) {
- SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Tdb_set_max_dead" "', argument " "1"" of type '" "tdb *""'");
+ SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "set_default_backend" "', argument " "1"" of type '" "char const *""'");
}
- arg1 = (tdb *)(argp1);
- ecode2 = SWIG_AsVal_int(obj1, &val2);
- if (!SWIG_IsOK(ecode2)) {
- SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Tdb_set_max_dead" "', argument " "2"" of type '" "int""'");
- }
- arg2 = (int)(val2);
- tdb_set_max_dead(arg1,arg2);
+ arg1 = (char *)(buf1);
+ event_set_default_backend((char const *)arg1);
resultobj = SWIG_Py_Void();
+ if (alloc1 == SWIG_NEWOBJ) free((char*)buf1);
return resultobj;
fail:
+ if (alloc1 == SWIG_NEWOBJ) free((char*)buf1);
return NULL;
}
-SWIGINTERN PyObject *_wrap_Tdb_name(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
- PyObject *resultobj = 0;
- tdb *arg1 = (tdb *) 0 ;
- void *argp1 = 0 ;
- int res1 = 0 ;
- PyObject *swig_obj[1] ;
- char *result = 0 ;
-
- if (!args) SWIG_fail;
- swig_obj[0] = args;
- res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_tdb_context, 0 | 0 );
- if (!SWIG_IsOK(res1)) {
- SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Tdb_name" "', argument " "1"" of type '" "tdb *""'");
- }
- arg1 = (tdb *)(argp1);
- result = (char *)tdb_name(arg1);
- resultobj = SWIG_FromCharPtr((const char *)result);
- return resultobj;
-fail:
- return NULL;
-}
-
-
-SWIGINTERN PyObject *Tdb_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
- PyObject *obj;
- if (!SWIG_Python_UnpackTuple(args,(char*)"swigregister", 1, 1,&obj)) return NULL;
- SWIG_TypeNewClientData(SWIGTYPE_p_tdb_context, SWIG_NewClientData(obj));
- return SWIG_Py_Void();
-}
-
-SWIGINTERN PyObject *Tdb_swiginit(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
- return SWIG_Python_InitShadowInstance(args);
-}
-
static PyMethodDef SwigMethods[] = {
- { (char *)"new_Tdb", (PyCFunction) _wrap_new_Tdb, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
- "S.__init__(name,hash_size=0,tdb_flags=TDB_DEFAULT,flags=O_RDWR,mode=0600)\n"
- "Open a TDB file.\n"
- ""},
- { (char *)"Tdb_error", (PyCFunction)_wrap_Tdb_error, METH_O, (char *)"\n"
- "S.error() -> int\n"
- "Find last error number returned by operation on this TDB.\n"
- ""},
- { (char *)"delete_Tdb", (PyCFunction)_wrap_delete_Tdb, METH_O, NULL},
- { (char *)"Tdb_close", (PyCFunction)_wrap_Tdb_close, METH_O, (char *)"\n"
- "S.close() -> None\n"
- "Close the TDB file.\n"
- ""},
- { (char *)"Tdb_append", (PyCFunction) _wrap_Tdb_append, METH_VARARGS | METH_KEYWORDS, NULL},
- { (char *)"Tdb_errorstr", (PyCFunction)_wrap_Tdb_errorstr, METH_O, (char *)"\n"
- "S.errorstr() -> errorstring\n"
- "Obtain last error message.\n"
- ""},
- { (char *)"Tdb_get", (PyCFunction) _wrap_Tdb_get, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
- "S.fetch(key) -> value\n"
- "Fetch a value.\n"
- ""},
- { (char *)"Tdb_delete", (PyCFunction) _wrap_Tdb_delete, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
- "S.delete(key) -> None\n"
- "Delete an entry.\n"
- ""},
- { (char *)"Tdb_store", (PyCFunction) _wrap_Tdb_store, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
- "S.store(key, value, flag=TDB_REPLACE) -> None\n"
- "Store an entry.\n"
- ""},
- { (char *)"Tdb_exists", (PyCFunction) _wrap_Tdb_exists, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
- "S.exists(key) -> bool\n"
- "Check whether key exists in this database.\n"
- ""},
- { (char *)"Tdb_firstkey", (PyCFunction)_wrap_Tdb_firstkey, METH_O, (char *)"\n"
- "S.firstkey() -> data\n"
- "Return the first key in this database.\n"
- ""},
- { (char *)"Tdb_nextkey", (PyCFunction) _wrap_Tdb_nextkey, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
- "S.nextkey(prev) -> data\n"
- "Return the next key in this database.\n"
- ""},
- { (char *)"Tdb_lock_all", (PyCFunction)_wrap_Tdb_lock_all, METH_O, (char *)"S.lockall() -> bool"},
- { (char *)"Tdb_unlock_all", (PyCFunction)_wrap_Tdb_unlock_all, METH_O, (char *)"S.unlockall() -> bool"},
- { (char *)"Tdb_read_lock_all", (PyCFunction)_wrap_Tdb_read_lock_all, METH_O, NULL},
- { (char *)"Tdb_read_unlock_all", (PyCFunction)_wrap_Tdb_read_unlock_all, METH_O, NULL},
- { (char *)"Tdb_reopen", (PyCFunction)_wrap_Tdb_reopen, METH_O, (char *)"\n"
- "S.reopen() -> bool\n"
- "Reopen this file.\n"
- ""},
- { (char *)"Tdb_transaction_start", (PyCFunction)_wrap_Tdb_transaction_start, METH_O, (char *)"\n"
- "S.transaction_start() -> None\n"
- "Start a new transaction.\n"
- ""},
- { (char *)"Tdb_transaction_commit", (PyCFunction)_wrap_Tdb_transaction_commit, METH_O, (char *)"\n"
- "S.transaction_commit() -> None\n"
- "Commit the currently active transaction.\n"
- ""},
- { (char *)"Tdb_transaction_cancel", (PyCFunction)_wrap_Tdb_transaction_cancel, METH_O, (char *)"\n"
- "S.transaction_cancel() -> None\n"
- "Cancel the currently active transaction.\n"
- ""},
- { (char *)"Tdb_transaction_recover", (PyCFunction)_wrap_Tdb_transaction_recover, METH_O, NULL},
- { (char *)"Tdb_hash_size", (PyCFunction)_wrap_Tdb_hash_size, METH_O, (char *)"S.hash_size() -> int"},
- { (char *)"Tdb_map_size", (PyCFunction)_wrap_Tdb_map_size, METH_O, (char *)"S.map_size() -> int"},
- { (char *)"Tdb_get_flags", (PyCFunction)_wrap_Tdb_get_flags, METH_O, (char *)"S.get_flags() -> int"},
- { (char *)"Tdb_set_max_dead", (PyCFunction) _wrap_Tdb_set_max_dead, METH_VARARGS | METH_KEYWORDS, (char *)"S.set_max_dead(int) -> None"},
- { (char *)"Tdb_name", (PyCFunction)_wrap_Tdb_name, METH_O, (char *)"\n"
- "S.name() -> path\n"
- "Return filename of this TDB file.\n"
- ""},
- { (char *)"Tdb_swigregister", Tdb_swigregister, METH_VARARGS, NULL},
- { (char *)"Tdb_swiginit", Tdb_swiginit, METH_VARARGS, NULL},
+ { (char *)"new_event", (PyCFunction)_wrap_new_event, METH_NOARGS, (char *)"S.__init__()"},
+ { (char *)"event_loop_once", (PyCFunction)_wrap_event_loop_once, METH_O, (char *)"S.loop_once() -> int"},
+ { (char *)"event_loop_wait", (PyCFunction)_wrap_event_loop_wait, METH_O, (char *)"S.loop_wait() -> int"},
+ { (char *)"delete_event", (PyCFunction)_wrap_delete_event, METH_O, NULL},
+ { (char *)"event_swigregister", event_swigregister, METH_VARARGS, NULL},
+ { (char *)"event_swiginit", event_swiginit, METH_VARARGS, NULL},
+ { (char *)"event_context_init_byname", (PyCFunction) _wrap_event_context_init_byname, METH_VARARGS | METH_KEYWORDS, NULL},
+ { (char *)"event_backend_list", (PyCFunction)_wrap_event_backend_list, METH_NOARGS, (char *)"event_backend_list() -> list"},
+ { (char *)"set_default_backend", (PyCFunction) _wrap_set_default_backend, METH_VARARGS | METH_KEYWORDS, (char *)"event_set_default_backend(name) -> None"},
{ NULL, NULL, 0, NULL }
};
/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */
-static swig_type_info _swigt__p_TDB_DATA = {"_p_TDB_DATA", "TDB_DATA *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_TALLOC_CTX = {"_p_TALLOC_CTX", "TALLOC_CTX *", 0, 0, (void*)0, 0};
static swig_type_info _swigt__p_char = {"_p_char", "char *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_int = {"_p_int", "intptr_t *|int *|int_least32_t *|int_fast32_t *|int32_t *|int_fast16_t *|mode_t *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_long_long = {"_p_long_long", "int_least64_t *|int_fast64_t *|int64_t *|long long *|intmax_t *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_short = {"_p_short", "short *|int_least16_t *|int16_t *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_signed_char = {"_p_signed_char", "signed char *|int_least8_t *|int_fast8_t *|int8_t *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_tdb_context = {"_p_tdb_context", "struct tdb_context *|tdb *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_unsigned_char = {"_p_unsigned_char", "unsigned char *|uint_least8_t *|uint_fast8_t *|uint8_t *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_unsigned_int = {"_p_unsigned_int", "uintptr_t *|uint_least32_t *|uint_fast32_t *|uint32_t *|unsigned int *|uint_fast16_t *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_unsigned_long_long = {"_p_unsigned_long_long", "uint_least64_t *|uint_fast64_t *|uint64_t *|unsigned long long *|uintmax_t *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_unsigned_short = {"_p_unsigned_short", "unsigned short *|uint_least16_t *|uint16_t *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_event_context = {"_p_event_context", "struct event_context *|event *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_p_char = {"_p_p_char", "char **", 0, 0, (void*)0, 0};
static swig_type_info *swig_type_initial[] = {
- &_swigt__p_TDB_DATA,
+ &_swigt__p_TALLOC_CTX,
&_swigt__p_char,
- &_swigt__p_int,
- &_swigt__p_long_long,
- &_swigt__p_short,
- &_swigt__p_signed_char,
- &_swigt__p_tdb_context,
- &_swigt__p_unsigned_char,
- &_swigt__p_unsigned_int,
- &_swigt__p_unsigned_long_long,
- &_swigt__p_unsigned_short,
+ &_swigt__p_event_context,
+ &_swigt__p_p_char,
};
-static swig_cast_info _swigc__p_TDB_DATA[] = { {&_swigt__p_TDB_DATA, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_TALLOC_CTX[] = { {&_swigt__p_TALLOC_CTX, 0, 0, 0},{0, 0, 0, 0}};
static swig_cast_info _swigc__p_char[] = { {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_int[] = { {&_swigt__p_int, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_long_long[] = { {&_swigt__p_long_long, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_short[] = { {&_swigt__p_short, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_signed_char[] = { {&_swigt__p_signed_char, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_tdb_context[] = { {&_swigt__p_tdb_context, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_unsigned_char[] = { {&_swigt__p_unsigned_char, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_unsigned_int[] = { {&_swigt__p_unsigned_int, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_unsigned_long_long[] = { {&_swigt__p_unsigned_long_long, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_unsigned_short[] = { {&_swigt__p_unsigned_short, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_event_context[] = { {&_swigt__p_event_context, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_p_char[] = { {&_swigt__p_p_char, 0, 0, 0},{0, 0, 0, 0}};
static swig_cast_info *swig_cast_initial[] = {
- _swigc__p_TDB_DATA,
+ _swigc__p_TALLOC_CTX,
_swigc__p_char,
- _swigc__p_int,
- _swigc__p_long_long,
- _swigc__p_short,
- _swigc__p_signed_char,
- _swigc__p_tdb_context,
- _swigc__p_unsigned_char,
- _swigc__p_unsigned_int,
- _swigc__p_unsigned_long_long,
- _swigc__p_unsigned_short,
+ _swigc__p_event_context,
+ _swigc__p_p_char,
};
@@ -4287,26 +3344,5 @@ SWIGEXPORT void SWIG_init(void) {
SWIG_InstallConstants(d,swig_const_table);
- SWIG_Python_SetConstant(d, "REPLACE",SWIG_From_int((int)(TDB_REPLACE)));
- SWIG_Python_SetConstant(d, "INSERT",SWIG_From_int((int)(TDB_INSERT)));
- SWIG_Python_SetConstant(d, "MODIFY",SWIG_From_int((int)(TDB_MODIFY)));
- SWIG_Python_SetConstant(d, "DEFAULT",SWIG_From_int((int)(TDB_DEFAULT)));
- SWIG_Python_SetConstant(d, "CLEAR_IF_FIRST",SWIG_From_int((int)(TDB_CLEAR_IF_FIRST)));
- SWIG_Python_SetConstant(d, "INTERNAL",SWIG_From_int((int)(TDB_INTERNAL)));
- SWIG_Python_SetConstant(d, "NOLOCK",SWIG_From_int((int)(TDB_NOLOCK)));
- SWIG_Python_SetConstant(d, "NOMMAP",SWIG_From_int((int)(TDB_NOMMAP)));
- SWIG_Python_SetConstant(d, "CONVERT",SWIG_From_int((int)(TDB_CONVERT)));
- SWIG_Python_SetConstant(d, "BIGENDIAN",SWIG_From_int((int)(TDB_BIGENDIAN)));
- SWIG_Python_SetConstant(d, "TDB_SUCCESS",SWIG_From_int((int)(TDB_SUCCESS)));
- SWIG_Python_SetConstant(d, "TDB_ERR_CORRUPT",SWIG_From_int((int)(TDB_ERR_CORRUPT)));
- SWIG_Python_SetConstant(d, "TDB_ERR_IO",SWIG_From_int((int)(TDB_ERR_IO)));
- SWIG_Python_SetConstant(d, "TDB_ERR_LOCK",SWIG_From_int((int)(TDB_ERR_LOCK)));
- SWIG_Python_SetConstant(d, "TDB_ERR_OOM",SWIG_From_int((int)(TDB_ERR_OOM)));
- SWIG_Python_SetConstant(d, "TDB_ERR_EXISTS",SWIG_From_int((int)(TDB_ERR_EXISTS)));
- SWIG_Python_SetConstant(d, "TDB_ERR_NOLOCK",SWIG_From_int((int)(TDB_ERR_NOLOCK)));
- SWIG_Python_SetConstant(d, "TDB_ERR_LOCK_TIMEOUT",SWIG_From_int((int)(TDB_ERR_LOCK_TIMEOUT)));
- SWIG_Python_SetConstant(d, "TDB_ERR_NOEXIST",SWIG_From_int((int)(TDB_ERR_NOEXIST)));
- SWIG_Python_SetConstant(d, "TDB_ERR_EINVAL",SWIG_From_int((int)(TDB_ERR_EINVAL)));
- SWIG_Python_SetConstant(d, "TDB_ERR_RDONLY",SWIG_From_int((int)(TDB_ERR_RDONLY)));
}
diff --git a/lib/tevent/libtalloc.m4 b/lib/tevent/libtalloc.m4
new file mode 100644
index 0000000000..a4c5b8a9d9
--- /dev/null
+++ b/lib/tevent/libtalloc.m4
@@ -0,0 +1,7 @@
+AC_SUBST(TALLOC_OBJ)
+AC_SUBST(TALLOC_CFLAGS)
+AC_SUBST(TALLOC_LIBS)
+
+AC_CHECK_HEADER(talloc.h,
+ [AC_CHECK_LIB(talloc, talloc_init, [TALLOC_LIBS="-ltalloc"]) ],
+ [PKG_CHECK_MODULES(TALLOC, talloc)])
diff --git a/lib/tevent/libtevent.m4 b/lib/tevent/libtevent.m4
new file mode 100644
index 0000000000..30105d9bef
--- /dev/null
+++ b/lib/tevent/libtevent.m4
@@ -0,0 +1,51 @@
+dnl find the tevent sources. This is meant to work both for
+dnl standalone builds, and builds of packages using libtevent
+if test x"$teventdir" = "x"; then
+ teventdir=""
+ teventpaths="$srcdir $srcdir/../lib/tevent $srcdir/tevent $srcdir/../tevent"
+ for d in $teventpaths; do
+ if test -f "$d/tevent.c"; then
+ teventdir="$d"
+ AC_SUBST(teventdir)
+ break;
+ fi
+ done
+ if test x"$teventdir" = "x"; then
+ AC_MSG_ERROR([cannot find libtevent source in $teventpaths])
+ fi
+fi
+
+TEVENT_OBJ="tevent.o tevent_select.o tevent_signal.o tevent_timed.o tevent_standard.o tevent_debug.o tevent_util.o"
+AC_LIBREPLACE_NETWORK_CHECKS
+
+SMB_ENABLE(TEVENT_EPOLL, NO)
+SMB_ENABLE(TEVENT_AIO, NO)
+AC_CHECK_HEADERS(sys/epoll.h)
+AC_CHECK_FUNCS(epoll_create)
+if test x"$ac_cv_header_sys_epoll_h" = x"yes" -a x"$ac_cv_func_epoll_create" = x"yes"; then
+ TEVENT_OBJ="$TEVENT_OBJ tevent_epoll.o"
+ SMB_ENABLE(TEVENT_EPOLL,YES)
+ AC_DEFINE(HAVE_EPOLL, 1, [Whether epoll available])
+ #TODO: remove HAVE_EVENTS_EPOLL and use HAVE_EPOLL
+ AC_DEFINE(HAVE_EVENTS_EPOLL, 1, [Whether epoll available])
+
+ # check for native Linux AIO interface
+ AC_CHECK_HEADERS(libaio.h)
+ AC_CHECK_LIB_EXT(aio, AIO_LIBS, io_getevents)
+ if test x"$ac_cv_header_libaio_h" = x"yes" -a x"$ac_cv_lib_ext_aio_io_getevents" = x"yes";then
+ TEVENT_OBJ="$TEVENT_OBJ tevent_aio.o"
+ SMB_ENABLE(TEVENT_AIO,YES)
+ AC_DEFINE(HAVE_LINUX_AIO, 1, [Whether Linux AIO is available])
+ fi
+fi
+
+AC_SUBST(TEVENT_OBJ)
+SMB_EXT_LIB(LIBAIO_LINUX, $AIO_LIBS)
+
+TEVENT_CFLAGS="-I$teventdir"
+AC_SUBST(TEVENT_CFLAGS)
+
+TEVENT_LIBS="$AIO_LIBS"
+AC_SUBST(TEVENT_LIBS)
+
+
diff --git a/lib/tevent/pkg.m4 b/lib/tevent/pkg.m4
new file mode 100644
index 0000000000..a8b3d06c81
--- /dev/null
+++ b/lib/tevent/pkg.m4
@@ -0,0 +1,156 @@
+# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
+#
+# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
+#
+# This program 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.
+#
+# This program 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/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# PKG_PROG_PKG_CONFIG([MIN-VERSION])
+# ----------------------------------
+AC_DEFUN([PKG_PROG_PKG_CONFIG],
+[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
+m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+ AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+fi
+if test -n "$PKG_CONFIG"; then
+ _pkg_min_version=m4_default([$1], [0.9.0])
+ AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
+ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ PKG_CONFIG=""
+ fi
+
+fi[]dnl
+])# PKG_PROG_PKG_CONFIG
+
+# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#
+# Check to see whether a particular set of modules exists. Similar
+# to PKG_CHECK_MODULES(), but does not set variables or print errors.
+#
+#
+# Similar to PKG_CHECK_MODULES, make sure that the first instance of
+# this or PKG_CHECK_MODULES is called, or make sure to call
+# PKG_CHECK_EXISTS manually
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_EXISTS],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+if test -n "$PKG_CONFIG" && \
+ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
+ m4_ifval([$2], [$2], [:])
+m4_ifvaln([$3], [else
+ $3])dnl
+fi])
+
+
+# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+# ---------------------------------------------
+m4_define([_PKG_CONFIG],
+[if test -n "$PKG_CONFIG"; then
+ if test -n "$$1"; then
+ pkg_cv_[]$1="$$1"
+ else
+ PKG_CHECK_EXISTS([$3],
+ [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
+ [pkg_failed=yes])
+ fi
+else
+ pkg_failed=untried
+fi[]dnl
+])# _PKG_CONFIG
+
+# _PKG_SHORT_ERRORS_SUPPORTED
+# -----------------------------
+AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi[]dnl
+])# _PKG_SHORT_ERRORS_SUPPORTED
+
+
+# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+# [ACTION-IF-NOT-FOUND])
+#
+#
+# Note that if there is a possibility the first call to
+# PKG_CHECK_MODULES might not happen, you should be sure to include an
+# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
+#
+#
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_MODULES],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
+AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
+
+pkg_failed=no
+AC_MSG_CHECKING([for $1])
+
+_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
+_PKG_CONFIG([$1][_LIBS], [libs], [$2])
+
+m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
+and $1[]_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.])
+
+if test $pkg_failed = yes; then
+ _PKG_SHORT_ERRORS_SUPPORTED
+ if test $_pkg_short_errors_supported = yes; then
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"`
+ else
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
+
+ ifelse([$4], , [AC_MSG_ERROR(dnl
+[Package requirements ($2) were not met:
+
+$$1_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+_PKG_TEXT
+])],
+ [AC_MSG_RESULT([no])
+ $4])
+elif test $pkg_failed = untried; then
+ ifelse([$4], , [AC_MSG_FAILURE(dnl
+[The pkg-config script could not be found or is too old. Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+_PKG_TEXT
+
+To get pkg-config, see <http://www.freedesktop.org/software/pkgconfig>.])],
+ [$4])
+else
+ $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
+ $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
+ AC_MSG_RESULT([yes])
+ ifelse([$3], , :, [$3])
+fi[]dnl
+])# PKG_CHECK_MODULES
diff --git a/lib/tevent/rules.mk b/lib/tevent/rules.mk
new file mode 100644
index 0000000000..cfe548039b
--- /dev/null
+++ b/lib/tevent/rules.mk
@@ -0,0 +1,21 @@
+.SUFFIXES: .i _wrap.c
+
+.i_wrap.c:
+ $(SWIG) -O -Wall -python -keyword $<
+
+showflags::
+ @echo 'libevents will be compiled with flags:'
+ @echo ' CFLAGS = $(CFLAGS)'
+ @echo ' CPPFLAGS = $(CPPFLAGS)'
+ @echo ' LDFLAGS = $(LDFLAGS)'
+ @echo ' LIBS = $(LIBS)'
+
+.SUFFIXES: .c .o
+
+.c.o:
+ @echo Compiling $*.c
+ @mkdir -p `dirname $@`
+ @$(CC) $(PICFLAG) $(CFLAGS) -c $< -o $@
+
+distclean::
+ rm -f *~ */*~
diff --git a/lib/tevent/tests.py b/lib/tevent/tests.py
new file mode 100644
index 0000000000..006426207e
--- /dev/null
+++ b/lib/tevent/tests.py
@@ -0,0 +1,31 @@
+#!/usr/bin/python
+
+# Unix SMB/CIFS implementation.
+# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
+#
+# This program 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.
+#
+# This program 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/>.
+#
+
+from samba import events
+import unittest
+
+# Just test the bindings are there and that calling them doesn't crash
+# anything.
+
+class EventTestCase(unittest.TestCase):
+ def test_create(self):
+ self.assertTrue(events.event() is not None)
+
+ def test_loop_wait(self):
+ self.assertEquals(0, events.event().loop_wait())
diff --git a/lib/tevent/testsuite.c b/lib/tevent/testsuite.c
new file mode 100644
index 0000000000..7f2729ceff
--- /dev/null
+++ b/lib/tevent/testsuite.c
@@ -0,0 +1,145 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ testing of the events subsystem
+
+ Copyright (C) Stefan Metzmacher
+
+ This program 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.
+
+ This program 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 "includes.h"
+#include "lib/events/events.h"
+#include "system/filesys.h"
+#include "torture/torture.h"
+
+static int fde_count;
+
+static void fde_handler(struct event_context *ev_ctx, struct fd_event *f,
+ uint16_t flags, void *private)
+{
+ int *fd = (int *)private;
+ char c;
+#ifdef SA_SIGINFO
+ kill(getpid(), SIGUSR1);
+#endif
+ kill(getpid(), SIGALRM);
+ read(fd[0], &c, 1);
+ write(fd[1], &c, 1);
+ fde_count++;
+}
+
+static void finished_handler(struct event_context *ev_ctx, struct timed_event *te,
+ struct timeval tval, void *private)
+{
+ int *finished = (int *)private;
+ (*finished) = 1;
+}
+
+static void count_handler(struct event_context *ev_ctx, struct signal_event *te,
+ int signum, int count, void *info, void *private)
+{
+ int *countp = (int *)private;
+ (*countp) += count;
+}
+
+static bool test_event_context(struct torture_context *test,
+ const void *test_data)
+{
+ struct event_context *ev_ctx;
+ int fd[2] = { -1, -1 };
+ const char *backend = (const char *)test_data;
+ int alarm_count=0, info_count=0;
+ struct fd_event *fde;
+ struct signal_event *se1, *se2, *se3;
+ int finished=0;
+ struct timeval t;
+ char c = 0;
+
+ ev_ctx = event_context_init_byname(test, backend);
+ if (ev_ctx == NULL) {
+ torture_comment(test, "event backend '%s' not supported\n", backend);
+ return true;
+ }
+
+ torture_comment(test, "Testing event backend '%s'\n", backend);
+
+ /* reset globals */
+ fde_count = 0;
+
+ /* create a pipe */
+ pipe(fd);
+
+ fde = event_add_fd(ev_ctx, ev_ctx, fd[0], EVENT_FD_READ|EVENT_FD_AUTOCLOSE,
+ fde_handler, fd);
+
+ event_add_timed(ev_ctx, ev_ctx, timeval_current_ofs(2,0),
+ finished_handler, &finished);
+
+ se1 = event_add_signal(ev_ctx, ev_ctx, SIGALRM, SA_RESTART, count_handler, &alarm_count);
+ se2 = event_add_signal(ev_ctx, ev_ctx, SIGALRM, SA_RESETHAND, count_handler, &alarm_count);
+#ifdef SA_SIGINFO
+ se3 = event_add_signal(ev_ctx, ev_ctx, SIGUSR1, SA_SIGINFO, count_handler, &info_count);
+#endif
+
+ write(fd[1], &c, 1);
+
+ t = timeval_current();
+ while (!finished) {
+ errno = 0;
+ if (event_loop_once(ev_ctx) == -1) {
+ talloc_free(ev_ctx);
+ torture_fail(test, talloc_asprintf(test, "Failed event loop %s\n", strerror(errno)));
+ }
+ }
+
+ talloc_free(fde);
+ close(fd[1]);
+
+ while (alarm_count < fde_count+1) {
+ if (event_loop_once(ev_ctx) == -1) {
+ break;
+ }
+ }
+
+ torture_comment(test, "Got %.2f pipe events/sec\n", fde_count/timeval_elapsed(&t));
+
+ talloc_free(se1);
+
+ torture_assert_int_equal(test, alarm_count, 1+fde_count, "alarm count mismatch");
+
+#ifdef SA_SIGINFO
+ talloc_free(se3);
+ torture_assert_int_equal(test, info_count, fde_count, "info count mismatch");
+#endif
+
+ talloc_free(ev_ctx);
+
+ return true;
+}
+
+struct torture_suite *torture_local_event(TALLOC_CTX *mem_ctx)
+{
+ struct torture_suite *suite = torture_suite_create(mem_ctx, "EVENT");
+ const char **list = event_backend_list(suite);
+ int i;
+
+ for (i=0;list && list[i];i++) {
+ torture_suite_add_simple_tcase_const(suite, list[i],
+ test_event_context,
+ (const void *)list[i]);
+ }
+
+ return suite;
+}
diff --git a/lib/tevent/tevent.c b/lib/tevent/tevent.c
new file mode 100644
index 0000000000..cd470c93ae
--- /dev/null
+++ b/lib/tevent/tevent.c
@@ -0,0 +1,310 @@
+/*
+ Unix SMB/CIFS implementation.
+ main select loop and event handling
+ Copyright (C) Andrew Tridgell 2003
+
+ This program 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.
+
+ This program 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/>.
+*/
+
+/*
+ PLEASE READ THIS BEFORE MODIFYING!
+
+ This module is a general abstraction for the main select loop and
+ event handling. Do not ever put any localised hacks in here, instead
+ register one of the possible event types and implement that event
+ somewhere else.
+
+ There are 2 types of event handling that are handled in this module:
+
+ 1) a file descriptor becoming readable or writeable. This is mostly
+ used for network sockets, but can be used for any type of file
+ descriptor. You may only register one handler for each file
+ descriptor/io combination or you will get unpredictable results
+ (this means that you can have a handler for read events, and a
+ separate handler for write events, but not two handlers that are
+ both handling read events)
+
+ 2) a timed event. You can register an event that happens at a
+ specific time. You can register as many of these as you
+ like. They are single shot - add a new timed event in the event
+ handler to get another event.
+
+ To setup a set of events you first need to create a event_context
+ structure using the function event_context_init(); This returns a
+ 'struct event_context' that you use in all subsequent calls.
+
+ After that you can add/remove events that you are interested in
+ using event_add_*() and talloc_free()
+
+ Finally, you call event_loop_wait_once() to block waiting for one of the
+ events to occor or event_loop_wait() which will loop
+ forever.
+
+*/
+#include "replace.h"
+#include "tevent.h"
+#include "tevent_internal.h"
+#include "tevent_util.h"
+
+struct event_ops_list {
+ struct event_ops_list *next, *prev;
+ const char *name;
+ const struct event_ops *ops;
+};
+
+/* list of registered event backends */
+static struct event_ops_list *event_backends = NULL;
+static char *event_default_backend = NULL;
+
+/*
+ register an events backend
+*/
+bool event_register_backend(const char *name, const struct event_ops *ops)
+{
+ struct event_ops_list *e;
+
+ for (e = event_backends; e != NULL; e = e->next) {
+ if (0 == strcmp(e->name, name)) {
+ /* already registered, skip it */
+ return true;
+ }
+ }
+
+ e = talloc(talloc_autofree_context(), struct event_ops_list);
+ if (e == NULL) return false;
+
+ e->name = name;
+ e->ops = ops;
+ DLIST_ADD(event_backends, e);
+
+ return true;
+}
+
+/*
+ set the default event backend
+ */
+void event_set_default_backend(const char *backend)
+{
+ if (event_default_backend) free(event_default_backend);
+ event_default_backend = strdup(backend);
+}
+
+/*
+ initialise backends if not already done
+*/
+static void event_backend_init(void)
+{
+ events_select_init();
+ events_standard_init();
+#if HAVE_EVENTS_EPOLL
+ events_epoll_init();
+#endif
+#if HAVE_LINUX_AIO
+ events_aio_init();
+#endif
+}
+
+/*
+ list available backends
+*/
+const char **event_backend_list(TALLOC_CTX *mem_ctx)
+{
+ const char **list = NULL;
+ struct event_ops_list *e;
+
+ event_backend_init();
+
+ for (e=event_backends;e;e=e->next) {
+ list = ev_str_list_add(list, e->name);
+ }
+
+ talloc_steal(mem_ctx, list);
+
+ return list;
+}
+
+/*
+ create a event_context structure for a specific implemementation.
+ This must be the first events call, and all subsequent calls pass
+ this event_context as the first element. Event handlers also
+ receive this as their first argument.
+
+ This function is for allowing third-party-applications to hook in gluecode
+ to their own event loop code, so that they can make async usage of our client libs
+
+ NOTE: use event_context_init() inside of samba!
+*/
+static struct event_context *event_context_init_ops(TALLOC_CTX *mem_ctx,
+ const struct event_ops *ops)
+{
+ struct event_context *ev;
+ int ret;
+
+ ev = talloc_zero(mem_ctx, struct event_context);
+ if (!ev) return NULL;
+
+ ev->ops = ops;
+
+ ret = ev->ops->context_init(ev);
+ if (ret != 0) {
+ talloc_free(ev);
+ return NULL;
+ }
+
+ return ev;
+}
+
+/*
+ create a event_context structure. This must be the first events
+ call, and all subsequent calls pass this event_context as the first
+ element. Event handlers also receive this as their first argument.
+*/
+struct event_context *event_context_init_byname(TALLOC_CTX *mem_ctx, const char *name)
+{
+ struct event_ops_list *e;
+
+ event_backend_init();
+
+ if (name == NULL) {
+ name = event_default_backend;
+ }
+ if (name == NULL) {
+ name = "standard";
+ }
+
+ for (e=event_backends;e;e=e->next) {
+ if (strcmp(name, e->name) == 0) {
+ return event_context_init_ops(mem_ctx, e->ops);
+ }
+ }
+ return NULL;
+}
+
+
+/*
+ create a event_context structure. This must be the first events
+ call, and all subsequent calls pass this event_context as the first
+ element. Event handlers also receive this as their first argument.
+*/
+struct event_context *event_context_init(TALLOC_CTX *mem_ctx)
+{
+ return event_context_init_byname(mem_ctx, NULL);
+}
+
+/*
+ add a fd based event
+ return NULL on failure (memory allocation error)
+
+ if flags contains EVENT_FD_AUTOCLOSE then the fd will be closed when
+ the returned fd_event context is freed
+*/
+struct fd_event *event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx,
+ int fd, uint16_t flags, event_fd_handler_t handler,
+ void *private_data)
+{
+ return ev->ops->add_fd(ev, mem_ctx, fd, flags, handler, private_data);
+}
+
+/*
+ add a disk aio event
+*/
+struct aio_event *event_add_aio(struct event_context *ev,
+ TALLOC_CTX *mem_ctx,
+ struct iocb *iocb,
+ event_aio_handler_t handler,
+ void *private_data)
+{
+ if (ev->ops->add_aio == NULL) return NULL;
+ return ev->ops->add_aio(ev, mem_ctx, iocb, handler, private_data);
+}
+
+/*
+ return the fd event flags
+*/
+uint16_t event_get_fd_flags(struct fd_event *fde)
+{
+ if (!fde) return 0;
+ return fde->event_ctx->ops->get_fd_flags(fde);
+}
+
+/*
+ set the fd event flags
+*/
+void event_set_fd_flags(struct fd_event *fde, uint16_t flags)
+{
+ if (!fde) return;
+ fde->event_ctx->ops->set_fd_flags(fde, flags);
+}
+
+/*
+ add a timed event
+ return NULL on failure
+*/
+struct timed_event *event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ctx,
+ struct timeval next_event,
+ event_timed_handler_t handler,
+ void *private_data)
+{
+ return ev->ops->add_timed(ev, mem_ctx, next_event, handler, private_data);
+}
+
+/*
+ add a signal event
+
+ sa_flags are flags to sigaction(2)
+
+ return NULL on failure
+*/
+struct signal_event *event_add_signal(struct event_context *ev, TALLOC_CTX *mem_ctx,
+ int signum,
+ int sa_flags,
+ event_signal_handler_t handler,
+ void *private_data)
+{
+ return ev->ops->add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data);
+}
+
+/*
+ do a single event loop using the events defined in ev
+*/
+int event_loop_once(struct event_context *ev)
+{
+ return ev->ops->loop_once(ev);
+}
+
+/*
+ return on failure or (with 0) if all fd events are removed
+*/
+int event_loop_wait(struct event_context *ev)
+{
+ return ev->ops->loop_wait(ev);
+}
+
+/*
+ find an event context that is a parent of the given memory context,
+ or create a new event context as a child of the given context if
+ none is found
+
+ This should be used in preference to event_context_init() in places
+ where you would prefer to use the existing event context if possible
+ (which is most situations)
+*/
+struct event_context *event_context_find(TALLOC_CTX *mem_ctx)
+{
+ struct event_context *ev = talloc_find_parent_bytype(mem_ctx, struct event_context);
+ if (ev == NULL) {
+ ev = event_context_init(mem_ctx);
+ }
+ return ev;
+}
diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h
new file mode 100644
index 0000000000..1857f9bb10
--- /dev/null
+++ b/lib/tevent/tevent.h
@@ -0,0 +1,98 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ generalised event loop handling
+
+ Copyright (C) Andrew Tridgell 2005
+
+ This program 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.
+
+ This program 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/>.
+*/
+
+#ifndef __TEVENT_H__
+#define __TEVENT_H__
+
+#include <stdint.h>
+#include <talloc.h>
+
+struct event_context;
+struct event_ops;
+struct fd_event;
+struct timed_event;
+struct aio_event;
+struct signal_event;
+
+/* event handler types */
+typedef void (*event_fd_handler_t)(struct event_context *, struct fd_event *,
+ uint16_t , void *);
+typedef void (*event_timed_handler_t)(struct event_context *, struct timed_event *,
+ struct timeval , void *);
+typedef void (*event_signal_handler_t)(struct event_context *, struct signal_event *,
+ int , int, void *, void *);
+typedef void (*event_aio_handler_t)(struct event_context *, struct aio_event *,
+ int, void *);
+
+#ifdef _SAMBA_BUILD_
+struct event_context *s4_event_context_init(TALLOC_CTX *mem_ctx);
+#endif
+
+struct event_context *event_context_init(TALLOC_CTX *mem_ctx);
+struct event_context *event_context_init_byname(TALLOC_CTX *mem_ctx, const char *name);
+const char **event_backend_list(TALLOC_CTX *mem_ctx);
+void event_set_default_backend(const char *backend);
+
+struct fd_event *event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx,
+ int fd, uint16_t flags, event_fd_handler_t handler,
+ void *private_data);
+
+struct timed_event *event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ctx,
+ struct timeval next_event,
+ event_timed_handler_t handler,
+ void *private_data);
+
+struct signal_event *event_add_signal(struct event_context *ev, TALLOC_CTX *mem_ctx,
+ int signum, int sa_flags,
+ event_signal_handler_t handler,
+ void *private_data);
+
+struct iocb;
+struct aio_event *event_add_aio(struct event_context *ev,
+ TALLOC_CTX *mem_ctx,
+ struct iocb *iocb,
+ event_aio_handler_t handler,
+ void *private_data);
+
+int event_loop_once(struct event_context *ev);
+int event_loop_wait(struct event_context *ev);
+
+uint16_t event_get_fd_flags(struct fd_event *fde);
+void event_set_fd_flags(struct fd_event *fde, uint16_t flags);
+
+struct event_context *event_context_find(TALLOC_CTX *mem_ctx);
+
+/* bits for file descriptor event flags */
+#define EVENT_FD_READ 1
+#define EVENT_FD_WRITE 2
+#define EVENT_FD_AUTOCLOSE 4
+
+#define EVENT_FD_WRITEABLE(fde) \
+ event_set_fd_flags(fde, event_get_fd_flags(fde) | EVENT_FD_WRITE)
+#define EVENT_FD_READABLE(fde) \
+ event_set_fd_flags(fde, event_get_fd_flags(fde) | EVENT_FD_READ)
+
+#define EVENT_FD_NOT_WRITEABLE(fde) \
+ event_set_fd_flags(fde, event_get_fd_flags(fde) & ~EVENT_FD_WRITE)
+#define EVENT_FD_NOT_READABLE(fde) \
+ event_set_fd_flags(fde, event_get_fd_flags(fde) & ~EVENT_FD_READ)
+
+#endif /* __TEVENT_H__ */
diff --git a/lib/tevent/tevent.mk b/lib/tevent/tevent.mk
new file mode 100644
index 0000000000..2bc6221689
--- /dev/null
+++ b/lib/tevent/tevent.mk
@@ -0,0 +1,59 @@
+
+EVENTS_SONAME = libevents.$(SHLIBEXT).0
+EVENTS_SOLIB = libevents.$(SHLIBEXT).$(PACKAGE_VERSION)
+
+libevents.a: $(EVENTS_OBJ)
+ ar -rv libevents.a $(EVENTS_OBJ)
+
+libevents.$(SHLIBEXT): $(EVENTS_SOLIB)
+ ln -fs $< $@
+
+$(EVENTS_SONAME): $(EVENTS_SOLIB)
+ ln -fs $< $@
+
+dirs::
+ @mkdir -p lib
+
+installdirs::
+ mkdir -p $(DESTDIR)$(includedir)
+ mkdir -p $(DESTDIR)$(libdir)
+ mkdir -p $(DESTDIR)$(libdir)/pkgconfig
+
+installheaders:: installdirs
+ cp $(srcdir)/events.h $(DESTDIR)$(includedir)
+
+installlibs:: installdirs
+ cp events.pc $(DESTDIR)$(libdir)/pkgconfig
+ cp libevents.a $(EVENTS_SOLIB) $(DESTDIR)$(libdir)
+
+install:: all installdirs installheaders installlibs $(PYTHON_INSTALL_TARGET)
+
+clean::
+ rm -f $(EVENTS_SONAME) $(EVENTS_SOLIB) libevents.a libevents.$(SHLIBEXT)
+ rm -f events.pc
+ rm -f _libevents.$(SHLIBEXT)
+
+
+#python stuff
+
+check-python:: build-python
+ $(LIB_PATH_VAR)=. PYTHONPATH=".:$(eventsdir)" $(PYTHON) $(eventsdir)/python/tests/simple.py
+
+install-swig::
+ mkdir -p $(DESTDIR)`$(SWIG) -swiglib`
+ cp events.i $(DESTDIR)`$(SWIG) -swiglib`
+
+build-python:: _libevents.$(SHLIBEXT)
+
+events_wrap.o: $(eventsdir)/events_wrap.c
+ $(CC) $(PICFLAG) -c $(eventsdir)/events_wrap.c $(CFLAGS) `$(PYTHON_CONFIG) --cflags`
+
+_libevents.$(SHLIBEXT): libevents.$(SHLIBEXT) events_wrap.o
+ $(SHLD) $(SHLD_FLAGS) -o $@ events_wrap.o -L. -levents `$(PYTHON_CONFIG) --libs`
+
+install-python:: build-python
+ mkdir -p $(DESTDIR)`$(PYTHON) -c "import distutils.sysconfig; print distutils.sysconfig.get_python_lib(0, prefix='$(prefix)')"` \
+ $(DESTDIR)`$(PYTHON) -c "import distutils.sysconfig; print distutils.sysconfig.get_python_lib(1, prefix='$(prefix)')"`
+ cp $(eventsdir)/events.py $(DESTDIR)`$(PYTHON) -c "import distutils.sysconfig; print distutils.sysconfig.get_python_lib(0, prefix='$(prefix)')"`
+ cp _libevents.$(SHLIBEXT) $(DESTDIR)`$(PYTHON) -c "import distutils.sysconfig; print distutils.sysconfig.get_python_lib(1, prefix='$(prefix)')"`
+
diff --git a/lib/tevent/tevent.pc.in b/lib/tevent/tevent.pc.in
new file mode 100644
index 0000000000..afd9fcc279
--- /dev/null
+++ b/lib/tevent/tevent.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: events
+Description: An event system library
+Version: @PACKAGE_VERSION@
+Libs: -L${libdir} -ltevent
+Cflags: -I${includedir}
+URL: http://samba.org/
diff --git a/lib/tevent/tevent_aio.c b/lib/tevent/tevent_aio.c
new file mode 100644
index 0000000000..7c3473b9a7
--- /dev/null
+++ b/lib/tevent/tevent_aio.c
@@ -0,0 +1,567 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ main select loop and event handling - aio/epoll hybrid implementation
+
+ Copyright (C) Andrew Tridgell 2006
+
+ based on events_standard.c
+
+ This program 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.
+
+ This program 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/>.
+*/
+/*
+ this is a very strange beast. The Linux AIO implementation doesn't
+ yet integrate properly with epoll, but there is a kernel patch that
+ allows the aio wait primitives to be used to wait for epoll events,
+ and this can be used to give us a unified event system incorporating
+ both aio events and epoll events
+
+ this is _very_ experimental code
+*/
+
+#include "system/filesys.h"
+#include "replace.h"
+#include "tevent.h"
+#include "tevent_internal.h"
+#include "tevent_util.h"
+#include <sys/epoll.h>
+#include <libaio.h>
+
+#define MAX_AIO_QUEUE_DEPTH 100
+#ifndef IOCB_CMD_EPOLL_WAIT
+#define IOCB_CMD_EPOLL_WAIT 9
+#endif
+
+struct aio_event_context {
+ /* a pointer back to the generic event_context */
+ struct event_context *ev;
+
+ /* list of filedescriptor events */
+ struct fd_event *fd_events;
+
+ /* number of registered fd event handlers */
+ int num_fd_events;
+
+ uint32_t destruction_count;
+
+ io_context_t ioctx;
+
+ struct epoll_event epevent[MAX_AIO_QUEUE_DEPTH];
+
+ struct iocb *epoll_iocb;
+
+ int epoll_fd;
+ int is_epoll_set;
+ pid_t pid;
+};
+
+struct aio_event {
+ struct event_context *event_ctx;
+ struct iocb iocb;
+ void *private_data;
+ event_aio_handler_t handler;
+};
+
+/*
+ map from EVENT_FD_* to EPOLLIN/EPOLLOUT
+*/
+static uint32_t epoll_map_flags(uint16_t flags)
+{
+ uint32_t ret = 0;
+ if (flags & EVENT_FD_READ) ret |= (EPOLLIN | EPOLLERR | EPOLLHUP);
+ if (flags & EVENT_FD_WRITE) ret |= (EPOLLOUT | EPOLLERR | EPOLLHUP);
+ return ret;
+}
+
+/*
+ free the epoll fd
+*/
+static int aio_ctx_destructor(struct aio_event_context *aio_ev)
+{
+ io_queue_release(aio_ev->ioctx);
+ close(aio_ev->epoll_fd);
+ aio_ev->epoll_fd = -1;
+ return 0;
+}
+
+static void epoll_add_event(struct aio_event_context *aio_ev, struct fd_event *fde);
+
+/*
+ reopen the epoll handle when our pid changes
+ see http://junkcode.samba.org/ftp/unpacked/junkcode/epoll_fork.c for an
+ demonstration of why this is needed
+ */
+static void epoll_check_reopen(struct aio_event_context *aio_ev)
+{
+ struct fd_event *fde;
+
+ if (aio_ev->pid == getpid()) {
+ return;
+ }
+
+ close(aio_ev->epoll_fd);
+ aio_ev->epoll_fd = epoll_create(MAX_AIO_QUEUE_DEPTH);
+ if (aio_ev->epoll_fd == -1) {
+ ev_debug(aio_ev->ev, EV_DEBUG_FATAL, "Failed to recreate epoll handle after fork\n");
+ return;
+ }
+ aio_ev->pid = getpid();
+ for (fde=aio_ev->fd_events;fde;fde=fde->next) {
+ epoll_add_event(aio_ev, fde);
+ }
+}
+
+#define EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT (1<<0)
+#define EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR (1<<1)
+#define EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR (1<<2)
+
+/*
+ add the epoll event to the given fd_event
+*/
+static void epoll_add_event(struct aio_event_context *aio_ev, struct fd_event *fde)
+{
+ struct epoll_event event;
+ if (aio_ev->epoll_fd == -1) return;
+
+ fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
+
+ /* if we don't want events yet, don't add an aio_event */
+ if (fde->flags == 0) return;
+
+ memset(&event, 0, sizeof(event));
+ event.events = epoll_map_flags(fde->flags);
+ event.data.ptr = fde;
+ epoll_ctl(aio_ev->epoll_fd, EPOLL_CTL_ADD, fde->fd, &event);
+ fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
+
+ /* only if we want to read we want to tell the event handler about errors */
+ if (fde->flags & EVENT_FD_READ) {
+ fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
+ }
+}
+
+/*
+ delete the epoll event for given fd_event
+*/
+static void epoll_del_event(struct aio_event_context *aio_ev, struct fd_event *fde)
+{
+ struct epoll_event event;
+
+ DLIST_REMOVE(aio_ev->fd_events, fde);
+
+ if (aio_ev->epoll_fd == -1) return;
+
+ fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
+
+ /* if there's no aio_event, we don't need to delete it */
+ if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT)) return;
+
+ ZERO_STRUCT(event);
+ event.events = epoll_map_flags(fde->flags);
+ event.data.ptr = fde;
+ epoll_ctl(aio_ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event);
+
+ fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
+}
+
+/*
+ change the epoll event to the given fd_event
+*/
+static void epoll_mod_event(struct aio_event_context *aio_ev, struct fd_event *fde)
+{
+ struct epoll_event event;
+ if (aio_ev->epoll_fd == -1) return;
+
+ fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
+
+ ZERO_STRUCT(event);
+ event.events = epoll_map_flags(fde->flags);
+ event.data.ptr = fde;
+ epoll_ctl(aio_ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event);
+
+ /* only if we want to read we want to tell the event handler about errors */
+ if (fde->flags & EVENT_FD_READ) {
+ fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
+ }
+}
+
+static void epoll_change_event(struct aio_event_context *aio_ev, struct fd_event *fde)
+{
+ bool got_error = (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR);
+ bool want_read = (fde->flags & EVENT_FD_READ);
+ bool want_write= (fde->flags & EVENT_FD_WRITE);
+
+ if (aio_ev->epoll_fd == -1) return;
+
+ fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
+
+ /* there's already an event */
+ if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT) {
+ if (want_read || (want_write && !got_error)) {
+ epoll_mod_event(aio_ev, fde);
+ return;
+ }
+ epoll_del_event(aio_ev, fde);
+ return;
+ }
+
+ /* there's no aio_event attached to the fde */
+ if (want_read || (want_write && !got_error)) {
+ DLIST_ADD(aio_ev->fd_events, fde);
+ epoll_add_event(aio_ev, fde);
+ return;
+ }
+}
+
+static int setup_epoll_wait(struct aio_event_context *aio_ev)
+{
+ if (aio_ev->is_epoll_set) {
+ return 0;
+ }
+ memset(aio_ev->epoll_iocb, 0, sizeof(*aio_ev->epoll_iocb));
+ aio_ev->epoll_iocb->aio_fildes = aio_ev->epoll_fd;
+ aio_ev->epoll_iocb->aio_lio_opcode = IOCB_CMD_EPOLL_WAIT;
+ aio_ev->epoll_iocb->aio_reqprio = 0;
+
+ aio_ev->epoll_iocb->u.c.nbytes = MAX_AIO_QUEUE_DEPTH;
+ aio_ev->epoll_iocb->u.c.offset = -1;
+ aio_ev->epoll_iocb->u.c.buf = aio_ev->epevent;
+
+ if (io_submit(aio_ev->ioctx, 1, &aio_ev->epoll_iocb) != 1) {
+ return -1;
+ }
+ aio_ev->is_epoll_set = 1;
+
+ return 0;
+}
+
+
+/*
+ event loop handling using aio/epoll hybrid
+*/
+static int aio_event_loop(struct aio_event_context *aio_ev, struct timeval *tvalp)
+{
+ int ret, i;
+ uint32_t destruction_count = ++aio_ev->destruction_count;
+ struct timespec timeout;
+ struct io_event events[8];
+
+ if (aio_ev->epoll_fd == -1) return -1;
+
+ if (aio_ev->ev->num_signal_handlers &&
+ common_event_check_signal(aio_ev->ev)) {
+ return 0;
+ }
+
+ if (tvalp) {
+ timeout.tv_sec = tvalp->tv_sec;
+ timeout.tv_nsec = tvalp->tv_usec;
+ timeout.tv_nsec *= 1000;
+ }
+
+ if (setup_epoll_wait(aio_ev) < 0)
+ return -1;
+
+ ret = io_getevents(aio_ev->ioctx, 1, 8,
+ events, tvalp?&timeout:NULL);
+
+ if (ret == -EINTR) {
+ if (aio_ev->ev->num_signal_handlers) {
+ common_event_check_signal(aio_ev->ev);
+ }
+ return 0;
+ }
+
+ if (ret == 0 && tvalp) {
+ /* we don't care about a possible delay here */
+ common_event_loop_timer_delay(aio_ev->ev);
+ return 0;
+ }
+
+ for (i=0;i<ret;i++) {
+ struct io_event *event = &events[i];
+ struct iocb *finished = event->obj;
+
+ switch (finished->aio_lio_opcode) {
+ case IO_CMD_PWRITE:
+ case IO_CMD_PREAD: {
+ struct aio_event *ae = talloc_get_type(finished->data,
+ struct aio_event);
+ if (ae) {
+ talloc_set_destructor(ae, NULL);
+ ae->handler(ae->event_ctx, ae,
+ event->res, ae->private_data);
+ talloc_free(ae);
+ }
+ break;
+ }
+ case IOCB_CMD_EPOLL_WAIT: {
+ struct epoll_event *ep = (struct epoll_event *)finished->u.c.buf;
+ struct fd_event *fde;
+ uint16_t flags = 0;
+ int j;
+
+ aio_ev->is_epoll_set = 0;
+
+ for (j=0; j<event->res; j++, ep++) {
+ fde = talloc_get_type(ep->data.ptr,
+ struct fd_event);
+ if (fde == NULL) {
+ return -1;
+ }
+ if (ep->events & (EPOLLHUP|EPOLLERR)) {
+ fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR;
+ if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR)) {
+ epoll_del_event(aio_ev, fde);
+ continue;
+ }
+ flags |= EVENT_FD_READ;
+ }
+ if (ep->events & EPOLLIN) flags |= EVENT_FD_READ;
+ if (ep->events & EPOLLOUT) flags |= EVENT_FD_WRITE;
+ if (flags) {
+ fde->handler(aio_ev->ev, fde, flags, fde->private_data);
+ }
+ }
+ break;
+ }
+ }
+ if (destruction_count != aio_ev->destruction_count) {
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ create a aio_event_context structure.
+*/
+static int aio_event_context_init(struct event_context *ev)
+{
+ struct aio_event_context *aio_ev;
+
+ aio_ev = talloc_zero(ev, struct aio_event_context);
+ if (!aio_ev) return -1;
+
+ aio_ev->ev = ev;
+ aio_ev->epoll_iocb = talloc(aio_ev, struct iocb);
+
+ if (io_queue_init(MAX_AIO_QUEUE_DEPTH, &aio_ev->ioctx) != 0) {
+ talloc_free(aio_ev);
+ return -1;
+ }
+
+ aio_ev->epoll_fd = epoll_create(MAX_AIO_QUEUE_DEPTH);
+ if (aio_ev->epoll_fd == -1) {
+ talloc_free(aio_ev);
+ return -1;
+ }
+ aio_ev->pid = getpid();
+
+ talloc_set_destructor(aio_ev, aio_ctx_destructor);
+
+ ev->additional_data = aio_ev;
+
+ if (setup_epoll_wait(aio_ev) < 0) {
+ talloc_free(aio_ev);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ destroy an fd_event
+*/
+static int aio_event_fd_destructor(struct fd_event *fde)
+{
+ struct event_context *ev = fde->event_ctx;
+ struct aio_event_context *aio_ev = talloc_get_type(ev->additional_data,
+ struct aio_event_context);
+
+ epoll_check_reopen(aio_ev);
+
+ aio_ev->num_fd_events--;
+ aio_ev->destruction_count++;
+
+ epoll_del_event(aio_ev, fde);
+
+ if (fde->flags & EVENT_FD_AUTOCLOSE) {
+ close(fde->fd);
+ fde->fd = -1;
+ }
+
+ return 0;
+}
+
+/*
+ add a fd based event
+ return NULL on failure (memory allocation error)
+*/
+static struct fd_event *aio_event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx,
+ int fd, uint16_t flags,
+ event_fd_handler_t handler,
+ void *private_data)
+{
+ struct aio_event_context *aio_ev = talloc_get_type(ev->additional_data,
+ struct aio_event_context);
+ struct fd_event *fde;
+
+ epoll_check_reopen(aio_ev);
+
+ fde = talloc(mem_ctx?mem_ctx:ev, struct fd_event);
+ if (!fde) return NULL;
+
+ fde->event_ctx = ev;
+ fde->fd = fd;
+ fde->flags = flags;
+ fde->handler = handler;
+ fde->private_data = private_data;
+ fde->additional_flags = 0;
+ fde->additional_data = NULL;
+
+ aio_ev->num_fd_events++;
+ talloc_set_destructor(fde, aio_event_fd_destructor);
+
+ DLIST_ADD(aio_ev->fd_events, fde);
+ epoll_add_event(aio_ev, fde);
+
+ return fde;
+}
+
+
+/*
+ return the fd event flags
+*/
+static uint16_t aio_event_get_fd_flags(struct fd_event *fde)
+{
+ return fde->flags;
+}
+
+/*
+ set the fd event flags
+*/
+static void aio_event_set_fd_flags(struct fd_event *fde, uint16_t flags)
+{
+ struct event_context *ev;
+ struct aio_event_context *aio_ev;
+
+ if (fde->flags == flags) return;
+
+ ev = fde->event_ctx;
+ aio_ev = talloc_get_type(ev->additional_data, struct aio_event_context);
+
+ fde->flags = flags;
+
+ epoll_check_reopen(aio_ev);
+
+ epoll_change_event(aio_ev, fde);
+}
+
+/*
+ do a single event loop using the events defined in ev
+*/
+static int aio_event_loop_once(struct event_context *ev)
+{
+ struct aio_event_context *aio_ev = talloc_get_type(ev->additional_data,
+ struct aio_event_context);
+ struct timeval tval;
+
+ tval = common_event_loop_timer_delay(ev);
+ if (ev_timeval_is_zero(&tval)) {
+ return 0;
+ }
+
+ epoll_check_reopen(aio_ev);
+
+ return aio_event_loop(aio_ev, &tval);
+}
+
+/*
+ return on failure or (with 0) if all fd events are removed
+*/
+static int aio_event_loop_wait(struct event_context *ev)
+{
+ struct aio_event_context *aio_ev = talloc_get_type(ev->additional_data,
+ struct aio_event_context);
+ while (aio_ev->num_fd_events) {
+ if (aio_event_loop_once(ev) != 0) {
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ called when a disk IO event needs to be cancelled
+*/
+static int aio_destructor(struct aio_event *ae)
+{
+ struct event_context *ev = ae->event_ctx;
+ struct aio_event_context *aio_ev = talloc_get_type(ev->additional_data,
+ struct aio_event_context);
+ struct io_event result;
+ io_cancel(aio_ev->ioctx, &ae->iocb, &result);
+ /* TODO: handle errors from io_cancel()! */
+ return 0;
+}
+
+/* submit an aio disk IO event */
+static struct aio_event *aio_event_add_aio(struct event_context *ev,
+ TALLOC_CTX *mem_ctx,
+ struct iocb *iocb,
+ event_aio_handler_t handler,
+ void *private_data)
+{
+ struct aio_event_context *aio_ev = talloc_get_type(ev->additional_data,
+ struct aio_event_context);
+ struct iocb *iocbp;
+ struct aio_event *ae = talloc(mem_ctx?mem_ctx:ev, struct aio_event);
+ if (ae == NULL) return NULL;
+
+ ae->event_ctx = ev;
+ ae->iocb = *iocb;
+ ae->handler = handler;
+ ae->private_data = private_data;
+ iocbp = &ae->iocb;
+
+ if (io_submit(aio_ev->ioctx, 1, &iocbp) != 1) {
+ talloc_free(ae);
+ return NULL;
+ }
+ ae->iocb.data = ae;
+ talloc_set_destructor(ae, aio_destructor);
+
+ return ae;
+}
+
+static const struct event_ops aio_event_ops = {
+ .context_init = aio_event_context_init,
+ .add_fd = aio_event_add_fd,
+ .add_aio = aio_event_add_aio,
+ .get_fd_flags = aio_event_get_fd_flags,
+ .set_fd_flags = aio_event_set_fd_flags,
+ .add_timed = common_event_add_timed,
+ .add_signal = common_event_add_signal,
+ .loop_once = aio_event_loop_once,
+ .loop_wait = aio_event_loop_wait,
+};
+
+bool events_aio_init(void)
+{
+ return event_register_backend("aio", &aio_event_ops);
+}
+
diff --git a/lib/tevent/tevent_debug.c b/lib/tevent/tevent_debug.c
new file mode 100644
index 0000000000..a23ff09755
--- /dev/null
+++ b/lib/tevent/tevent_debug.c
@@ -0,0 +1,83 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Copyright (C) Andrew Tridgell 2005
+ Copyright (C) Jelmer Vernooij 2005
+
+ This program 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.
+
+ This program 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 "replace.h"
+#include "tevent.h"
+#include "tevent_internal.h"
+
+/********************************************************************
+ * Debug wrapper functions, modeled (with lot's of code copied as is)
+ * after the ev debug wrapper functions
+ ********************************************************************/
+
+/*
+ this allows the user to choose their own debug function
+*/
+int ev_set_debug(struct event_context *ev,
+ void (*debug)(void *context, enum ev_debug_level level,
+ const char *fmt, va_list ap),
+ void *context)
+{
+ ev->debug_ops.debug = debug;
+ ev->debug_ops.context = context;
+ return 0;
+}
+
+/*
+ debug function for ev_set_debug_stderr
+*/
+void ev_debug_stderr(void *context, enum ev_debug_level level,
+ const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0);
+void ev_debug_stderr(void *context, enum ev_debug_level level,
+ const char *fmt, va_list ap)
+{
+ if (level <= EV_DEBUG_WARNING) {
+ vfprintf(stderr, fmt, ap);
+ }
+}
+
+/*
+ convenience function to setup debug messages on stderr
+ messages of level EV_DEBUG_WARNING and higher are printed
+*/
+int ev_set_debug_stderr(struct event_context *ev)
+{
+ return ev_set_debug(ev, ev_debug_stderr, ev);
+}
+
+/*
+ * log a message
+ *
+ * The default debug action is to ignore debugging messages.
+ * This is the most appropriate action for a library.
+ * Applications using the library must decide where to
+ * redirect debugging messages
+*/
+void ev_debug(struct event_context *ev, enum ev_debug_level level, const char *fmt, ...)
+{
+ va_list ap;
+ if (ev->debug_ops.debug == NULL) {
+ return;
+ }
+ va_start(ap, fmt);
+ ev->debug_ops.debug(ev->debug_ops.context, level, fmt, ap);
+ va_end(ap);
+}
+
diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c
new file mode 100644
index 0000000000..1d03b7dbf0
--- /dev/null
+++ b/lib/tevent/tevent_epoll.c
@@ -0,0 +1,482 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ main select loop and event handling - epoll implementation
+
+ Copyright (C) Andrew Tridgell 2003-2005
+ Copyright (C) Stefan Metzmacher 2005
+
+ This program 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.
+
+ This program 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 "replace.h"
+#include "system/filesys.h"
+#include "system/network.h"
+#include "tevent.h"
+#include "tevent_internal.h"
+#include "tevent_util.h"
+#include <sys/epoll.h>
+
+struct epoll_event_context {
+ /* a pointer back to the generic event_context */
+ struct event_context *ev;
+
+ /* list of filedescriptor events */
+ struct fd_event *fd_events;
+
+ /* number of registered fd event handlers */
+ int num_fd_events;
+
+ /* this is changed by the destructors for the fd event
+ type. It is used to detect event destruction by event
+ handlers, which means the code that is calling the event
+ handler needs to assume that the linked list is no longer
+ valid
+ */
+ uint32_t destruction_count;
+
+ /* when using epoll this is the handle from epoll_create */
+ int epoll_fd;
+
+ pid_t pid;
+};
+
+/*
+ called when a epoll call fails, and we should fallback
+ to using select
+*/
+static void epoll_panic(struct epoll_event_context *epoll_ev, const char *reason)
+{
+ ev_debug(epoll_ev->ev, EV_DEBUG_FATAL,
+ "%s (%s) - calling abort()\n", reason, strerror(errno));
+ abort();
+}
+
+/*
+ map from EVENT_FD_* to EPOLLIN/EPOLLOUT
+*/
+static uint32_t epoll_map_flags(uint16_t flags)
+{
+ uint32_t ret = 0;
+ if (flags & EVENT_FD_READ) ret |= (EPOLLIN | EPOLLERR | EPOLLHUP);
+ if (flags & EVENT_FD_WRITE) ret |= (EPOLLOUT | EPOLLERR | EPOLLHUP);
+ return ret;
+}
+
+/*
+ free the epoll fd
+*/
+static int epoll_ctx_destructor(struct epoll_event_context *epoll_ev)
+{
+ close(epoll_ev->epoll_fd);
+ epoll_ev->epoll_fd = -1;
+ return 0;
+}
+
+/*
+ init the epoll fd
+*/
+static int epoll_init_ctx(struct epoll_event_context *epoll_ev)
+{
+ epoll_ev->epoll_fd = epoll_create(64);
+ epoll_ev->pid = getpid();
+ talloc_set_destructor(epoll_ev, epoll_ctx_destructor);
+ if (epoll_ev->epoll_fd == -1) {
+ return -1;
+ }
+ return 0;
+}
+
+static void epoll_add_event(struct epoll_event_context *epoll_ev, struct fd_event *fde);
+
+/*
+ reopen the epoll handle when our pid changes
+ see http://junkcode.samba.org/ftp/unpacked/junkcode/epoll_fork.c for an
+ demonstration of why this is needed
+ */
+static void epoll_check_reopen(struct epoll_event_context *epoll_ev)
+{
+ struct fd_event *fde;
+
+ if (epoll_ev->pid == getpid()) {
+ return;
+ }
+
+ close(epoll_ev->epoll_fd);
+ epoll_ev->epoll_fd = epoll_create(64);
+ if (epoll_ev->epoll_fd == -1) {
+ ev_debug(epoll_ev->ev, EV_DEBUG_FATAL,
+ "Failed to recreate epoll handle after fork\n");
+ return;
+ }
+ epoll_ev->pid = getpid();
+ for (fde=epoll_ev->fd_events;fde;fde=fde->next) {
+ epoll_add_event(epoll_ev, fde);
+ }
+}
+
+#define EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT (1<<0)
+#define EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR (1<<1)
+#define EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR (1<<2)
+
+/*
+ add the epoll event to the given fd_event
+*/
+static void epoll_add_event(struct epoll_event_context *epoll_ev, struct fd_event *fde)
+{
+ struct epoll_event event;
+
+ if (epoll_ev->epoll_fd == -1) return;
+
+ fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
+
+ /* if we don't want events yet, don't add an epoll_event */
+ if (fde->flags == 0) return;
+
+ ZERO_STRUCT(event);
+ event.events = epoll_map_flags(fde->flags);
+ event.data.ptr = fde;
+ if (epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_ADD, fde->fd, &event) != 0) {
+ epoll_panic(epoll_ev, "EPOLL_CTL_ADD failed");
+ }
+ fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
+
+ /* only if we want to read we want to tell the event handler about errors */
+ if (fde->flags & EVENT_FD_READ) {
+ fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
+ }
+}
+
+/*
+ delete the epoll event for given fd_event
+*/
+static void epoll_del_event(struct epoll_event_context *epoll_ev, struct fd_event *fde)
+{
+ struct epoll_event event;
+
+ if (epoll_ev->epoll_fd == -1) return;
+
+ fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
+
+ /* if there's no epoll_event, we don't need to delete it */
+ if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT)) return;
+
+ ZERO_STRUCT(event);
+ event.events = epoll_map_flags(fde->flags);
+ event.data.ptr = fde;
+ if (epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event) != 0) {
+ ev_debug(epoll_ev->ev, EV_DEBUG_FATAL,
+ "epoll_del_event failed! probable early close bug (%s)\n",
+ strerror(errno));
+ }
+ fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
+}
+
+/*
+ change the epoll event to the given fd_event
+*/
+static void epoll_mod_event(struct epoll_event_context *epoll_ev, struct fd_event *fde)
+{
+ struct epoll_event event;
+ if (epoll_ev->epoll_fd == -1) return;
+
+ fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
+
+ ZERO_STRUCT(event);
+ event.events = epoll_map_flags(fde->flags);
+ event.data.ptr = fde;
+ if (epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event) != 0) {
+ epoll_panic(epoll_ev, "EPOLL_CTL_MOD failed");
+ }
+
+ /* only if we want to read we want to tell the event handler about errors */
+ if (fde->flags & EVENT_FD_READ) {
+ fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
+ }
+}
+
+static void epoll_change_event(struct epoll_event_context *epoll_ev, struct fd_event *fde)
+{
+ bool got_error = (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR);
+ bool want_read = (fde->flags & EVENT_FD_READ);
+ bool want_write= (fde->flags & EVENT_FD_WRITE);
+
+ if (epoll_ev->epoll_fd == -1) return;
+
+ fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
+
+ /* there's already an event */
+ if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT) {
+ if (want_read || (want_write && !got_error)) {
+ epoll_mod_event(epoll_ev, fde);
+ return;
+ }
+ /*
+ * if we want to match the select behavior, we need to remove the epoll_event
+ * when the caller isn't interested in events.
+ *
+ * this is because epoll reports EPOLLERR and EPOLLHUP, even without asking for them
+ */
+ epoll_del_event(epoll_ev, fde);
+ return;
+ }
+
+ /* there's no epoll_event attached to the fde */
+ if (want_read || (want_write && !got_error)) {
+ epoll_add_event(epoll_ev, fde);
+ return;
+ }
+}
+
+/*
+ event loop handling using epoll
+*/
+static int epoll_event_loop(struct epoll_event_context *epoll_ev, struct timeval *tvalp)
+{
+ int ret, i;
+#define MAXEVENTS 32
+ struct epoll_event events[MAXEVENTS];
+ uint32_t destruction_count = ++epoll_ev->destruction_count;
+ int timeout = -1;
+
+ if (epoll_ev->epoll_fd == -1) return -1;
+
+ if (tvalp) {
+ /* it's better to trigger timed events a bit later than to early */
+ timeout = ((tvalp->tv_usec+999) / 1000) + (tvalp->tv_sec*1000);
+ }
+
+ if (epoll_ev->ev->num_signal_handlers &&
+ common_event_check_signal(epoll_ev->ev)) {
+ return 0;
+ }
+
+ ret = epoll_wait(epoll_ev->epoll_fd, events, MAXEVENTS, timeout);
+
+ if (ret == -1 && errno == EINTR && epoll_ev->ev->num_signal_handlers) {
+ if (common_event_check_signal(epoll_ev->ev)) {
+ return 0;
+ }
+ }
+
+ if (ret == -1 && errno != EINTR) {
+ epoll_panic(epoll_ev, "epoll_wait() failed");
+ return -1;
+ }
+
+ if (ret == 0 && tvalp) {
+ /* we don't care about a possible delay here */
+ common_event_loop_timer_delay(epoll_ev->ev);
+ return 0;
+ }
+
+ for (i=0;i<ret;i++) {
+ struct fd_event *fde = talloc_get_type(events[i].data.ptr,
+ struct fd_event);
+ uint16_t flags = 0;
+
+ if (fde == NULL) {
+ epoll_panic(epoll_ev, "epoll_wait() gave bad data");
+ return -1;
+ }
+ if (events[i].events & (EPOLLHUP|EPOLLERR)) {
+ fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR;
+ /*
+ * if we only wait for EVENT_FD_WRITE, we should not tell the
+ * event handler about it, and remove the epoll_event,
+ * as we only report errors when waiting for read events,
+ * to match the select() behavior
+ */
+ if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR)) {
+ epoll_del_event(epoll_ev, fde);
+ continue;
+ }
+ flags |= EVENT_FD_READ;
+ }
+ if (events[i].events & EPOLLIN) flags |= EVENT_FD_READ;
+ if (events[i].events & EPOLLOUT) flags |= EVENT_FD_WRITE;
+ if (flags) {
+ fde->handler(epoll_ev->ev, fde, flags, fde->private_data);
+ if (destruction_count != epoll_ev->destruction_count) {
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*
+ create a epoll_event_context structure.
+*/
+static int epoll_event_context_init(struct event_context *ev)
+{
+ int ret;
+ struct epoll_event_context *epoll_ev;
+
+ epoll_ev = talloc_zero(ev, struct epoll_event_context);
+ if (!epoll_ev) return -1;
+ epoll_ev->ev = ev;
+ epoll_ev->epoll_fd = -1;
+
+ ret = epoll_init_ctx(epoll_ev);
+ if (ret != 0) {
+ talloc_free(epoll_ev);
+ return ret;
+ }
+
+ ev->additional_data = epoll_ev;
+ return 0;
+}
+
+/*
+ destroy an fd_event
+*/
+static int epoll_event_fd_destructor(struct fd_event *fde)
+{
+ struct event_context *ev = fde->event_ctx;
+ struct epoll_event_context *epoll_ev = talloc_get_type(ev->additional_data,
+ struct epoll_event_context);
+
+ epoll_check_reopen(epoll_ev);
+
+ epoll_ev->num_fd_events--;
+ epoll_ev->destruction_count++;
+
+ DLIST_REMOVE(epoll_ev->fd_events, fde);
+
+ epoll_del_event(epoll_ev, fde);
+
+ if (fde->flags & EVENT_FD_AUTOCLOSE) {
+ close(fde->fd);
+ fde->fd = -1;
+ }
+
+ return 0;
+}
+
+/*
+ add a fd based event
+ return NULL on failure (memory allocation error)
+*/
+static struct fd_event *epoll_event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx,
+ int fd, uint16_t flags,
+ event_fd_handler_t handler,
+ void *private_data)
+{
+ struct epoll_event_context *epoll_ev = talloc_get_type(ev->additional_data,
+ struct epoll_event_context);
+ struct fd_event *fde;
+
+ epoll_check_reopen(epoll_ev);
+
+ fde = talloc(mem_ctx?mem_ctx:ev, struct fd_event);
+ if (!fde) return NULL;
+
+ fde->event_ctx = ev;
+ fde->fd = fd;
+ fde->flags = flags;
+ fde->handler = handler;
+ fde->private_data = private_data;
+ fde->additional_flags = 0;
+ fde->additional_data = NULL;
+
+ epoll_ev->num_fd_events++;
+ talloc_set_destructor(fde, epoll_event_fd_destructor);
+
+ DLIST_ADD(epoll_ev->fd_events, fde);
+ epoll_add_event(epoll_ev, fde);
+
+ return fde;
+}
+
+
+/*
+ return the fd event flags
+*/
+static uint16_t epoll_event_get_fd_flags(struct fd_event *fde)
+{
+ return fde->flags;
+}
+
+/*
+ set the fd event flags
+*/
+static void epoll_event_set_fd_flags(struct fd_event *fde, uint16_t flags)
+{
+ struct event_context *ev;
+ struct epoll_event_context *epoll_ev;
+
+ if (fde->flags == flags) return;
+
+ ev = fde->event_ctx;
+ epoll_ev = talloc_get_type(ev->additional_data, struct epoll_event_context);
+
+ fde->flags = flags;
+
+ epoll_check_reopen(epoll_ev);
+
+ epoll_change_event(epoll_ev, fde);
+}
+
+/*
+ do a single event loop using the events defined in ev
+*/
+static int epoll_event_loop_once(struct event_context *ev)
+{
+ struct epoll_event_context *epoll_ev = talloc_get_type(ev->additional_data,
+ struct epoll_event_context);
+ struct timeval tval;
+
+ tval = common_event_loop_timer_delay(ev);
+ if (ev_timeval_is_zero(&tval)) {
+ return 0;
+ }
+
+ epoll_check_reopen(epoll_ev);
+
+ return epoll_event_loop(epoll_ev, &tval);
+}
+
+/*
+ return on failure or (with 0) if all fd events are removed
+*/
+static int epoll_event_loop_wait(struct event_context *ev)
+{
+ struct epoll_event_context *epoll_ev = talloc_get_type(ev->additional_data,
+ struct epoll_event_context);
+ while (epoll_ev->num_fd_events) {
+ if (epoll_event_loop_once(ev) != 0) {
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static const struct event_ops epoll_event_ops = {
+ .context_init = epoll_event_context_init,
+ .add_fd = epoll_event_add_fd,
+ .get_fd_flags = epoll_event_get_fd_flags,
+ .set_fd_flags = epoll_event_set_fd_flags,
+ .add_timed = common_event_add_timed,
+ .add_signal = common_event_add_signal,
+ .loop_once = epoll_event_loop_once,
+ .loop_wait = epoll_event_loop_wait,
+};
+
+bool events_epoll_init(void)
+{
+ return event_register_backend("epoll", &epoll_event_ops);
+}
diff --git a/lib/tevent/tevent_internal.h b/lib/tevent/tevent_internal.h
new file mode 100644
index 0000000000..0d0755f298
--- /dev/null
+++ b/lib/tevent/tevent_internal.h
@@ -0,0 +1,158 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ generalised event loop handling
+
+ Internal structs
+
+ Copyright (C) Stefan Metzmacher 2005
+
+ This program 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.
+
+ This program 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/>.
+*/
+
+struct event_ops {
+ /* conntext init */
+ int (*context_init)(struct event_context *ev);
+
+ /* fd_event functions */
+ struct fd_event *(*add_fd)(struct event_context *ev,
+ TALLOC_CTX *mem_ctx,
+ int fd, uint16_t flags,
+ event_fd_handler_t handler,
+ void *private_data);
+ uint16_t (*get_fd_flags)(struct fd_event *fde);
+ void (*set_fd_flags)(struct fd_event *fde, uint16_t flags);
+
+ /* timed_event functions */
+ struct timed_event *(*add_timed)(struct event_context *ev,
+ TALLOC_CTX *mem_ctx,
+ struct timeval next_event,
+ event_timed_handler_t handler,
+ void *private_data);
+ /* disk aio event functions */
+ struct aio_event *(*add_aio)(struct event_context *ev,
+ TALLOC_CTX *mem_ctx,
+ struct iocb *iocb,
+ event_aio_handler_t handler,
+ void *private_data);
+ /* signal functions */
+ struct signal_event *(*add_signal)(struct event_context *ev,
+ TALLOC_CTX *mem_ctx,
+ int signum, int sa_flags,
+ event_signal_handler_t handler,
+ void *private_data);
+
+ /* loop functions */
+ int (*loop_once)(struct event_context *ev);
+ int (*loop_wait)(struct event_context *ev);
+};
+
+struct fd_event {
+ struct fd_event *prev, *next;
+ struct event_context *event_ctx;
+ int fd;
+ uint16_t flags; /* see EVENT_FD_* flags */
+ event_fd_handler_t handler;
+ /* this is private for the specific handler */
+ void *private_data;
+ /* this is private for the events_ops implementation */
+ uint16_t additional_flags;
+ void *additional_data;
+};
+
+struct timed_event {
+ struct timed_event *prev, *next;
+ struct event_context *event_ctx;
+ struct timeval next_event;
+ event_timed_handler_t handler;
+ /* this is private for the specific handler */
+ void *private_data;
+ /* this is private for the events_ops implementation */
+ void *additional_data;
+};
+
+struct signal_event {
+ struct signal_event *prev, *next;
+ struct event_context *event_ctx;
+ event_signal_handler_t handler;
+ void *private_data;
+ int signum;
+ int sa_flags;
+};
+
+/* DEBUG */
+enum ev_debug_level {EV_DEBUG_FATAL, EV_DEBUG_ERROR,
+ EV_DEBUG_WARNING, EV_DEBUG_TRACE};
+
+struct ev_debug_ops {
+ void (*debug)(void *context, enum ev_debug_level level,
+ const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0);
+ void *context;
+};
+
+int ev_set_debug(struct event_context *ev,
+ void (*debug)(void *context, enum ev_debug_level level,
+ const char *fmt, va_list ap),
+ void *context);
+int ev_set_debug_stderr(struct event_context *ev);
+void ev_debug(struct event_context *ev, enum ev_debug_level level, const char *fmt, ...);
+
+/* aio event is private to the aio backend */
+struct aio_event;
+
+struct event_context {
+ /* the specific events implementation */
+ const struct event_ops *ops;
+
+ /* list of timed events - used by common code */
+ struct timed_event *timed_events;
+
+ /* this is private for the events_ops implementation */
+ void *additional_data;
+
+ /* number of signal event handlers */
+ int num_signal_handlers;
+
+ /* pipe hack used with signal handlers */
+ struct fd_event *pipe_fde;
+
+ /* debugging operations */
+ struct ev_debug_ops debug_ops;
+};
+
+
+bool event_register_backend(const char *name, const struct event_ops *ops);
+
+bool ev_timeval_is_zero(const struct timeval *tv);
+struct timed_event *common_event_add_timed(struct event_context *, TALLOC_CTX *,
+ struct timeval, event_timed_handler_t, void *);
+struct timeval common_event_loop_timer_delay(struct event_context *);
+
+struct signal_event *common_event_add_signal(struct event_context *ev,
+ TALLOC_CTX *mem_ctx,
+ int signum,
+ int sa_flags,
+ event_signal_handler_t handler,
+ void *private_data);
+int common_event_check_signal(struct event_context *ev);
+
+
+bool events_standard_init(void);
+bool events_select_init(void);
+#if HAVE_EVENTS_EPOLL
+bool events_epoll_init(void);
+#endif
+#if HAVE_LINUX_AIO
+bool events_aio_init(void);
+#endif
diff --git a/lib/tevent/tevent_liboop.c b/lib/tevent/tevent_liboop.c
new file mode 100644
index 0000000000..339297a3cf
--- /dev/null
+++ b/lib/tevent/tevent_liboop.c
@@ -0,0 +1,288 @@
+/*
+ Unix SMB/CIFS implementation.
+ main select loop and event handling
+ wrapper for http://liboop.org/
+
+ Copyright (C) Stefan Metzmacher 2005
+
+ This program 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.
+
+ This program 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 "events.h"
+#include "events_internal.h"
+
+#include <oop.h>
+
+/*
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+ NOTE: this code compiles fine, but is completly *UNTESTED*
+ and is only commited as example
+
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+*/
+
+static int oop_event_context_destructor(struct event_context *ev)
+{
+ oop_source_sys *oop_sys = ev->additional_data;
+
+ oop_sys_delete(oop_sys);
+
+ return 0;
+}
+
+/*
+ create a oop_event_context structure.
+*/
+static int oop_event_context_init(struct event_context *ev, void *private_data)
+{
+ oop_source_sys *oop_sys = private_data;
+
+ if (!oop_sys) {
+ oop_sys = oop_sys_new();
+ if (!oop_sys) {
+ return -1;
+ }
+
+ talloc_set_destructor(ev, oop_event_context_destructor);
+ }
+
+ ev->additional_data = oop_sys;
+
+ return 0;
+}
+
+static void *oop_event_fd_handler(oop_source *oop, int fd, oop_event oop_type, void *ptr)
+{
+ struct fd_event *fde = ptr;
+
+ if (fd != fde->fd) return OOP_ERROR;
+
+ switch(oop_type) {
+ case OOP_READ:
+ fde->handler(fde->event_ctx, fde, EVENT_FD_READ, fde->private_data);
+ return OOP_CONTINUE;
+ case OOP_WRITE:
+ fde->handler(fde->event_ctx, fde, EVENT_FD_WRITE, fde->private_data);
+ return OOP_CONTINUE;
+ case OOP_EXCEPTION:
+ return OOP_ERROR;
+ case OOP_NUM_EVENTS:
+ return OOP_ERROR;
+ }
+
+ return OOP_ERROR;
+}
+
+/*
+ destroy an fd_event
+*/
+static int oop_event_fd_destructor(struct fd_event *fde)
+{
+ struct event_context *ev = fde->event_ctx;
+ oop_source_sys *oop_sys = ev->additional_data;
+ oop_source *oop = oop_sys_source(oop_sys);
+
+ if (fde->flags & EVENT_FD_READ)
+ oop->cancel_fd(oop, fde->fd, OOP_READ);
+ if (fde->flags & EVENT_FD_WRITE)
+ oop->cancel_fd(oop, fde->fd, OOP_WRITE);
+
+ if (fde->flags & EVENT_FD_AUTOCLOSE) {
+ close(fde->fd);
+ fde->fd = -1;
+ }
+
+ return 0;
+}
+
+/*
+ add a fd based event
+ return NULL on failure (memory allocation error)
+*/
+static struct fd_event *oop_event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx,
+ int fd, uint16_t flags,
+ event_fd_handler_t handler,
+ void *private_data)
+{
+ struct fd_event *fde;
+ oop_source_sys *oop_sys = ev->additional_data;
+ oop_source *oop = oop_sys_source(oop_sys);
+
+ fde = talloc(mem_ctx?mem_ctx:ev, struct fd_event);
+ if (!fde) return NULL;
+
+ fde->event_ctx = ev;
+ fde->fd = fd;
+ fde->flags = flags;
+ fde->handler = handler;
+ fde->private_data = private_data;
+ fde->additional_flags = 0;
+ fde->additional_data = NULL;
+
+ if (fde->flags & EVENT_FD_READ)
+ oop->on_fd(oop, fde->fd, OOP_READ, oop_event_fd_handler, fde);
+ if (fde->flags & EVENT_FD_WRITE)
+ oop->on_fd(oop, fde->fd, OOP_WRITE, oop_event_fd_handler, fde);
+
+ talloc_set_destructor(fde, oop_event_fd_destructor);
+
+ return fde;
+}
+
+/*
+ return the fd event flags
+*/
+static uint16_t oop_event_get_fd_flags(struct fd_event *fde)
+{
+ return fde->flags;
+}
+
+/*
+ set the fd event flags
+*/
+static void oop_event_set_fd_flags(struct fd_event *fde, uint16_t flags)
+{
+ oop_source_sys *oop_sys;
+ oop_source *oop;
+
+ oop_sys = fde->event_ctx->additional_data;
+ oop = oop_sys_source(oop_sys);
+
+ if ((fde->flags & EVENT_FD_READ)&&(!(flags & EVENT_FD_READ)))
+ oop->cancel_fd(oop, fde->fd, OOP_READ);
+
+ if ((!(fde->flags & EVENT_FD_READ))&&(flags & EVENT_FD_READ))
+ oop->on_fd(oop, fde->fd, OOP_READ, oop_event_fd_handler, fde);
+
+ if ((fde->flags & EVENT_FD_WRITE)&&(!(flags & EVENT_FD_WRITE)))
+ oop->cancel_fd(oop, fde->fd, OOP_WRITE);
+
+ if ((!(fde->flags & EVENT_FD_WRITE))&&(flags & EVENT_FD_WRITE))
+ oop->on_fd(oop, fde->fd, OOP_WRITE, oop_event_fd_handler, fde);
+
+ fde->flags = flags;
+}
+
+static int oop_event_timed_destructor(struct timed_event *te);
+
+static int oop_event_timed_deny_destructor(struct timed_event *te)
+{
+ return -1;
+}
+
+static void *oop_event_timed_handler(oop_source *oop, struct timeval t, void *ptr)
+{
+ struct timed_event *te = ptr;
+
+ /* deny the handler to free the event */
+ talloc_set_destructor(te, oop_event_timed_deny_destructor);
+ te->handler(te->event_ctx, te, t, te->private_data);
+
+ talloc_set_destructor(te, oop_event_timed_destructor);
+ talloc_free(te);
+
+ return OOP_CONTINUE;
+}
+
+/*
+ destroy a timed event
+*/
+static int oop_event_timed_destructor(struct timed_event *te)
+{
+ struct event_context *ev = te->event_ctx;
+ oop_source_sys *oop_sys = ev->additional_data;
+ oop_source *oop = oop_sys_source(oop_sys);
+
+ oop->cancel_time(oop, te->next_event, oop_event_timed_handler, te);
+
+ return 0;
+}
+
+/*
+ add a timed event
+ return NULL on failure (memory allocation error)
+*/
+static struct timed_event *oop_event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ctx,
+ struct timeval next_event,
+ event_timed_handler_t handler,
+ void *private_data)
+{
+ oop_source_sys *oop_sys = ev->additional_data;
+ oop_source *oop = oop_sys_source(oop_sys);
+ struct timed_event *te;
+
+ te = talloc(mem_ctx?mem_ctx:ev, struct timed_event);
+ if (te == NULL) return NULL;
+
+ te->event_ctx = ev;
+ te->next_event = next_event;
+ te->handler = handler;
+ te->private_data = private_data;
+ te->additional_data = NULL;
+
+ oop->on_time(oop, te->next_event, oop_event_timed_handler, te);
+
+ talloc_set_destructor(te, oop_event_timed_destructor);
+
+ return te;
+}
+
+/*
+ do a single event loop using the events defined in ev
+*/
+static int oop_event_loop_once(struct event_context *ev)
+{
+ void *oop_ret;
+ oop_source_sys *oop_sys = ev->additional_data;
+
+ oop_ret = oop_sys_run_once(oop_sys);
+ if (oop_ret == OOP_CONTINUE) {
+ return 0;
+ }
+
+ return -1;
+}
+
+/*
+ return on failure or (with 0) if all fd events are removed
+*/
+static int oop_event_loop_wait(struct event_context *ev)
+{
+ void *oop_ret;
+ oop_source_sys *oop_sys = ev->additional_data;
+
+ oop_ret = oop_sys_run(oop_sys);
+ if (oop_ret == OOP_CONTINUE) {
+ return 0;
+ }
+
+ return -1;
+}
+
+static const struct event_ops event_oop_ops = {
+ .context_init = oop_event_context_init,
+ .add_fd = oop_event_add_fd,
+ .get_fd_flags = oop_event_get_fd_flags,
+ .set_fd_flags = oop_event_set_fd_flags,
+ .add_timed = oop_event_add_timed,
+ .add_signal = common_event_add_signal,
+ .loop_once = oop_event_loop_once,
+ .loop_wait = oop_event_loop_wait,
+};
+
+const struct event_ops *event_liboop_get_ops(void)
+{
+ return &event_oop_ops;
+}
diff --git a/lib/tevent/tevent_s4.c b/lib/tevent/tevent_s4.c
new file mode 100644
index 0000000000..4be92599a7
--- /dev/null
+++ b/lib/tevent/tevent_s4.c
@@ -0,0 +1,108 @@
+/*
+ Unix SMB/CIFS implementation.
+ Copyright (C) Andrew Tridgell 2003
+
+ This program 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.
+
+ This program 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 "includes.h"
+#include "tevent.h"
+#include "tevent_internal.h"
+
+NTSTATUS s4_events_standard_init(void)
+{
+ if (!events_standard_init()) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS s4_events_select_init(void)
+{
+ if (!events_select_init()) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+ return NT_STATUS_OK;
+}
+
+#if HAVE_EVENTS_EPOLL
+NTSTATUS s4_events_epoll_init(void)
+{
+ if (!events_epoll_init()) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+ return NT_STATUS_OK;
+}
+#endif
+
+#if HAVE_LINUX_AIO
+NTSTATUS s4_events_aio_init(void)
+{
+ if (!events_aio_init()) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+ return NT_STATUS_OK;
+}
+#endif
+
+/*
+ this is used to catch debug messages from events
+*/
+static void ev_wrap_debug(void *context, enum ev_debug_level level,
+ const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0);
+
+static void ev_wrap_debug(void *context, enum ev_debug_level level,
+ const char *fmt, va_list ap)
+{
+ int samba_level = -1;
+ char *s = NULL;
+ switch (level) {
+ case EV_DEBUG_FATAL:
+ samba_level = 0;
+ break;
+ case EV_DEBUG_ERROR:
+ samba_level = 1;
+ break;
+ case EV_DEBUG_WARNING:
+ samba_level = 2;
+ break;
+ case EV_DEBUG_TRACE:
+ samba_level = 5;
+ break;
+
+ };
+ vasprintf(&s, fmt, ap);
+ if (!s) return;
+ DEBUG(samba_level, ("events: %s\n", s));
+ free(s);
+}
+
+/*
+ create a event_context structure. This must be the first events
+ call, and all subsequent calls pass this event_context as the first
+ element. Event handlers also receive this as their first argument.
+
+ This samba4 specific call sets the samba4 debug handler.
+*/
+struct event_context *s4_event_context_init(TALLOC_CTX *mem_ctx)
+{
+ struct event_context *ev;
+
+ ev = event_context_init_byname(mem_ctx, NULL);
+ if (ev) {
+ ev_set_debug(ev, ev_wrap_debug, NULL);
+ }
+ return ev;
+}
+
diff --git a/lib/tevent/tevent_select.c b/lib/tevent/tevent_select.c
new file mode 100644
index 0000000000..35c6f78599
--- /dev/null
+++ b/lib/tevent/tevent_select.c
@@ -0,0 +1,302 @@
+/*
+ Unix SMB/CIFS implementation.
+ main select loop and event handling
+ Copyright (C) Andrew Tridgell 2003-2005
+ Copyright (C) Stefan Metzmacher 2005
+
+ This program 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.
+
+ This program 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/>.
+*/
+
+/*
+ This is SAMBA's default event loop code
+
+*/
+
+#include "replace.h"
+#include "system/filesys.h"
+#include "system/select.h"
+#include "tevent.h"
+#include "tevent_util.h"
+#include "tevent_internal.h"
+
+struct select_event_context {
+ /* a pointer back to the generic event_context */
+ struct event_context *ev;
+
+ /* list of filedescriptor events */
+ struct fd_event *fd_events;
+
+ /* list of timed events */
+ struct timed_event *timed_events;
+
+ /* the maximum file descriptor number in fd_events */
+ int maxfd;
+
+ /* information for exiting from the event loop */
+ int exit_code;
+
+ /* this is incremented when the loop over events causes something which
+ could change the events yet to be processed */
+ uint32_t destruction_count;
+};
+
+/*
+ create a select_event_context structure.
+*/
+static int select_event_context_init(struct event_context *ev)
+{
+ struct select_event_context *select_ev;
+
+ select_ev = talloc_zero(ev, struct select_event_context);
+ if (!select_ev) return -1;
+ select_ev->ev = ev;
+
+ ev->additional_data = select_ev;
+ return 0;
+}
+
+/*
+ recalculate the maxfd
+*/
+static void calc_maxfd(struct select_event_context *select_ev)
+{
+ struct fd_event *fde;
+
+ select_ev->maxfd = 0;
+ for (fde = select_ev->fd_events; fde; fde = fde->next) {
+ if (fde->fd > select_ev->maxfd) {
+ select_ev->maxfd = fde->fd;
+ }
+ }
+}
+
+
+/* to mark the ev->maxfd invalid
+ * this means we need to recalculate it
+ */
+#define EVENT_INVALID_MAXFD (-1)
+
+/*
+ destroy an fd_event
+*/
+static int select_event_fd_destructor(struct fd_event *fde)
+{
+ struct event_context *ev = fde->event_ctx;
+ struct select_event_context *select_ev = talloc_get_type(ev->additional_data,
+ struct select_event_context);
+
+ if (select_ev->maxfd == fde->fd) {
+ select_ev->maxfd = EVENT_INVALID_MAXFD;
+ }
+
+ DLIST_REMOVE(select_ev->fd_events, fde);
+ select_ev->destruction_count++;
+
+ if (fde->flags & EVENT_FD_AUTOCLOSE) {
+ close(fde->fd);
+ fde->fd = -1;
+ }
+
+ return 0;
+}
+
+/*
+ add a fd based event
+ return NULL on failure (memory allocation error)
+*/
+static struct fd_event *select_event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx,
+ int fd, uint16_t flags,
+ event_fd_handler_t handler,
+ void *private_data)
+{
+ struct select_event_context *select_ev = talloc_get_type(ev->additional_data,
+ struct select_event_context);
+ struct fd_event *fde;
+
+ fde = talloc(mem_ctx?mem_ctx:ev, struct fd_event);
+ if (!fde) return NULL;
+
+ fde->event_ctx = ev;
+ fde->fd = fd;
+ fde->flags = flags;
+ fde->handler = handler;
+ fde->private_data = private_data;
+ fde->additional_flags = 0;
+ fde->additional_data = NULL;
+
+ DLIST_ADD(select_ev->fd_events, fde);
+ if (fde->fd > select_ev->maxfd) {
+ select_ev->maxfd = fde->fd;
+ }
+ talloc_set_destructor(fde, select_event_fd_destructor);
+
+ return fde;
+}
+
+
+/*
+ return the fd event flags
+*/
+static uint16_t select_event_get_fd_flags(struct fd_event *fde)
+{
+ return fde->flags;
+}
+
+/*
+ set the fd event flags
+*/
+static void select_event_set_fd_flags(struct fd_event *fde, uint16_t flags)
+{
+ struct event_context *ev;
+ struct select_event_context *select_ev;
+
+ if (fde->flags == flags) return;
+
+ ev = fde->event_ctx;
+ select_ev = talloc_get_type(ev->additional_data, struct select_event_context);
+
+ fde->flags = flags;
+}
+
+/*
+ event loop handling using select()
+*/
+static int select_event_loop_select(struct select_event_context *select_ev, struct timeval *tvalp)
+{
+ fd_set r_fds, w_fds;
+ struct fd_event *fde;
+ int selrtn;
+ uint32_t destruction_count = ++select_ev->destruction_count;
+
+ /* we maybe need to recalculate the maxfd */
+ if (select_ev->maxfd == EVENT_INVALID_MAXFD) {
+ calc_maxfd(select_ev);
+ }
+
+ FD_ZERO(&r_fds);
+ FD_ZERO(&w_fds);
+
+ /* setup any fd events */
+ for (fde = select_ev->fd_events; fde; fde = fde->next) {
+ if (fde->flags & EVENT_FD_READ) {
+ FD_SET(fde->fd, &r_fds);
+ }
+ if (fde->flags & EVENT_FD_WRITE) {
+ FD_SET(fde->fd, &w_fds);
+ }
+ }
+
+ if (select_ev->ev->num_signal_handlers &&
+ common_event_check_signal(select_ev->ev)) {
+ return 0;
+ }
+
+ selrtn = select(select_ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp);
+
+ if (selrtn == -1 && errno == EINTR &&
+ select_ev->ev->num_signal_handlers) {
+ common_event_check_signal(select_ev->ev);
+ return 0;
+ }
+
+ if (selrtn == -1 && errno == EBADF) {
+ /* the socket is dead! this should never
+ happen as the socket should have first been
+ made readable and that should have removed
+ the event, so this must be a bug. This is a
+ fatal error. */
+ ev_debug(select_ev->ev, EV_DEBUG_FATAL,
+ "ERROR: EBADF on select_event_loop_once\n");
+ select_ev->exit_code = EBADF;
+ return -1;
+ }
+
+ if (selrtn == 0 && tvalp) {
+ /* we don't care about a possible delay here */
+ common_event_loop_timer_delay(select_ev->ev);
+ return 0;
+ }
+
+ if (selrtn > 0) {
+ /* at least one file descriptor is ready - check
+ which ones and call the handler, being careful to allow
+ the handler to remove itself when called */
+ for (fde = select_ev->fd_events; fde; fde = fde->next) {
+ uint16_t flags = 0;
+
+ if (FD_ISSET(fde->fd, &r_fds)) flags |= EVENT_FD_READ;
+ if (FD_ISSET(fde->fd, &w_fds)) flags |= EVENT_FD_WRITE;
+ if (flags) {
+ fde->handler(select_ev->ev, fde, flags, fde->private_data);
+ if (destruction_count != select_ev->destruction_count) {
+ break;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*
+ do a single event loop using the events defined in ev
+*/
+static int select_event_loop_once(struct event_context *ev)
+{
+ struct select_event_context *select_ev = talloc_get_type(ev->additional_data,
+ struct select_event_context);
+ struct timeval tval;
+
+ tval = common_event_loop_timer_delay(ev);
+ if (ev_timeval_is_zero(&tval)) {
+ return 0;
+ }
+
+ return select_event_loop_select(select_ev, &tval);
+}
+
+/*
+ return on failure or (with 0) if all fd events are removed
+*/
+static int select_event_loop_wait(struct event_context *ev)
+{
+ struct select_event_context *select_ev = talloc_get_type(ev->additional_data,
+ struct select_event_context);
+ select_ev->exit_code = 0;
+
+ while (select_ev->fd_events && select_ev->exit_code == 0) {
+ if (select_event_loop_once(ev) != 0) {
+ break;
+ }
+ }
+
+ return select_ev->exit_code;
+}
+
+static const struct event_ops select_event_ops = {
+ .context_init = select_event_context_init,
+ .add_fd = select_event_add_fd,
+ .get_fd_flags = select_event_get_fd_flags,
+ .set_fd_flags = select_event_set_fd_flags,
+ .add_timed = common_event_add_timed,
+ .add_signal = common_event_add_signal,
+ .loop_once = select_event_loop_once,
+ .loop_wait = select_event_loop_wait,
+};
+
+bool events_select_init(void)
+{
+ return event_register_backend("select", &select_event_ops);
+}
+
diff --git a/lib/tevent/tevent_signal.c b/lib/tevent/tevent_signal.c
new file mode 100644
index 0000000000..36907af6be
--- /dev/null
+++ b/lib/tevent/tevent_signal.c
@@ -0,0 +1,291 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ common events code for signal events
+
+ Copyright (C) Andrew Tridgell 2007
+
+ This program 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.
+
+ This program 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 <signal.h>
+#include "replace.h"
+#include "system/filesys.h"
+#include "system/select.h"
+#include "tevent.h"
+#include "tevent_internal.h"
+#include "tevent_util.h"
+
+#define NUM_SIGNALS 64
+
+/* maximum number of SA_SIGINFO signals to hold in the queue */
+#define SA_INFO_QUEUE_COUNT 10
+
+struct sigcounter {
+ uint32_t count;
+ uint32_t seen;
+};
+
+#define SIG_INCREMENT(s) (s).count++
+#define SIG_SEEN(s, n) (s).seen += (n)
+#define SIG_PENDING(s) ((s).seen != (s).count)
+
+
+/*
+ the poor design of signals means that this table must be static global
+*/
+static struct sig_state {
+ struct signal_event *sig_handlers[NUM_SIGNALS+1];
+ struct sigaction *oldact[NUM_SIGNALS+1];
+ struct sigcounter signal_count[NUM_SIGNALS+1];
+ struct sigcounter got_signal;
+ int pipe_hack[2];
+#ifdef SA_SIGINFO
+ /* with SA_SIGINFO we get quite a lot of info per signal */
+ siginfo_t *sig_info[NUM_SIGNALS+1];
+ struct sigcounter sig_blocked[NUM_SIGNALS+1];
+#endif
+} *sig_state;
+
+/*
+ return number of sigcounter events not processed yet
+*/
+static uint32_t sig_count(struct sigcounter s)
+{
+ if (s.count >= s.seen) {
+ return s.count - s.seen;
+ }
+ return 1 + (0xFFFFFFFF & ~(s.seen - s.count));
+}
+
+/*
+ signal handler - redirects to registered signals
+*/
+static void signal_handler(int signum)
+{
+ char c = 0;
+ SIG_INCREMENT(sig_state->signal_count[signum]);
+ SIG_INCREMENT(sig_state->got_signal);
+ /* doesn't matter if this pipe overflows */
+ write(sig_state->pipe_hack[1], &c, 1);
+}
+
+#ifdef SA_SIGINFO
+/*
+ signal handler with SA_SIGINFO - redirects to registered signals
+*/
+static void signal_handler_info(int signum, siginfo_t *info, void *uctx)
+{
+ uint32_t count = sig_count(sig_state->signal_count[signum]);
+ sig_state->sig_info[signum][count] = *info;
+
+ signal_handler(signum);
+
+ /* handle SA_SIGINFO */
+ if (count+1 == SA_INFO_QUEUE_COUNT) {
+ /* we've filled the info array - block this signal until
+ these ones are delivered */
+ sigset_t set;
+ sigemptyset(&set);
+ sigaddset(&set, signum);
+ sigprocmask(SIG_BLOCK, &set, NULL);
+ SIG_INCREMENT(sig_state->sig_blocked[signum]);
+ }
+}
+#endif
+
+/*
+ destroy a signal event
+*/
+static int signal_event_destructor(struct signal_event *se)
+{
+ se->event_ctx->num_signal_handlers--;
+ DLIST_REMOVE(sig_state->sig_handlers[se->signum], se);
+ if (sig_state->sig_handlers[se->signum] == NULL) {
+ /* restore old handler, if any */
+ sigaction(se->signum, sig_state->oldact[se->signum], NULL);
+ sig_state->oldact[se->signum] = NULL;
+#ifdef SA_SIGINFO
+ if (se->sa_flags & SA_SIGINFO) {
+ talloc_free(sig_state->sig_info[se->signum]);
+ sig_state->sig_info[se->signum] = NULL;
+ }
+#endif
+ }
+ return 0;
+}
+
+/*
+ this is part of the pipe hack needed to avoid the signal race condition
+*/
+static void signal_pipe_handler(struct event_context *ev, struct fd_event *fde,
+ uint16_t flags, void *private)
+{
+ char c[16];
+ /* its non-blocking, doesn't matter if we read too much */
+ read(sig_state->pipe_hack[0], c, sizeof(c));
+}
+
+/*
+ add a signal event
+ return NULL on failure (memory allocation error)
+*/
+struct signal_event *common_event_add_signal(struct event_context *ev,
+ TALLOC_CTX *mem_ctx,
+ int signum,
+ int sa_flags,
+ event_signal_handler_t handler,
+ void *private_data)
+{
+ struct signal_event *se;
+
+ if (signum >= NUM_SIGNALS) {
+ return NULL;
+ }
+
+ /* the sig_state needs to be on a global context as it can last across
+ multiple event contexts */
+ if (sig_state == NULL) {
+ sig_state = talloc_zero(talloc_autofree_context(), struct sig_state);
+ if (sig_state == NULL) {
+ return NULL;
+ }
+ }
+
+ se = talloc(mem_ctx?mem_ctx:ev, struct signal_event);
+ if (se == NULL) return NULL;
+
+ se->event_ctx = ev;
+ se->handler = handler;
+ se->private_data = private_data;
+ se->signum = signum;
+ se->sa_flags = sa_flags;
+
+ /* Ensure, no matter the destruction order, that we always have a handle on the global sig_state */
+ if (!talloc_reference(se, sig_state)) {
+ return NULL;
+ }
+
+ /* only install a signal handler if not already installed */
+ if (sig_state->sig_handlers[signum] == NULL) {
+ struct sigaction act;
+ ZERO_STRUCT(act);
+ act.sa_handler = signal_handler;
+ act.sa_flags = sa_flags;
+#ifdef SA_SIGINFO
+ if (sa_flags & SA_SIGINFO) {
+ act.sa_handler = NULL;
+ act.sa_sigaction = signal_handler_info;
+ if (sig_state->sig_info[signum] == NULL) {
+ sig_state->sig_info[signum] = talloc_array(sig_state, siginfo_t, SA_INFO_QUEUE_COUNT);
+ if (sig_state->sig_info[signum] == NULL) {
+ talloc_free(se);
+ return NULL;
+ }
+ }
+ }
+#endif
+ sig_state->oldact[signum] = talloc(sig_state, struct sigaction);
+ if (sig_state->oldact[signum] == NULL) {
+ talloc_free(se);
+ return NULL;
+ }
+ if (sigaction(signum, &act, sig_state->oldact[signum]) == -1) {
+ talloc_free(se);
+ return NULL;
+ }
+ }
+
+ DLIST_ADD(sig_state->sig_handlers[signum], se);
+
+ talloc_set_destructor(se, signal_event_destructor);
+
+ /* we need to setup the pipe hack handler if not already
+ setup */
+ if (ev->pipe_fde == NULL) {
+ if (sig_state->pipe_hack[0] == 0 &&
+ sig_state->pipe_hack[1] == 0) {
+ pipe(sig_state->pipe_hack);
+ ev_set_blocking(sig_state->pipe_hack[0], false);
+ ev_set_blocking(sig_state->pipe_hack[1], false);
+ }
+ ev->pipe_fde = event_add_fd(ev, ev, sig_state->pipe_hack[0],
+ EVENT_FD_READ, signal_pipe_handler, NULL);
+ }
+ ev->num_signal_handlers++;
+
+ return se;
+}
+
+
+/*
+ check if a signal is pending
+ return != 0 if a signal was pending
+*/
+int common_event_check_signal(struct event_context *ev)
+{
+ int i;
+
+ if (!sig_state || !SIG_PENDING(sig_state->got_signal)) {
+ return 0;
+ }
+
+ for (i=0;i<NUM_SIGNALS+1;i++) {
+ struct signal_event *se, *next;
+ struct sigcounter counter = sig_state->signal_count[i];
+ uint32_t count = sig_count(counter);
+
+ if (count == 0) {
+ continue;
+ }
+ for (se=sig_state->sig_handlers[i];se;se=next) {
+ next = se->next;
+#ifdef SA_SIGINFO
+ if (se->sa_flags & SA_SIGINFO) {
+ int j;
+ for (j=0;j<count;j++) {
+ /* note the use of the sig_info array as a
+ ring buffer */
+ int ofs = ((count-1) + j) % SA_INFO_QUEUE_COUNT;
+ se->handler(ev, se, i, 1,
+ (void*)&sig_state->sig_info[i][ofs],
+ se->private_data);
+ }
+ if (SIG_PENDING(sig_state->sig_blocked[i])) {
+ /* we'd filled the queue, unblock the
+ signal now */
+ sigset_t set;
+ sigemptyset(&set);
+ sigaddset(&set, i);
+ SIG_SEEN(sig_state->sig_blocked[i],
+ sig_count(sig_state->sig_blocked[i]));
+ sigprocmask(SIG_UNBLOCK, &set, NULL);
+ }
+ if (se->sa_flags & SA_RESETHAND) {
+ talloc_free(se);
+ }
+ continue;
+ }
+#endif
+ se->handler(ev, se, i, count, NULL, se->private_data);
+ if (se->sa_flags & SA_RESETHAND) {
+ talloc_free(se);
+ }
+ }
+ SIG_SEEN(sig_state->signal_count[i], count);
+ SIG_SEEN(sig_state->got_signal, count);
+ }
+
+ return 1;
+}
diff --git a/lib/tevent/tevent_standard.c b/lib/tevent/tevent_standard.c
new file mode 100644
index 0000000000..c63d092173
--- /dev/null
+++ b/lib/tevent/tevent_standard.c
@@ -0,0 +1,607 @@
+/*
+ Unix SMB/CIFS implementation.
+ main select loop and event handling
+ Copyright (C) Andrew Tridgell 2003-2005
+ Copyright (C) Stefan Metzmacher 2005
+
+ This program 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.
+
+ This program 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/>.
+*/
+
+/*
+ This is SAMBA's default event loop code
+
+ - we try to use epoll if configure detected support for it
+ otherwise we use select()
+ - if epoll is broken on the system or the kernel doesn't support it
+ at runtime we fallback to select()
+*/
+
+#include "replace.h"
+#include "system/filesys.h"
+#include "system/network.h"
+#include "system/select.h" /* needed for HAVE_EVENTS_EPOLL */
+#include "tevent.h"
+#include "tevent_util.h"
+#include "tevent_internal.h"
+
+struct std_event_context {
+ /* a pointer back to the generic event_context */
+ struct event_context *ev;
+
+ /* list of filedescriptor events */
+ struct fd_event *fd_events;
+
+ /* the maximum file descriptor number in fd_events */
+ int maxfd;
+
+ /* information for exiting from the event loop */
+ int exit_code;
+
+ /* this is changed by the destructors for the fd event
+ type. It is used to detect event destruction by event
+ handlers, which means the code that is calling the event
+ handler needs to assume that the linked list is no longer
+ valid
+ */
+ uint32_t destruction_count;
+
+ /* when using epoll this is the handle from epoll_create */
+ int epoll_fd;
+
+ /* our pid at the time the epoll_fd was created */
+ pid_t pid;
+};
+
+/* use epoll if it is available */
+#if HAVE_EVENTS_EPOLL
+/*
+ called when a epoll call fails, and we should fallback
+ to using select
+*/
+static void epoll_fallback_to_select(struct std_event_context *std_ev, const char *reason)
+{
+ ev_debug(std_ev->ev, EV_DEBUG_FATAL,
+ "%s (%s) - falling back to select()\n",
+ reason, strerror(errno));
+ close(std_ev->epoll_fd);
+ std_ev->epoll_fd = -1;
+ talloc_set_destructor(std_ev, NULL);
+}
+
+/*
+ map from EVENT_FD_* to EPOLLIN/EPOLLOUT
+*/
+static uint32_t epoll_map_flags(uint16_t flags)
+{
+ uint32_t ret = 0;
+ if (flags & EVENT_FD_READ) ret |= (EPOLLIN | EPOLLERR | EPOLLHUP);
+ if (flags & EVENT_FD_WRITE) ret |= (EPOLLOUT | EPOLLERR | EPOLLHUP);
+ return ret;
+}
+
+/*
+ free the epoll fd
+*/
+static int epoll_ctx_destructor(struct std_event_context *std_ev)
+{
+ if (std_ev->epoll_fd != -1) {
+ close(std_ev->epoll_fd);
+ }
+ std_ev->epoll_fd = -1;
+ return 0;
+}
+
+/*
+ init the epoll fd
+*/
+static void epoll_init_ctx(struct std_event_context *std_ev)
+{
+ std_ev->epoll_fd = epoll_create(64);
+ std_ev->pid = getpid();
+ talloc_set_destructor(std_ev, epoll_ctx_destructor);
+}
+
+static void epoll_add_event(struct std_event_context *std_ev, struct fd_event *fde);
+
+/*
+ reopen the epoll handle when our pid changes
+ see http://junkcode.samba.org/ftp/unpacked/junkcode/epoll_fork.c for an
+ demonstration of why this is needed
+ */
+static void epoll_check_reopen(struct std_event_context *std_ev)
+{
+ struct fd_event *fde;
+
+ if (std_ev->pid == getpid()) {
+ return;
+ }
+
+ close(std_ev->epoll_fd);
+ std_ev->epoll_fd = epoll_create(64);
+ if (std_ev->epoll_fd == -1) {
+ ev_debug(std_ev->ev, EV_DEBUG_FATAL,
+ "Failed to recreate epoll handle after fork\n");
+ return;
+ }
+ std_ev->pid = getpid();
+ for (fde=std_ev->fd_events;fde;fde=fde->next) {
+ epoll_add_event(std_ev, fde);
+ }
+}
+
+#define EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT (1<<0)
+#define EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR (1<<1)
+#define EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR (1<<2)
+
+/*
+ add the epoll event to the given fd_event
+*/
+static void epoll_add_event(struct std_event_context *std_ev, struct fd_event *fde)
+{
+ struct epoll_event event;
+ if (std_ev->epoll_fd == -1) return;
+
+ fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
+
+ /* if we don't want events yet, don't add an epoll_event */
+ if (fde->flags == 0) return;
+
+ ZERO_STRUCT(event);
+ event.events = epoll_map_flags(fde->flags);
+ event.data.ptr = fde;
+ if (epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_ADD, fde->fd, &event) != 0) {
+ epoll_fallback_to_select(std_ev, "EPOLL_CTL_ADD failed");
+ }
+ fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
+
+ /* only if we want to read we want to tell the event handler about errors */
+ if (fde->flags & EVENT_FD_READ) {
+ fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
+ }
+}
+
+/*
+ delete the epoll event for given fd_event
+*/
+static void epoll_del_event(struct std_event_context *std_ev, struct fd_event *fde)
+{
+ struct epoll_event event;
+ if (std_ev->epoll_fd == -1) return;
+
+ fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
+
+ /* if there's no epoll_event, we don't need to delete it */
+ if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT)) return;
+
+ ZERO_STRUCT(event);
+ event.events = epoll_map_flags(fde->flags);
+ event.data.ptr = fde;
+ epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event);
+ fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
+}
+
+/*
+ change the epoll event to the given fd_event
+*/
+static void epoll_mod_event(struct std_event_context *std_ev, struct fd_event *fde)
+{
+ struct epoll_event event;
+ if (std_ev->epoll_fd == -1) return;
+
+ fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
+
+ ZERO_STRUCT(event);
+ event.events = epoll_map_flags(fde->flags);
+ event.data.ptr = fde;
+ if (epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event) != 0) {
+ epoll_fallback_to_select(std_ev, "EPOLL_CTL_MOD failed");
+ }
+
+ /* only if we want to read we want to tell the event handler about errors */
+ if (fde->flags & EVENT_FD_READ) {
+ fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
+ }
+}
+
+static void epoll_change_event(struct std_event_context *std_ev, struct fd_event *fde)
+{
+ bool got_error = (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR);
+ bool want_read = (fde->flags & EVENT_FD_READ);
+ bool want_write= (fde->flags & EVENT_FD_WRITE);
+
+ if (std_ev->epoll_fd == -1) return;
+
+ fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
+
+ /* there's already an event */
+ if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT) {
+ if (want_read || (want_write && !got_error)) {
+ epoll_mod_event(std_ev, fde);
+ return;
+ }
+ /*
+ * if we want to match the select behavior, we need to remove the epoll_event
+ * when the caller isn't interested in events.
+ *
+ * this is because epoll reports EPOLLERR and EPOLLHUP, even without asking for them
+ */
+ epoll_del_event(std_ev, fde);
+ return;
+ }
+
+ /* there's no epoll_event attached to the fde */
+ if (want_read || (want_write && !got_error)) {
+ epoll_add_event(std_ev, fde);
+ return;
+ }
+}
+
+/*
+ event loop handling using epoll
+*/
+static int epoll_event_loop(struct std_event_context *std_ev, struct timeval *tvalp)
+{
+ int ret, i;
+#define MAXEVENTS 8
+ struct epoll_event events[MAXEVENTS];
+ uint32_t destruction_count = ++std_ev->destruction_count;
+ int timeout = -1;
+
+ if (std_ev->epoll_fd == -1) return -1;
+
+ if (tvalp) {
+ /* it's better to trigger timed events a bit later than to early */
+ timeout = ((tvalp->tv_usec+999) / 1000) + (tvalp->tv_sec*1000);
+ }
+
+ if (std_ev->ev->num_signal_handlers &&
+ common_event_check_signal(std_ev->ev)) {
+ return 0;
+ }
+
+ ret = epoll_wait(std_ev->epoll_fd, events, MAXEVENTS, timeout);
+
+ if (ret == -1 && errno == EINTR && std_ev->ev->num_signal_handlers) {
+ if (common_event_check_signal(std_ev->ev)) {
+ return 0;
+ }
+ }
+
+ if (ret == -1 && errno != EINTR) {
+ epoll_fallback_to_select(std_ev, "epoll_wait() failed");
+ return -1;
+ }
+
+ if (ret == 0 && tvalp) {
+ /* we don't care about a possible delay here */
+ common_event_loop_timer_delay(std_ev->ev);
+ return 0;
+ }
+
+ for (i=0;i<ret;i++) {
+ struct fd_event *fde = talloc_get_type(events[i].data.ptr,
+ struct fd_event);
+ uint16_t flags = 0;
+
+ if (fde == NULL) {
+ epoll_fallback_to_select(std_ev, "epoll_wait() gave bad data");
+ return -1;
+ }
+ if (events[i].events & (EPOLLHUP|EPOLLERR)) {
+ fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR;
+ /*
+ * if we only wait for EVENT_FD_WRITE, we should not tell the
+ * event handler about it, and remove the epoll_event,
+ * as we only report errors when waiting for read events,
+ * to match the select() behavior
+ */
+ if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR)) {
+ epoll_del_event(std_ev, fde);
+ continue;
+ }
+ flags |= EVENT_FD_READ;
+ }
+ if (events[i].events & EPOLLIN) flags |= EVENT_FD_READ;
+ if (events[i].events & EPOLLOUT) flags |= EVENT_FD_WRITE;
+ if (flags) {
+ fde->handler(std_ev->ev, fde, flags, fde->private_data);
+ if (destruction_count != std_ev->destruction_count) {
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+#else
+#define epoll_init_ctx(std_ev)
+#define epoll_add_event(std_ev,fde)
+#define epoll_del_event(std_ev,fde)
+#define epoll_change_event(std_ev,fde)
+#define epoll_event_loop(std_ev,tvalp) (-1)
+#define epoll_check_reopen(std_ev)
+#endif
+
+/*
+ create a std_event_context structure.
+*/
+static int std_event_context_init(struct event_context *ev)
+{
+ struct std_event_context *std_ev;
+
+ std_ev = talloc_zero(ev, struct std_event_context);
+ if (!std_ev) return -1;
+ std_ev->ev = ev;
+ std_ev->epoll_fd = -1;
+
+ epoll_init_ctx(std_ev);
+
+ ev->additional_data = std_ev;
+ return 0;
+}
+
+/*
+ recalculate the maxfd
+*/
+static void calc_maxfd(struct std_event_context *std_ev)
+{
+ struct fd_event *fde;
+
+ std_ev->maxfd = 0;
+ for (fde = std_ev->fd_events; fde; fde = fde->next) {
+ if (fde->fd > std_ev->maxfd) {
+ std_ev->maxfd = fde->fd;
+ }
+ }
+}
+
+
+/* to mark the ev->maxfd invalid
+ * this means we need to recalculate it
+ */
+#define EVENT_INVALID_MAXFD (-1)
+
+/*
+ destroy an fd_event
+*/
+static int std_event_fd_destructor(struct fd_event *fde)
+{
+ struct event_context *ev = fde->event_ctx;
+ struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
+ struct std_event_context);
+
+ epoll_check_reopen(std_ev);
+
+ if (std_ev->maxfd == fde->fd) {
+ std_ev->maxfd = EVENT_INVALID_MAXFD;
+ }
+
+ DLIST_REMOVE(std_ev->fd_events, fde);
+ std_ev->destruction_count++;
+
+ epoll_del_event(std_ev, fde);
+
+ if (fde->flags & EVENT_FD_AUTOCLOSE) {
+ close(fde->fd);
+ fde->fd = -1;
+ }
+
+ return 0;
+}
+
+/*
+ add a fd based event
+ return NULL on failure (memory allocation error)
+*/
+static struct fd_event *std_event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx,
+ int fd, uint16_t flags,
+ event_fd_handler_t handler,
+ void *private_data)
+{
+ struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
+ struct std_event_context);
+ struct fd_event *fde;
+
+ epoll_check_reopen(std_ev);
+
+ fde = talloc(mem_ctx?mem_ctx:ev, struct fd_event);
+ if (!fde) return NULL;
+
+ fde->event_ctx = ev;
+ fde->fd = fd;
+ fde->flags = flags;
+ fde->handler = handler;
+ fde->private_data = private_data;
+ fde->additional_flags = 0;
+ fde->additional_data = NULL;
+
+ DLIST_ADD(std_ev->fd_events, fde);
+ if ((std_ev->maxfd != EVENT_INVALID_MAXFD)
+ && (fde->fd > std_ev->maxfd)) {
+ std_ev->maxfd = fde->fd;
+ }
+ talloc_set_destructor(fde, std_event_fd_destructor);
+
+ epoll_add_event(std_ev, fde);
+
+ return fde;
+}
+
+
+/*
+ return the fd event flags
+*/
+static uint16_t std_event_get_fd_flags(struct fd_event *fde)
+{
+ return fde->flags;
+}
+
+/*
+ set the fd event flags
+*/
+static void std_event_set_fd_flags(struct fd_event *fde, uint16_t flags)
+{
+ struct event_context *ev;
+ struct std_event_context *std_ev;
+
+ if (fde->flags == flags) return;
+
+ ev = fde->event_ctx;
+ std_ev = talloc_get_type(ev->additional_data, struct std_event_context);
+
+ fde->flags = flags;
+
+ epoll_check_reopen(std_ev);
+
+ epoll_change_event(std_ev, fde);
+}
+
+/*
+ event loop handling using select()
+*/
+static int std_event_loop_select(struct std_event_context *std_ev, struct timeval *tvalp)
+{
+ fd_set r_fds, w_fds;
+ struct fd_event *fde;
+ int selrtn;
+ uint32_t destruction_count = ++std_ev->destruction_count;
+
+ /* we maybe need to recalculate the maxfd */
+ if (std_ev->maxfd == EVENT_INVALID_MAXFD) {
+ calc_maxfd(std_ev);
+ }
+
+ FD_ZERO(&r_fds);
+ FD_ZERO(&w_fds);
+
+ /* setup any fd events */
+ for (fde = std_ev->fd_events; fde; fde = fde->next) {
+ if (fde->flags & EVENT_FD_READ) {
+ FD_SET(fde->fd, &r_fds);
+ }
+ if (fde->flags & EVENT_FD_WRITE) {
+ FD_SET(fde->fd, &w_fds);
+ }
+ }
+
+ if (std_ev->ev->num_signal_handlers &&
+ common_event_check_signal(std_ev->ev)) {
+ return 0;
+ }
+
+ selrtn = select(std_ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp);
+
+ if (selrtn == -1 && errno == EINTR &&
+ std_ev->ev->num_signal_handlers) {
+ common_event_check_signal(std_ev->ev);
+ return 0;
+ }
+
+ if (selrtn == -1 && errno == EBADF) {
+ /* the socket is dead! this should never
+ happen as the socket should have first been
+ made readable and that should have removed
+ the event, so this must be a bug. This is a
+ fatal error. */
+ ev_debug(std_ev->ev, EV_DEBUG_FATAL,
+ "ERROR: EBADF on std_event_loop_once\n");
+ std_ev->exit_code = EBADF;
+ return -1;
+ }
+
+ if (selrtn == 0 && tvalp) {
+ /* we don't care about a possible delay here */
+ common_event_loop_timer_delay(std_ev->ev);
+ return 0;
+ }
+
+ if (selrtn > 0) {
+ /* at least one file descriptor is ready - check
+ which ones and call the handler, being careful to allow
+ the handler to remove itself when called */
+ for (fde = std_ev->fd_events; fde; fde = fde->next) {
+ uint16_t flags = 0;
+
+ if (FD_ISSET(fde->fd, &r_fds)) flags |= EVENT_FD_READ;
+ if (FD_ISSET(fde->fd, &w_fds)) flags |= EVENT_FD_WRITE;
+ if (flags) {
+ fde->handler(std_ev->ev, fde, flags, fde->private_data);
+ if (destruction_count != std_ev->destruction_count) {
+ break;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*
+ do a single event loop using the events defined in ev
+*/
+static int std_event_loop_once(struct event_context *ev)
+{
+ struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
+ struct std_event_context);
+ struct timeval tval;
+
+ tval = common_event_loop_timer_delay(ev);
+ if (ev_timeval_is_zero(&tval)) {
+ return 0;
+ }
+
+ epoll_check_reopen(std_ev);
+
+ if (epoll_event_loop(std_ev, &tval) == 0) {
+ return 0;
+ }
+
+ return std_event_loop_select(std_ev, &tval);
+}
+
+/*
+ return on failure or (with 0) if all fd events are removed
+*/
+static int std_event_loop_wait(struct event_context *ev)
+{
+ struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
+ struct std_event_context);
+ std_ev->exit_code = 0;
+
+ while (std_ev->fd_events && std_ev->exit_code == 0) {
+ if (std_event_loop_once(ev) != 0) {
+ break;
+ }
+ }
+
+ return std_ev->exit_code;
+}
+
+static const struct event_ops std_event_ops = {
+ .context_init = std_event_context_init,
+ .add_fd = std_event_add_fd,
+ .get_fd_flags = std_event_get_fd_flags,
+ .set_fd_flags = std_event_set_fd_flags,
+ .add_timed = common_event_add_timed,
+ .add_signal = common_event_add_signal,
+ .loop_once = std_event_loop_once,
+ .loop_wait = std_event_loop_wait,
+};
+
+
+bool events_standard_init(void)
+{
+ return event_register_backend("standard", &std_event_ops);
+}
+
diff --git a/lib/tevent/tevent_timed.c b/lib/tevent/tevent_timed.c
new file mode 100644
index 0000000000..ba8213710e
--- /dev/null
+++ b/lib/tevent/tevent_timed.c
@@ -0,0 +1,230 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ common events code for timed events
+
+ Copyright (C) Andrew Tridgell 2003-2006
+ Copyright (C) Stefan Metzmacher 2005
+
+ This program 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.
+
+ This program 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 <sys/time.h>
+#include <time.h>
+#include "replace.h"
+#include "system/filesys.h"
+#include "system/select.h"
+#include "tevent.h"
+#include "tevent_internal.h"
+#include "tevent_util.h"
+
+/**
+ compare two timeval structures.
+ Return -1 if tv1 < tv2
+ Return 0 if tv1 == tv2
+ Return 1 if tv1 > tv2
+*/
+static int ev_timeval_compare(const struct timeval *tv1, const struct timeval *tv2)
+{
+ if (tv1->tv_sec > tv2->tv_sec) return 1;
+ if (tv1->tv_sec < tv2->tv_sec) return -1;
+ if (tv1->tv_usec > tv2->tv_usec) return 1;
+ if (tv1->tv_usec < tv2->tv_usec) return -1;
+ return 0;
+}
+
+/**
+ return a zero timeval
+*/
+static struct timeval ev_timeval_zero(void)
+{
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ return tv;
+}
+
+/**
+ return a timeval for the current time
+*/
+static struct timeval ev_timeval_current(void)
+{
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return tv;
+}
+
+/**
+ return a timeval struct with the given elements
+*/
+static struct timeval ev_timeval_set(uint32_t secs, uint32_t usecs)
+{
+ struct timeval tv;
+ tv.tv_sec = secs;
+ tv.tv_usec = usecs;
+ return tv;
+}
+
+/**
+ return the difference between two timevals as a timeval
+ if tv1 comes after tv2, then return a zero timeval
+ (this is *tv2 - *tv1)
+*/
+static struct timeval ev_timeval_until(const struct timeval *tv1,
+ const struct timeval *tv2)
+{
+ struct timeval t;
+ if (ev_timeval_compare(tv1, tv2) >= 0) {
+ return ev_timeval_zero();
+ }
+ t.tv_sec = tv2->tv_sec - tv1->tv_sec;
+ if (tv1->tv_usec > tv2->tv_usec) {
+ t.tv_sec--;
+ t.tv_usec = 1000000 - (tv1->tv_usec - tv2->tv_usec);
+ } else {
+ t.tv_usec = tv2->tv_usec - tv1->tv_usec;
+ }
+ return t;
+}
+
+/**
+ return true if a timeval is zero
+*/
+bool ev_timeval_is_zero(const struct timeval *tv)
+{
+ return tv->tv_sec == 0 && tv->tv_usec == 0;
+}
+
+/*
+ destroy a timed event
+*/
+static int common_event_timed_destructor(struct timed_event *te)
+{
+ struct event_context *ev = talloc_get_type(te->event_ctx,
+ struct event_context);
+ DLIST_REMOVE(ev->timed_events, te);
+ return 0;
+}
+
+static int common_event_timed_deny_destructor(struct timed_event *te)
+{
+ return -1;
+}
+
+/*
+ add a timed event
+ return NULL on failure (memory allocation error)
+*/
+struct timed_event *common_event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ctx,
+ struct timeval next_event,
+ event_timed_handler_t handler,
+ void *private_data)
+{
+ struct timed_event *te, *last_te, *cur_te;
+
+ te = talloc(mem_ctx?mem_ctx:ev, struct timed_event);
+ if (te == NULL) return NULL;
+
+ te->event_ctx = ev;
+ te->next_event = next_event;
+ te->handler = handler;
+ te->private_data = private_data;
+ te->additional_data = NULL;
+
+ /* keep the list ordered */
+ last_te = NULL;
+ for (cur_te = ev->timed_events; cur_te; cur_te = cur_te->next) {
+ /* if the new event comes before the current one break */
+ if (ev_timeval_compare(&te->next_event, &cur_te->next_event) < 0) {
+ break;
+ }
+
+ last_te = cur_te;
+ }
+
+ DLIST_ADD_AFTER(ev->timed_events, te, last_te);
+
+ talloc_set_destructor(te, common_event_timed_destructor);
+
+ return te;
+}
+
+/*
+ do a single event loop using the events defined in ev
+
+ return the delay untill the next timed event,
+ or zero if a timed event was triggered
+*/
+struct timeval common_event_loop_timer_delay(struct event_context *ev)
+{
+ struct timeval current_time = ev_timeval_zero();
+ struct timed_event *te = ev->timed_events;
+
+ if (!te) {
+ /* have a default tick time of 30 seconds. This guarantees
+ that code that uses its own timeout checking will be
+ able to proceeed eventually */
+ return ev_timeval_set(30, 0);
+ }
+
+ /*
+ * work out the right timeout for the next timed event
+ *
+ * avoid the syscall to gettimeofday() if the timed event should
+ * be triggered directly
+ *
+ * if there's a delay till the next timed event, we're done
+ * with just returning the delay
+ */
+ if (!ev_timeval_is_zero(&te->next_event)) {
+ struct timeval delay;
+
+ current_time = ev_timeval_current();
+
+ delay = ev_timeval_until(&current_time, &te->next_event);
+ if (!ev_timeval_is_zero(&delay)) {
+ return delay;
+ }
+ }
+
+ /*
+ * ok, we have a timed event that we'll process ...
+ */
+
+ /* deny the handler to free the event */
+ talloc_set_destructor(te, common_event_timed_deny_destructor);
+
+ /* We need to remove the timer from the list before calling the
+ * handler because in a semi-async inner event loop called from the
+ * handler we don't want to come across this event again -- vl */
+ DLIST_REMOVE(ev->timed_events, te);
+
+ /*
+ * If the timed event was registered for a zero current_time,
+ * then we pass a zero timeval here too! To avoid the
+ * overhead of gettimeofday() calls.
+ *
+ * otherwise we pass the current time
+ */
+ te->handler(ev, te, current_time, te->private_data);
+
+ /* The destructor isn't necessary anymore, we've already removed the
+ * event from the list. */
+ talloc_set_destructor(te, NULL);
+
+ talloc_free(te);
+
+ return ev_timeval_zero();
+}
+
diff --git a/lib/tevent/tevent_util.c b/lib/tevent/tevent_util.c
new file mode 100644
index 0000000000..cfcca9185d
--- /dev/null
+++ b/lib/tevent/tevent_util.c
@@ -0,0 +1,86 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Copyright (C) Andrew Tridgell 2005
+ Copyright (C) Jelmer Vernooij 2005
+
+ This program 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.
+
+ This program 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 "replace.h"
+#include "talloc.h"
+#include "tevent.h"
+#include "tevent_internal.h"
+#include "tevent_util.h"
+#include <fcntl.h>
+
+/**
+ return the number of elements in a string list
+*/
+static size_t str_list_length(const char **list)
+{
+ size_t ret;
+ for (ret=0;list && list[ret];ret++) /* noop */ ;
+ return ret;
+}
+
+/**
+ add an entry to a string list
+*/
+const char **ev_str_list_add(const char **list, const char *s)
+{
+ size_t len = str_list_length(list);
+ const char **ret;
+
+ ret = talloc_realloc(NULL, list, const char *, len+2);
+ if (ret == NULL) return NULL;
+
+ ret[len] = talloc_strdup(ret, s);
+ if (ret[len] == NULL) return NULL;
+
+ ret[len+1] = NULL;
+
+ return ret;
+}
+
+
+/**
+ Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
+ else
+ if SYSV use O_NDELAY
+ if BSD use FNDELAY
+**/
+
+int ev_set_blocking(int fd, bool set)
+{
+ int val;
+#ifdef O_NONBLOCK
+#define FLAG_TO_SET O_NONBLOCK
+#else
+#ifdef SYSV
+#define FLAG_TO_SET O_NDELAY
+#else /* BSD */
+#define FLAG_TO_SET FNDELAY
+#endif
+#endif
+
+ if((val = fcntl(fd, F_GETFL, 0)) == -1)
+ return -1;
+ if(set) /* Turn blocking on - ie. clear nonblock flag */
+ val &= ~FLAG_TO_SET;
+ else
+ val |= FLAG_TO_SET;
+ return fcntl( fd, F_SETFL, val);
+#undef FLAG_TO_SET
+}
diff --git a/lib/tevent/tevent_util.h b/lib/tevent/tevent_util.h
new file mode 100644
index 0000000000..052b302aae
--- /dev/null
+++ b/lib/tevent/tevent_util.h
@@ -0,0 +1,117 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Copyright (C) Andrew Tridgell 1998-2005
+ Copyright (C) Jelmer Vernooij 2005
+
+ This program 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.
+
+ This program 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/>.
+*/
+
+/* To use these macros you must have a structure containing a next and
+ prev pointer */
+
+#ifndef _DLINKLIST_H
+#define _DLINKLIST_H
+
+
+/* hook into the front of the list */
+#define DLIST_ADD(list, p) \
+do { \
+ if (!(list)) { \
+ (list) = (p); \
+ (p)->next = (p)->prev = NULL; \
+ } else { \
+ (list)->prev = (p); \
+ (p)->next = (list); \
+ (p)->prev = NULL; \
+ (list) = (p); \
+ }\
+} while (0)
+
+/* remove an element from a list - element doesn't have to be in list. */
+#define DLIST_REMOVE(list, p) \
+do { \
+ if ((p) == (list)) { \
+ (list) = (p)->next; \
+ if (list) (list)->prev = NULL; \
+ } else { \
+ if ((p)->prev) (p)->prev->next = (p)->next; \
+ if ((p)->next) (p)->next->prev = (p)->prev; \
+ } \
+ if ((p) != (list)) (p)->next = (p)->prev = NULL; \
+} while (0)
+
+/* promote an element to the top of the list */
+#define DLIST_PROMOTE(list, p) \
+do { \
+ DLIST_REMOVE(list, p); \
+ DLIST_ADD(list, p); \
+} while (0)
+
+/* hook into the end of the list - needs a tmp pointer */
+#define DLIST_ADD_END(list, p, type) \
+do { \
+ if (!(list)) { \
+ (list) = (p); \
+ (p)->next = (p)->prev = NULL; \
+ } else { \
+ type tmp; \
+ for (tmp = (list); tmp->next; tmp = tmp->next) ; \
+ tmp->next = (p); \
+ (p)->next = NULL; \
+ (p)->prev = tmp; \
+ } \
+} while (0)
+
+/* insert 'p' after the given element 'el' in a list. If el is NULL then
+ this is the same as a DLIST_ADD() */
+#define DLIST_ADD_AFTER(list, p, el) \
+do { \
+ if (!(list) || !(el)) { \
+ DLIST_ADD(list, p); \
+ } else { \
+ p->prev = el; \
+ p->next = el->next; \
+ el->next = p; \
+ if (p->next) p->next->prev = p; \
+ }\
+} while (0)
+
+/* demote an element to the end of the list, needs a tmp pointer */
+#define DLIST_DEMOTE(list, p, tmp) \
+do { \
+ DLIST_REMOVE(list, p); \
+ DLIST_ADD_END(list, p, tmp); \
+} while (0)
+
+/* concatenate two lists - putting all elements of the 2nd list at the
+ end of the first list */
+#define DLIST_CONCATENATE(list1, list2, type) \
+do { \
+ if (!(list1)) { \
+ (list1) = (list2); \
+ } else { \
+ type tmp; \
+ for (tmp = (list1); tmp->next; tmp = tmp->next) ; \
+ tmp->next = (list2); \
+ if (list2) { \
+ (list2)->prev = tmp; \
+ } \
+ } \
+} while (0)
+
+#endif /* _DLINKLIST_H */
+
+const char **ev_str_list_add(const char **list, const char *s);
+int ev_set_blocking(int fd, bool set);
diff --git a/lib/util/debug.h b/lib/util/debug.h
index a5962b04bb..7518a64e19 100644
--- a/lib/util/debug.h
+++ b/lib/util/debug.h
@@ -133,6 +133,7 @@ _PUBLIC_ void register_debug_handlers(const char *name, struct debug_ops *ops);
*/
_PUBLIC_ void dbgtext(const char *format, ...) PRINTF_ATTRIBUTE(1,2);
-extern XFILE *dbf;
+struct _XFILE;
+extern struct _XFILE *dbf;
#endif
diff --git a/lib/util/xfile.h b/lib/util/xfile.h
index af90f3f55c..1b15929997 100644
--- a/lib/util/xfile.h
+++ b/lib/util/xfile.h
@@ -23,7 +23,7 @@
see xfile.c for explanations
*/
-typedef struct {
+typedef struct _XFILE {
int fd;
char *buf;
char *next;