python/py_tdb.c

説明を見る。
00001 /* 
00002    Python wrappers for TDB module
00003 
00004    Copyright (C) Tim Potter, 2002-2003
00005    
00006      ** NOTE! The following LGPL license applies to the tdb python
00007      ** scripting library. This does NOT imply that all of Samba is 
00008      ** released under the LGPL
00009    
00010    This library is free software; you can redistribute it and/or
00011    modify it under the terms of the GNU Lesser General Public
00012    License as published by the Free Software Foundation; either
00013    version 2 of the License, or (at your option) any later version.
00014 
00015    This library is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018    Lesser General Public License for more details.
00019    
00020    You should have received a copy of the GNU Lesser General Public
00021    License along with this library; if not, write to the Free Software
00022    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023 */
00024 
00025 #include "includes.h"
00026 
00027 /* This symbol is used in both includes.h and Python.h which causes an
00028    annoying compiler warning. */
00029 
00030 #ifdef HAVE_FSTAT
00031 #undef HAVE_FSTAT
00032 #endif
00033 
00034 #include "Python.h"
00035 
00036 /* Tdb exception */
00037 
00038 PyObject *py_tdb_error;
00039 
00040 /* tdb handle object */
00041 
00042 typedef struct {
00043         PyObject_HEAD
00044         TDB_CONTEXT *tdb;
00045 } tdb_hnd_object;
00046 
00047 PyTypeObject tdb_hnd_type;
00048      
00049 PyObject *new_tdb_hnd_object(TDB_CONTEXT *tdb)
00050 {
00051         tdb_hnd_object *obj;
00052 
00053         obj = PyObject_New(tdb_hnd_object, &tdb_hnd_type);
00054         obj->tdb = tdb;
00055 
00056         return (PyObject *)obj;
00057 }
00058 
00059 PyObject *py_tdb_close(PyObject *self, PyObject *args)
00060 {
00061         tdb_hnd_object *obj;
00062 
00063         if (!PyArg_ParseTuple(args, "O!", &tdb_hnd_type, &obj))
00064                 return NULL;
00065 
00066         if (tdb_close(obj->tdb) == -1) {
00067                 obj->tdb = NULL;
00068                 PyErr_SetString(py_tdb_error, strerror(errno));
00069                 return NULL;
00070         }
00071 
00072         obj->tdb = NULL;
00073 
00074         Py_INCREF(Py_None);
00075         return Py_None;
00076 }
00077 
00078 PyObject *py_tdb_open(PyObject *self, PyObject *args, PyObject *kw)
00079 {
00080         static char *kwlist[] = { "name", "hash_size", "tdb_flags",
00081                                   "open_flags", "mode", NULL };
00082         char *name;
00083         int hash_size = 0, flags = TDB_DEFAULT, open_flags = -1, open_mode = 0600;      
00084         TDB_CONTEXT *tdb;
00085 
00086         if (!PyArg_ParseTupleAndKeywords(
00087                     args, kw, "s|iiii", kwlist, &name, &hash_size, &flags,
00088                     &open_flags, &open_mode))
00089                 return NULL;
00090 
00091         /* Default open_flags to read/write */
00092 
00093         if (open_flags == -1) {
00094                 if (access(name, W_OK) == -1)
00095                         open_flags = O_RDONLY;
00096                 else
00097                         open_flags = O_RDWR;
00098         }
00099 
00100         if (!(tdb = tdb_open(name, hash_size, flags, open_flags, open_mode))) {
00101                 PyErr_SetString(py_tdb_error, strerror(errno));
00102                 return NULL;
00103         }
00104 
00105         return new_tdb_hnd_object(tdb);
00106 }
00107 
00108 /*
00109  * Allow a tdb to act as a python mapping (dictionary)
00110  */
00111 
00112 static int tdb_traverse_count(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA value,
00113                               void *state)
00114 {
00115         /* Do nothing - tdb_traverse will return the number of records
00116            traversed. */
00117 
00118         return 0;
00119 }
00120 
00121 static int tdb_hnd_length(tdb_hnd_object *obj)
00122 {
00123         int result;
00124 
00125         result = tdb_traverse(obj->tdb, tdb_traverse_count, NULL);
00126 
00127         return result;
00128 }
00129 
00130 static PyObject *tdb_hnd_subscript(tdb_hnd_object *obj, PyObject *key)
00131 {
00132         TDB_DATA drec, krec;
00133         PyObject *result;
00134 
00135         if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize))
00136                 return NULL;
00137 
00138         drec = tdb_fetch(obj->tdb, krec);
00139 
00140         if (!drec.dptr) {
00141                 PyErr_SetString(PyExc_KeyError,
00142                                 PyString_AsString(key));
00143                 return NULL;
00144         }
00145 
00146         result = PyString_FromStringAndSize(drec.dptr, drec.dsize);
00147         free(drec.dptr);
00148 
00149         return result;
00150 }
00151         
00152 static int tdb_ass_subscript(tdb_hnd_object *obj, PyObject *key, PyObject *value)
00153 {
00154         TDB_DATA krec, drec;
00155 
00156         if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize)) {
00157                 PyErr_SetString(PyExc_TypeError,
00158                                 "tdb mappings have string indices only");
00159                 return -1;
00160         }
00161 
00162         if (!obj->tdb) {
00163                 PyErr_SetString(
00164                         py_tdb_error, "tdb object has been closed"); 
00165                 return -1; 
00166         }
00167 
00168         if (!value) {
00169 
00170                 /* Delete value */
00171 
00172                 if (tdb_delete(obj->tdb, krec) == -1) {
00173                         PyErr_SetString(PyExc_KeyError,
00174                                         PyString_AsString(value));
00175                         return -1;
00176                 }
00177 
00178         } else {
00179 
00180                 /* Set value */
00181 
00182                 if (!PyArg_Parse(value, "s#", &drec.dptr, &drec.dsize)) {
00183                         PyErr_SetString(PyExc_TypeError,
00184                                     "tdb mappings have string elements only");
00185                         return -1;
00186                 }
00187 
00188                 errno = 0;
00189 
00190                 if (tdb_store(obj->tdb, krec, drec, 0) < 0 ) {
00191                         if (errno != 0)
00192                                 PyErr_SetFromErrno(py_tdb_error);
00193                         else
00194                                 PyErr_SetString(
00195                                         py_tdb_error, 
00196                                         (char *)tdb_errorstr(obj->tdb));
00197 
00198                         return -1;
00199                 }
00200         }
00201 
00202         return 0;
00203 } 
00204 
00205 static PyMappingMethods tdb_mapping = {
00206         (inquiry) tdb_hnd_length,
00207         (binaryfunc) tdb_hnd_subscript,
00208         (objobjargproc) tdb_ass_subscript
00209 };
00210 
00211 /*
00212  * Utility methods
00213  */
00214 
00215 /* Return non-zero if a given key exists in the tdb */
00216 
00217 PyObject *py_tdb_hnd_has_key(PyObject *self, PyObject *args)
00218 {
00219         tdb_hnd_object *obj = (tdb_hnd_object *)self;
00220         TDB_DATA key;
00221 
00222         if (!PyArg_ParseTuple(args, "s#", &key.dptr, &key.dsize))
00223                 return NULL;
00224 
00225         if (!obj->tdb) {
00226                 PyErr_SetString(
00227                         py_tdb_error, "tdb object has been closed"); 
00228                 return NULL;
00229         }       
00230 
00231         return PyInt_FromLong(tdb_exists(obj->tdb, key));
00232 }
00233 
00234 /* Return a list of keys in the tdb */
00235 
00236 static int tdb_traverse_keys(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA value,
00237                              void *state)
00238 {
00239         PyObject *key_list = (PyObject *)state;
00240 
00241         PyList_Append(key_list, 
00242                       PyString_FromStringAndSize(key.dptr, key.dsize));
00243 
00244         return 0;
00245 }
00246 
00247 PyObject *py_tdb_hnd_keys(PyObject *self, PyObject *args)
00248 {
00249         tdb_hnd_object *obj = (tdb_hnd_object *)self;
00250         PyObject *key_list = PyList_New(0);
00251 
00252         if (!obj->tdb) {
00253                 PyErr_SetString(py_tdb_error, "tdb object has been closed"); 
00254                 return NULL;
00255         }       
00256 
00257         if (tdb_traverse(obj->tdb, tdb_traverse_keys, key_list) == -1) {
00258                 PyErr_SetString(py_tdb_error, "error traversing tdb");
00259                 Py_DECREF(key_list);
00260                 return NULL;
00261         }
00262 
00263         return key_list;        
00264 }
00265 
00266 PyObject *py_tdb_hnd_first_key(PyObject *self, PyObject *args)
00267 {
00268         tdb_hnd_object *obj = (tdb_hnd_object *)self;
00269         TDB_DATA key;
00270 
00271         if (!obj->tdb) {
00272                 PyErr_SetString(py_tdb_error, "tdb object has been closed"); 
00273                 return NULL;
00274         }       
00275 
00276         key = tdb_firstkey(obj->tdb);
00277 
00278         return Py_BuildValue("s#", key.dptr, key.dsize);
00279 }
00280 
00281 PyObject *py_tdb_hnd_next_key(PyObject *self, PyObject *py_oldkey)
00282 {
00283         tdb_hnd_object *obj = (tdb_hnd_object *)self;
00284         TDB_DATA key, oldkey;
00285 
00286         if (!obj->tdb) {
00287                 PyErr_SetString(py_tdb_error, "tdb object has been closed"); 
00288                 return NULL;
00289         }       
00290 
00291         if (!PyArg_Parse(py_oldkey, "s#", &oldkey.dptr, &oldkey.dsize))
00292                 return NULL;
00293 
00294         key = tdb_nextkey(obj->tdb, oldkey);
00295 
00296         return Py_BuildValue("s#", key.dptr, key.dsize);
00297 }
00298 
00299 /*
00300  * Locking routines
00301  */
00302 
00303 PyObject *py_tdb_hnd_lock_all(PyObject *self, PyObject *args)
00304 {
00305         tdb_hnd_object *obj = (tdb_hnd_object *)self;
00306         int result;
00307 
00308         if (!obj->tdb) {
00309                 PyErr_SetString(py_tdb_error, "tdb object has been closed"); 
00310                 return NULL;
00311         }       
00312 
00313         result = tdb_lockall(obj->tdb);
00314 
00315         return PyInt_FromLong(result != -1);
00316 }
00317 
00318 PyObject *py_tdb_hnd_unlock_all(PyObject *self, PyObject *args)
00319 {
00320         tdb_hnd_object *obj = (tdb_hnd_object *)self;
00321 
00322         if (!obj->tdb) {
00323                 PyErr_SetString(py_tdb_error, "tdb object has been closed"); 
00324                 return NULL;
00325         }       
00326 
00327         tdb_unlockall(obj->tdb);
00328 
00329         Py_INCREF(Py_None);
00330         return Py_None;
00331 }
00332 
00333 /* Return an array of keys from a python object which must be a string or a
00334    list of strings. */
00335 
00336 static BOOL make_lock_list(PyObject *py_keys, TDB_DATA **keys, int *num_keys)
00337 {
00338         /* Are we a list or a string? */
00339 
00340         if (!PyList_Check(py_keys) && !PyString_Check(py_keys)) {
00341                 PyErr_SetString(PyExc_TypeError, "arg must be list of string");
00342                 return False;
00343         }
00344 
00345         if (PyList_Check(py_keys)) {
00346                 int i;
00347 
00348                 /* Turn python list into array of keys */
00349                 
00350                 *num_keys = PyList_Size(py_keys);
00351                 *keys = (TDB_DATA *)SMB_XMALLOC_ARRAY(TDB_DATA, (*num_keys));
00352                 
00353                 for (i = 0; i < *num_keys; i++) {
00354                         PyObject *key = PyList_GetItem(py_keys, i);
00355                         
00356                         if (!PyString_Check(key)) {
00357                                 PyErr_SetString(
00358                                         PyExc_TypeError,
00359                                         "list elements must be strings");
00360                                 return False;
00361                         }
00362 
00363                         PyArg_Parse(key, "s#", &(*keys)[i].dptr, 
00364                                     &(*keys)[i].dsize);
00365                 }
00366 
00367         } else {
00368 
00369                 /* Turn python string into a single key */
00370 
00371                 *keys = (TDB_DATA *)SMB_XMALLOC_P(TDB_DATA);
00372                 *num_keys = 1;
00373                 PyArg_Parse(py_keys, "s#", &(*keys)->dptr, &(*keys)->dsize);
00374         }
00375 
00376         return True;
00377 }
00378 
00379 /*
00380  * tdb traversal
00381  */
00382 
00383 struct traverse_info {
00384         PyObject *callback;
00385         PyObject *state;
00386 };
00387 
00388 static int tdb_traverse_traverse(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA value,
00389                                  void *state)
00390 {
00391         struct traverse_info *info = state;
00392         PyObject *arglist, *py_result;
00393         int result;
00394 
00395         arglist = Py_BuildValue("(s#s#O)", key.dptr, key.dsize, value.dptr,
00396                                 value.dsize, info->state);
00397 
00398         py_result = PyEval_CallObject(info->callback, arglist);
00399 
00400         Py_DECREF(arglist);
00401         
00402         if (!PyInt_Check(py_result)) {
00403                 result = 1;     /* Hmm - non-integer object returned by callback */
00404                 goto done;
00405         }
00406 
00407         result = PyInt_AsLong(py_result);
00408 
00409 done:
00410         Py_DECREF(py_result);
00411         return result;
00412 }
00413 
00414 PyObject *py_tdb_hnd_traverse(PyObject *self, PyObject *args, PyObject *kw)
00415 {
00416         tdb_hnd_object *obj = (tdb_hnd_object *)self;
00417         static char *kwlist[] = { "traverse_fn", "state", NULL };
00418         PyObject *state = Py_None, *callback;
00419         struct traverse_info info;
00420         int result;
00421 
00422         if (!PyArg_ParseTupleAndKeywords(
00423                     args, kw, "O|O", kwlist, &callback, &state))
00424                 return NULL;
00425 
00426         if (!PyCallable_Check(callback)) {
00427                 PyErr_SetString(PyExc_TypeError, "parameter must be callable");
00428                 return NULL;
00429         }
00430 
00431         Py_INCREF(callback);
00432         Py_INCREF(state);
00433 
00434         info.callback = callback;
00435         info.state = state;
00436 
00437         result = tdb_traverse(obj->tdb, tdb_traverse_traverse, &info);
00438 
00439         Py_DECREF(callback);
00440         Py_DECREF(state);
00441 
00442         return PyInt_FromLong(result);
00443 }
00444 
00445 PyObject *py_tdb_hnd_chainlock(PyObject *self, PyObject *args)
00446 {
00447         tdb_hnd_object *obj = (tdb_hnd_object *)self;
00448         TDB_DATA key;
00449         int result;
00450 
00451         if (!obj->tdb) {
00452                 PyErr_SetString(py_tdb_error, "tdb object has been closed"); 
00453                 return NULL;
00454         }       
00455 
00456         if (!PyArg_ParseTuple(args, "s#", &key.dptr, &key.dsize))
00457                 return NULL;
00458 
00459         result = tdb_chainlock(obj->tdb, key);
00460 
00461         return PyInt_FromLong(result != -1);
00462 }
00463 
00464 PyObject *py_tdb_hnd_chainunlock(PyObject *self, PyObject *args)
00465 {
00466         tdb_hnd_object *obj = (tdb_hnd_object *)self;
00467         TDB_DATA key;
00468         int result;
00469 
00470         if (!obj->tdb) {
00471                 PyErr_SetString(py_tdb_error, "tdb object has been closed"); 
00472                 return NULL;
00473         }       
00474 
00475         if (!PyArg_ParseTuple(args, "s#", &key.dptr, &key.dsize))
00476                 return NULL;
00477 
00478         result = tdb_chainunlock(obj->tdb, key);
00479 
00480         return PyInt_FromLong(result != -1);
00481 }
00482 
00483 PyObject *py_tdb_hnd_lock_bystring(PyObject *self, PyObject *args)
00484 {
00485         tdb_hnd_object *obj = (tdb_hnd_object *)self;
00486         int result, timeout = 30;
00487         char *s;
00488 
00489         if (!obj->tdb) {
00490                 PyErr_SetString(py_tdb_error, "tdb object has been closed"); 
00491                 return NULL;
00492         }       
00493 
00494         if (!PyArg_ParseTuple(args, "s|i", &s, &timeout))
00495                 return NULL;
00496 
00497         result = tdb_lock_bystring_with_timeout(obj->tdb, s, timeout);
00498 
00499         return PyInt_FromLong(result != -1);
00500 }
00501 
00502 PyObject *py_tdb_hnd_unlock_bystring(PyObject *self, PyObject *args)
00503 {
00504         tdb_hnd_object *obj = (tdb_hnd_object *)self;
00505         char *s;
00506 
00507         if (!obj->tdb) {
00508                 PyErr_SetString(py_tdb_error, "tdb object has been closed"); 
00509                 return NULL;
00510         }       
00511 
00512         if (!PyArg_ParseTuple(args, "s", &s))
00513                 return NULL;
00514 
00515         tdb_unlock_bystring(obj->tdb, s);
00516 
00517         Py_INCREF(Py_None);
00518         return Py_None;
00519 }
00520 
00521 /* 
00522  * Method dispatch table for this module
00523  */
00524 
00525 static PyMethodDef tdb_methods[] = {
00526         { "open", (PyCFunction)py_tdb_open, METH_VARARGS | METH_KEYWORDS },
00527         { "close", (PyCFunction)py_tdb_close, METH_VARARGS },
00528         { NULL }
00529 };
00530 
00531 /* 
00532  * Methods on a tdb object
00533  */
00534 
00535 static PyMethodDef tdb_hnd_methods[] = {
00536         { "keys", (PyCFunction)py_tdb_hnd_keys, METH_VARARGS },
00537         { "has_key", (PyCFunction)py_tdb_hnd_has_key, METH_VARARGS },
00538         { "first_key", (PyCFunction)py_tdb_hnd_first_key, METH_VARARGS },
00539         { "next_key", (PyCFunction)py_tdb_hnd_next_key, METH_VARARGS },
00540         { "lock_all", (PyCFunction)py_tdb_hnd_lock_all, METH_VARARGS },
00541         { "unlock_all", (PyCFunction)py_tdb_hnd_unlock_all, METH_VARARGS },
00542         { "traverse", (PyCFunction)py_tdb_hnd_traverse, METH_VARARGS | METH_KEYWORDS },
00543         { "chainlock", (PyCFunction)py_tdb_hnd_chainlock, METH_VARARGS | METH_KEYWORDS },
00544         { "chainunlock", (PyCFunction)py_tdb_hnd_chainunlock, METH_VARARGS | METH_KEYWORDS },
00545         { "lock_bystring", (PyCFunction)py_tdb_hnd_lock_bystring, METH_VARARGS | METH_KEYWORDS },
00546         { "unlock_bystring", (PyCFunction)py_tdb_hnd_unlock_bystring, METH_VARARGS | METH_KEYWORDS },
00547         { NULL }
00548 };
00549 
00550 /* Deallocate a tdb handle object */
00551 
00552 static void tdb_hnd_dealloc(PyObject* self)
00553 {
00554         tdb_hnd_object *hnd = (tdb_hnd_object *)self;
00555 
00556         if (hnd->tdb) {
00557                 tdb_close(hnd->tdb);
00558                 hnd->tdb = NULL;
00559         }
00560 }
00561 
00562 /* Return tdb handle attributes */
00563 
00564 static PyObject *tdb_hnd_getattr(PyObject *self, char *attrname)
00565 {
00566         return Py_FindMethod(tdb_hnd_methods, self, attrname);
00567 }
00568 
00569 static char tdb_hnd_type_doc[] = 
00570 "Python wrapper for tdb.";
00571 
00572 PyTypeObject tdb_hnd_type = {
00573         PyObject_HEAD_INIT(NULL)
00574         0,
00575         "tdb",
00576         sizeof(tdb_hnd_object),
00577         0,
00578         tdb_hnd_dealloc,        /* tp_dealloc*/
00579         0,                      /* tp_print*/
00580         tdb_hnd_getattr,        /* tp_getattr*/
00581         0,                      /* tp_setattr*/
00582         0,                      /* tp_compare*/
00583         0,                      /* tp_repr*/
00584         0,                      /* tp_as_number*/
00585         0,                      /* tp_as_sequence*/
00586         &tdb_mapping,           /* tp_as_mapping*/
00587         0,                      /* tp_hash */
00588         0,                      /* tp_call */
00589         0,                      /* tp_str */
00590         0,                      /* tp_getattro */
00591         0,                      /* tp_setattro */
00592         0,                      /* tp_as_buffer*/
00593         Py_TPFLAGS_DEFAULT,     /* tp_flags */
00594         tdb_hnd_type_doc,       /* tp_doc */
00595 };
00596 
00597 /* Constants */
00598 
00599 static struct const_vals {
00600         char *name;
00601         uint32 value;
00602 } module_const_vals[] = {
00603 
00604         /* Flags for tdb_open() */
00605 
00606         { "TDB_DEFAULT", TDB_DEFAULT },
00607         { "TDB_CLEAR_IF_FIRST", TDB_CLEAR_IF_FIRST },
00608         { "TDB_INTERNAL", TDB_INTERNAL },
00609         { "TDB_NOLOCK", TDB_NOLOCK },
00610         { "TDB_NOMMAP", TDB_NOMMAP },
00611         { "TDB_CONVERT", TDB_CONVERT },
00612         { "TDB_BIGENDIAN", TDB_BIGENDIAN },
00613         
00614         { NULL },
00615 };
00616 
00617 static void const_init(PyObject *dict)
00618 {
00619         struct const_vals *tmp;
00620         PyObject *obj;
00621 
00622         for (tmp = module_const_vals; tmp->name; tmp++) {
00623                 obj = PyInt_FromLong(tmp->value);
00624                 PyDict_SetItemString(dict, tmp->name, obj);
00625                 Py_DECREF(obj);
00626         }
00627 }
00628 
00629 /* Module initialisation */
00630 
00631 void inittdb(void)
00632 {
00633         PyObject *module, *dict;
00634 
00635         /* Initialise module */
00636 
00637         module = Py_InitModule("tdb", tdb_methods);
00638         dict = PyModule_GetDict(module);
00639 
00640         py_tdb_error = PyErr_NewException("tdb.error", NULL, NULL);
00641         PyDict_SetItemString(dict, "error", py_tdb_error);
00642 
00643         /* Initialise policy handle object */
00644 
00645         tdb_hnd_type.ob_type = &PyType_Type;
00646 
00647         PyDict_SetItemString(dict, "tdb.hnd", 
00648                              (PyObject *)&tdb_hnd_type);
00649 
00650         /* Initialise constants */
00651 
00652         const_init(dict);
00653 }

Sambaに対してSat Aug 29 21:23:14 2009に生成されました。  doxygen 1.4.7