3 * Python 2 and 3 bindings for libnmdb
4 * Alberto Bertogli (albertito@blitiri.com.ar)
6 * This is the low-level module, used by the python one to construct
10 #define PY_SSIZE_T_CLEAN 1
30 static void db_dealloc(nmdbobject
*db
)
40 static PyObject
*db_add_tipc_server(nmdbobject
*db
, PyObject
*args
)
45 if (!PyArg_ParseTuple(args
, "i:add_tipc_server", &port
)) {
49 Py_BEGIN_ALLOW_THREADS
50 rv
= nmdb_add_tipc_server(db
->db
, port
);
53 return PyLong_FromLong(rv
);
57 static PyObject
*db_add_tcp_server(nmdbobject
*db
, PyObject
*args
)
63 if (!PyArg_ParseTuple(args
, "si:add_tcp_server", &addr
, &port
)) {
67 Py_BEGIN_ALLOW_THREADS
68 rv
= nmdb_add_tcp_server(db
->db
, addr
, port
);
71 return PyLong_FromLong(rv
);
75 static PyObject
*db_add_udp_server(nmdbobject
*db
, PyObject
*args
)
81 if (!PyArg_ParseTuple(args
, "si:add_udp_server", &addr
, &port
)) {
85 Py_BEGIN_ALLOW_THREADS
86 rv
= nmdb_add_udp_server(db
->db
, addr
, port
);
89 return PyLong_FromLong(rv
);
93 static PyObject
*db_cache_set(nmdbobject
*db
, PyObject
*args
)
95 unsigned char *key
, *val
;
99 if (!PyArg_ParseTuple(args
, "s#s#:cache_set", &key
, &ksize
,
104 Py_BEGIN_ALLOW_THREADS
105 rv
= nmdb_cache_set(db
->db
, key
, ksize
, val
, vsize
);
108 return PyLong_FromLong(rv
);
112 static PyObject
*db_cache_get(nmdbobject
*db
, PyObject
*args
)
114 unsigned char *key
, *val
;
119 if (!PyArg_ParseTuple(args
, "s#:cache_get", &key
, &ksize
)) {
123 /* vsize is enough to hold the any value */
127 return PyErr_NoMemory();
129 Py_BEGIN_ALLOW_THREADS
130 rv
= nmdb_cache_get(db
->db
, key
, ksize
, val
, vsize
);
134 /* FIXME: define a better exception */
135 r
= PyErr_SetFromErrno(PyExc_IOError
);
136 } else if (rv
== -1) {
137 /* Miss, handled in the high-level module. */
138 r
= PyLong_FromLong(-1);
141 r
= PyBytes_FromStringAndSize((char *) val
, rv
);
143 r
= PyString_FromStringAndSize((char *) val
, rv
);
152 static PyObject
*db_cache_delete(nmdbobject
*db
, PyObject
*args
)
158 if (!PyArg_ParseTuple(args
, "s#:cache_delete", &key
, &ksize
)) {
162 Py_BEGIN_ALLOW_THREADS
163 rv
= nmdb_cache_del(db
->db
, key
, ksize
);
166 return PyLong_FromLong(rv
);
170 static PyObject
*db_cache_cas(nmdbobject
*db
, PyObject
*args
)
172 unsigned char *key
, *oldval
, *newval
;
173 size_t ksize
, ovsize
, nvsize
;
176 if (!PyArg_ParseTuple(args
, "s#s#s#:cache_cas", &key
, &ksize
,
182 Py_BEGIN_ALLOW_THREADS
183 rv
= nmdb_cache_cas(db
->db
, key
, ksize
, oldval
, ovsize
,
187 return PyLong_FromLong(rv
);
190 /* cache increment */
191 static PyObject
*db_cache_incr(nmdbobject
*db
, PyObject
*args
)
196 long long int increment
;
199 if (!PyArg_ParseTuple(args
, "s#L:cache_incr", &key
, &ksize
,
204 Py_BEGIN_ALLOW_THREADS
205 rv
= nmdb_cache_incr(db
->db
, key
, ksize
, increment
, &newval
);
208 return Py_BuildValue("iL", rv
, newval
);
213 static PyObject
*db_set(nmdbobject
*db
, PyObject
*args
)
215 unsigned char *key
, *val
;
219 if (!PyArg_ParseTuple(args
, "s#s#:set", &key
, &ksize
,
224 Py_BEGIN_ALLOW_THREADS
225 rv
= nmdb_set(db
->db
, key
, ksize
, val
, vsize
);
228 return PyLong_FromLong(rv
);
232 static PyObject
*db_get(nmdbobject
*db
, PyObject
*args
)
234 unsigned char *key
, *val
;
239 if (!PyArg_ParseTuple(args
, "s#:get", &key
, &ksize
)) {
243 /* vsize is enough to hold the any value */
247 return PyErr_NoMemory();
249 Py_BEGIN_ALLOW_THREADS
250 rv
= nmdb_get(db
->db
, key
, ksize
, val
, vsize
);
254 /* FIXME: define a better exception */
255 r
= PyErr_SetFromErrno(PyExc_IOError
);
256 } else if (rv
== -1) {
257 /* Miss, handled in the high-level module. */
258 r
= PyLong_FromLong(-1);
261 r
= PyBytes_FromStringAndSize((char *) val
, rv
);
263 r
= PyString_FromStringAndSize((char *) val
, rv
);
272 static PyObject
*db_delete(nmdbobject
*db
, PyObject
*args
)
278 if (!PyArg_ParseTuple(args
, "s#:delete", &key
, &ksize
)) {
282 Py_BEGIN_ALLOW_THREADS
283 rv
= nmdb_del(db
->db
, key
, ksize
);
286 return PyLong_FromLong(rv
);
290 static PyObject
*db_cas(nmdbobject
*db
, PyObject
*args
)
292 unsigned char *key
, *oldval
, *newval
;
293 size_t ksize
, ovsize
, nvsize
;
296 if (!PyArg_ParseTuple(args
, "s#s#s#:cas", &key
, &ksize
,
302 Py_BEGIN_ALLOW_THREADS
303 rv
= nmdb_cas(db
->db
, key
, ksize
, oldval
, ovsize
, newval
, nvsize
);
306 return PyLong_FromLong(rv
);
310 static PyObject
*db_incr(nmdbobject
*db
, PyObject
*args
)
315 long long int increment
;
318 if (!PyArg_ParseTuple(args
, "s#L:incr", &key
, &ksize
, &increment
)) {
322 Py_BEGIN_ALLOW_THREADS
323 rv
= nmdb_incr(db
->db
, key
, ksize
, increment
, &newval
);
326 return Py_BuildValue("LL", rv
, newval
);
331 static PyObject
*db_set_sync(nmdbobject
*db
, PyObject
*args
)
333 unsigned char *key
, *val
;
337 if (!PyArg_ParseTuple(args
, "s#s#:set_sync", &key
, &ksize
,
342 Py_BEGIN_ALLOW_THREADS
343 rv
= nmdb_set_sync(db
->db
, key
, ksize
, val
, vsize
);
346 return PyLong_FromLong(rv
);
350 static PyObject
*db_delete_sync(nmdbobject
*db
, PyObject
*args
)
356 if (!PyArg_ParseTuple(args
, "s#:delete_sync", &key
, &ksize
)) {
360 Py_BEGIN_ALLOW_THREADS
361 rv
= nmdb_del_sync(db
->db
, key
, ksize
);
364 return PyLong_FromLong(rv
);
368 static PyObject
*db_firstkey(nmdbobject
*db
, PyObject
*args
)
375 if (!PyArg_ParseTuple(args
, "")) {
379 /* ksize is enough to hold the any value */
383 return PyErr_NoMemory();
385 Py_BEGIN_ALLOW_THREADS
386 rv
= nmdb_firstkey(db
->db
, key
, ksize
);
390 /* FIXME: define a better exception */
391 r
= PyErr_SetFromErrno(PyExc_IOError
);
392 } else if (rv
== -1) {
393 /* No first key or unsupported, handled in the high-level
395 r
= PyLong_FromLong(-1);
398 r
= PyBytes_FromStringAndSize((char *) key
, rv
);
400 r
= PyString_FromStringAndSize((char *) key
, rv
);
409 static PyObject
*db_nextkey(nmdbobject
*db
, PyObject
*args
)
411 unsigned char *key
, *newkey
;
412 size_t ksize
, nksize
;
416 if (!PyArg_ParseTuple(args
, "s#:nextkey", &key
, &ksize
)) {
420 /* nksize is enough to hold the any value */
422 newkey
= malloc(nksize
);
424 return PyErr_NoMemory();
426 Py_BEGIN_ALLOW_THREADS
427 rv
= nmdb_nextkey(db
->db
, key
, ksize
, newkey
, nksize
);
431 /* FIXME: define a better exception */
432 r
= PyErr_SetFromErrno(PyExc_IOError
);
433 } else if (rv
== -1) {
434 /* End, handled in the high-level module. */
435 r
= PyLong_FromLong(-1);
438 r
= PyBytes_FromStringAndSize((char *) newkey
, rv
);
440 r
= PyString_FromStringAndSize((char *) newkey
, rv
);
449 /* nmdb method table */
451 static PyMethodDef nmdb_methods
[] = {
452 { "add_tipc_server", (PyCFunction
) db_add_tipc_server
,
453 METH_VARARGS
, NULL
},
454 { "add_tcp_server", (PyCFunction
) db_add_tcp_server
,
455 METH_VARARGS
, NULL
},
456 { "add_udp_server", (PyCFunction
) db_add_udp_server
,
457 METH_VARARGS
, NULL
},
458 { "cache_set", (PyCFunction
) db_cache_set
, METH_VARARGS
, NULL
},
459 { "cache_get", (PyCFunction
) db_cache_get
, METH_VARARGS
, NULL
},
460 { "cache_delete", (PyCFunction
) db_cache_delete
, METH_VARARGS
, NULL
},
461 { "cache_cas", (PyCFunction
) db_cache_cas
, METH_VARARGS
, NULL
},
462 { "cache_incr", (PyCFunction
) db_cache_incr
, METH_VARARGS
, NULL
},
463 { "set", (PyCFunction
) db_set
, METH_VARARGS
, NULL
},
464 { "get", (PyCFunction
) db_get
, METH_VARARGS
, NULL
},
465 { "delete", (PyCFunction
) db_delete
, METH_VARARGS
, NULL
},
466 { "cas", (PyCFunction
) db_cas
, METH_VARARGS
, NULL
},
467 { "incr", (PyCFunction
) db_incr
, METH_VARARGS
, NULL
},
468 { "set_sync", (PyCFunction
) db_set_sync
, METH_VARARGS
, NULL
},
469 { "delete_sync", (PyCFunction
) db_delete_sync
, METH_VARARGS
, NULL
},
470 { "firstkey", (PyCFunction
) db_firstkey
, METH_VARARGS
, NULL
},
471 { "nextkey", (PyCFunction
) db_nextkey
, METH_VARARGS
, NULL
},
482 /* new, returns an nmdb object */
483 static PyTypeObject nmdbType
;
484 static PyObject
*db_new(PyObject
*self
, PyObject
*args
)
489 db
= (nmdbobject
*) nmdbType
.tp_alloc(&nmdbType
, 0);
491 db
= PyObject_New(nmdbobject
, &nmdbType
);
496 if (!PyArg_ParseTuple(args
, ":new")) {
500 db
->db
= nmdb_init();
501 if (db
->db
== NULL
) {
502 return PyErr_NoMemory();
505 /* XXX: is this necessary? */
506 if (PyErr_Occurred()) {
511 return (PyObject
*) db
;
514 static PyMethodDef nmdb_functions
[] = {
515 { "new", (PyCFunction
) db_new
, METH_VARARGS
, NULL
},
521 static PyTypeObject nmdbType
= {
522 PyObject_HEAD_INIT(NULL
)
523 .tp_name
= "nmdb_ll.nmdb",
524 .tp_itemsize
= sizeof(nmdbobject
),
525 .tp_dealloc
= (destructor
) db_dealloc
,
526 .tp_methods
= nmdb_methods
,
529 static PyModuleDef nmdb_module
= {
530 PyModuleDef_HEAD_INIT
,
534 .m_methods
= nmdb_functions
,
537 PyMODINIT_FUNC
PyInit_nmdb_ll(void)
541 if (PyType_Ready(&nmdbType
) < 0)
544 m
= PyModule_Create(&nmdb_module
);
550 static PyObject
*db_getattr(nmdbobject
*db
, char *name
)
552 return Py_FindMethod(nmdb_methods
, (PyObject
*)db
, name
);
555 static PyTypeObject nmdbType
= {
556 PyObject_HEAD_INIT(NULL
)
561 (destructor
) db_dealloc
,
563 (getattrfunc
) db_getattr
,
566 PyMODINIT_FUNC
initnmdb_ll(void)
570 nmdbType
.ob_type
= &PyType_Type
;
572 m
= Py_InitModule("nmdb_ll", nmdb_functions
);