Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
groongaql.c
Go to the documentation of this file.
1 /* Copyright(C) 2007 Brazil
2 
3  This library is free software; you can redistribute it and/or
4  modify it under the terms of the GNU Lesser General Public
5  License as published by the Free Software Foundation; either
6  version 2.1 of the License, or (at your option) any later version.
7 
8  This library is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  Lesser General Public License for more details.
12 
13  You should have received a copy of the GNU Lesser General Public
14  License along with this library; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 #include <Python.h>
18 #include <groonga.h>
19 
20 /* TODO: use exception */
21 
22 typedef struct {
23  PyObject_HEAD
25  int closed;
27 
28 static PyTypeObject groongaql_ContextType;
29 
30 /* Object methods */
31 
32 static PyObject *
33 groongaql_ContextObject_new(PyTypeObject *type, PyObject *args, PyObject *keywds)
34 {
35  grn_rc rc;
36  int flags;
37  grn_encoding encoding;
39 
40  static char *kwlist[] = {"flags", "encoding", NULL};
41 
42  if (!PyArg_ParseTupleAndKeywords(args, keywds, "ii", kwlist,
43  &flags, &encoding)) {
44  return NULL;
45  }
46  if (!(self = (groongaql_ContextObject *)type->tp_alloc(type, 0))) {
47  return NULL;
48  }
49  Py_BEGIN_ALLOW_THREADS
50  rc = grn_ctx_init(&self->ctx, flags);
51  GRN_CTX_SET_ENCODING(&self->ctx, encoding);
52  Py_END_ALLOW_THREADS
53  if (rc) {
54  self->ob_type->tp_free(self);
55  return NULL;
56  }
57  self->closed = 0;
58  return (PyObject *)self;
59 }
60 
61 static void
62 groongaql_ContextObject_dealloc(groongaql_ContextObject *self)
63 {
64  if (!self->closed) {
65  Py_BEGIN_ALLOW_THREADS
66  grn_ctx_fin(&self->ctx);
67  Py_END_ALLOW_THREADS
68  }
69  self->ob_type->tp_free(self);
70 }
71 
72 /* Class methods */
73 
74 /* instance methods */
75 
76 static PyObject *
77 groongaql_ContextClass_ql_connect(groongaql_ContextObject *self, PyObject *args, PyObject *keywds)
78 {
79  grn_rc rc;
80  int port, flags;
81  const char *host;
82  static char *kwlist[] = {"host", "port", "flags", NULL};
83 
84  if (!PyArg_ParseTupleAndKeywords(args, keywds, "sii", kwlist,
85  &host, &port, &flags)) {
86  return NULL;
87  }
88  if (self->closed) { return NULL; }
89  Py_BEGIN_ALLOW_THREADS
90  rc = grn_ctx_connect(&self->ctx, host, port, flags);
91  Py_END_ALLOW_THREADS
92  return Py_BuildValue("i", rc);
93 }
94 
95 static PyObject *
96 groongaql_Context_ql_send(groongaql_ContextObject *self, PyObject *args, PyObject *keywds)
97 {
98  grn_rc rc;
99  char *str;
100  int str_len, flags;
101  static char *kwlist[] = {"str", "flags", NULL};
102 
103  if (!PyArg_ParseTupleAndKeywords(args, keywds, "s#i", kwlist,
104  &str,
105  &str_len,
106  &flags)) {
107  return NULL;
108  }
109  if (self->closed) { return NULL; }
110  Py_BEGIN_ALLOW_THREADS
111  rc = grn_ctx_send(&self->ctx, str, str_len, flags);
112  Py_END_ALLOW_THREADS
113  return Py_BuildValue("i", rc);
114 }
115 
116 static PyObject *
117 groongaql_Context_ql_recv(groongaql_ContextObject *self)
118 {
119  grn_rc rc;
120  int flags;
121  char *str;
122  unsigned int str_len;
123 
124  if (self->closed) { return NULL; }
125  Py_BEGIN_ALLOW_THREADS
126  rc = grn_ctx_recv(&self->ctx, &str, &str_len, &flags);
127  Py_END_ALLOW_THREADS
128  return Py_BuildValue("(is#i)", rc, str, str_len, flags);
129 }
130 
131 static PyObject *
132 groongaql_Context_fin(groongaql_ContextObject *self)
133 {
134  grn_rc rc;
135 
136  if (self->closed) { return NULL; }
137  Py_BEGIN_ALLOW_THREADS
138  rc = grn_ctx_fin(&self->ctx);
139  Py_END_ALLOW_THREADS
140  if (!rc) {
141  self->closed = 1;
142  }
143  return Py_BuildValue("i", rc);
144 }
145 
146 static PyObject *
147 groongaql_Context_ql_info_get(groongaql_ContextObject *self)
148 {
149  grn_rc rc;
150  grn_ctx_info info;
151 
152  if (self->closed) { return NULL; }
153  rc = grn_ctx_info_get(&self->ctx, &info);
154  /* TODO: handling unsigned int properlly */
155  /* TODO: get outbuf */
156  return Py_BuildValue("{s:i,s:i,s:i}",
157  "rc", rc,
158  "com_status", info.com_status,
159  /* "outbuf", info.outbuf, */
160  "stat", info.stat
161  );
162 }
163 
164 /* methods of classes */
165 
166 static PyMethodDef groongaql_Context_methods[] = {
167  {"ql_connect", (PyCFunction)groongaql_ContextClass_ql_connect,
168  METH_VARARGS | METH_KEYWORDS,
169  "Create a remote groonga context."},
170  {"ql_send", (PyCFunction)groongaql_Context_ql_send,
171  METH_VARARGS | METH_KEYWORDS,
172  "Send message to context."},
173  {"ql_recv", (PyCFunction)groongaql_Context_ql_recv,
174  METH_NOARGS,
175  "Receive message from context."},
176  {"fin", (PyCFunction)groongaql_Context_fin,
177  METH_NOARGS,
178  "Release groonga context."},
179  {"ql_info_get", (PyCFunction)groongaql_Context_ql_info_get,
180  METH_NOARGS,
181  "Get QL context information."},
182  {NULL, NULL, 0, NULL}
183 };
184 
185 static PyMethodDef module_methods[] = {
186  {NULL, NULL, 0, NULL}
187 };
188 
189 /* type objects */
190 
191 static PyTypeObject groongaql_ContextType = {
192  PyObject_HEAD_INIT(NULL)
193  0, /* ob_size */
194  "groongaql.Context", /* tp_name */
195  sizeof(groongaql_ContextObject), /* tp_basicsize */
196  0, /* tp_itemsize */
197  (destructor)groongaql_ContextObject_dealloc, /* tp_dealloc */
198  0, /* tp_print */
199  0, /* tp_getattr */
200  0, /* tp_setattr */
201  0, /* tp_compare */
202  0, /* tp_repr */
203  0, /* tp_as_number */
204  0, /* tp_as_sequence */
205  0, /* tp_as_mapping */
206  0, /* tp_hash */
207  0, /* tp_call */
208  0, /* tp_str */
209  0, /* tp_getattro */
210  0, /* tp_setattro */
211  0, /* tp_as_buffer */
212  Py_TPFLAGS_DEFAULT, /* tp_flags */
213  "groonga Context objects", /* tp_doc */
214  0, /* tp_traverse */
215  0, /* tp_clear */
216  0, /* tp_richcompare */
217  0, /* tp_weaklistoffset */
218  0, /* tp_iter */
219  0, /* tp_iternext */
220  groongaql_Context_methods, /* tp_methods */
221  0, /* tp_members */
222  0, /* tp_getset */
223  0, /* tp_base */
224  0, /* tp_dict */
225  0, /* tp_descr_get */
226  0, /* tp_descr_set */
227  0, /* tp_dictoffset */
228  0, /* tp_init */
229  0, /* tp_alloc */
230  groongaql_ContextObject_new, /* tp_new */
231 };
232 
233 /* consts */
234 
235 typedef struct _ConstPair {
236  const char *name;
237  int value;
238 } ConstPair;
239 
240 static ConstPair consts[] = {
241  /* grn_rc */
242  {"SUCCESS", GRN_SUCCESS},
243  {"END_OF_DATA", GRN_END_OF_DATA},
244  {"UNKNOWN_ERROR", GRN_UNKNOWN_ERROR},
245  {"OPERATION_NOT_PERMITTED", GRN_OPERATION_NOT_PERMITTED},
246  {"NO_SUCH_FILE_OR_DIRECTORY", GRN_NO_SUCH_FILE_OR_DIRECTORY},
247  {"NO_SUCH_PROCESS", GRN_NO_SUCH_PROCESS},
248  {"INTERRUPTED_FUNCTION_CALL", GRN_INTERRUPTED_FUNCTION_CALL},
249  {"INPUT_OUTPUT_ERROR", GRN_INPUT_OUTPUT_ERROR},
250  {"NO_SUCH_DEVICE_OR_ADDRESS", GRN_NO_SUCH_DEVICE_OR_ADDRESS},
251  {"ARG_LIST_TOO_LONG", GRN_ARG_LIST_TOO_LONG},
252  {"EXEC_FORMAT_ERROR", GRN_EXEC_FORMAT_ERROR},
253  {"BAD_FILE_DESCRIPTOR", GRN_BAD_FILE_DESCRIPTOR},
254  {"NO_CHILD_PROCESSES", GRN_NO_CHILD_PROCESSES},
255  {"RESOURCE_TEMPORARILY_UNAVAILABLE", GRN_RESOURCE_TEMPORARILY_UNAVAILABLE},
256  {"NOT_ENOUGH_SPACE", GRN_NOT_ENOUGH_SPACE},
257  {"PERMISSION_DENIED", GRN_PERMISSION_DENIED},
258  {"BAD_ADDRESS", GRN_BAD_ADDRESS},
259  {"RESOURCE_BUSY", GRN_RESOURCE_BUSY},
260  {"FILE_EXISTS", GRN_FILE_EXISTS},
261  {"IMPROPER_LINK", GRN_IMPROPER_LINK},
262  {"NO_SUCH_DEVICE", GRN_NO_SUCH_DEVICE},
263  {"NOT_A_DIRECTORY", GRN_NOT_A_DIRECTORY},
264  {"IS_A_DIRECTORY", GRN_IS_A_DIRECTORY},
265  {"INVALID_ARGUMENT", GRN_INVALID_ARGUMENT},
266  {"TOO_MANY_OPEN_FILES_IN_SYSTEM", GRN_TOO_MANY_OPEN_FILES_IN_SYSTEM},
267  {"TOO_MANY_OPEN_FILES", GRN_TOO_MANY_OPEN_FILES},
268  {"INAPPROPRIATE_I_O_CONTROL_OPERATION", GRN_INAPPROPRIATE_I_O_CONTROL_OPERATION},
269  {"FILE_TOO_LARGE", GRN_FILE_TOO_LARGE},
270  {"NO_SPACE_LEFT_ON_DEVICE", GRN_NO_SPACE_LEFT_ON_DEVICE},
271  {"INVALID_SEEK", GRN_INVALID_SEEK},
272  {"READ_ONLY_FILE_SYSTEM", GRN_READ_ONLY_FILE_SYSTEM},
273  {"TOO_MANY_LINKS", GRN_TOO_MANY_LINKS},
274  {"BROKEN_PIPE", GRN_BROKEN_PIPE},
275  {"DOMAIN_ERROR", GRN_DOMAIN_ERROR},
276  {"RESULT_TOO_LARGE", GRN_RESULT_TOO_LARGE},
277  {"RESOURCE_DEADLOCK_AVOIDED", GRN_RESOURCE_DEADLOCK_AVOIDED},
278  {"NO_MEMORY_AVAILABLE", GRN_NO_MEMORY_AVAILABLE},
279  {"FILENAME_TOO_LONG", GRN_FILENAME_TOO_LONG},
280  {"NO_LOCKS_AVAILABLE", GRN_NO_LOCKS_AVAILABLE},
281  {"FUNCTION_NOT_IMPLEMENTED", GRN_FUNCTION_NOT_IMPLEMENTED},
282  {"DIRECTORY_NOT_EMPTY", GRN_DIRECTORY_NOT_EMPTY},
283  {"ILLEGAL_BYTE_SEQUENCE", GRN_ILLEGAL_BYTE_SEQUENCE},
284  {"SOCKET_NOT_INITIALIZED", GRN_SOCKET_NOT_INITIALIZED},
285  {"OPERATION_WOULD_BLOCK", GRN_OPERATION_WOULD_BLOCK},
286  {"ADDRESS_IS_NOT_AVAILABLE", GRN_ADDRESS_IS_NOT_AVAILABLE},
287  {"NETWORK_IS_DOWN", GRN_NETWORK_IS_DOWN},
288  {"NO_BUFFER", GRN_NO_BUFFER},
289  {"SOCKET_IS_ALREADY_CONNECTED", GRN_SOCKET_IS_ALREADY_CONNECTED},
290  {"SOCKET_IS_NOT_CONNECTED", GRN_SOCKET_IS_NOT_CONNECTED},
291  {"SOCKET_IS_ALREADY_SHUTDOWNED", GRN_SOCKET_IS_ALREADY_SHUTDOWNED},
292  {"OPERATION_TIMEOUT", GRN_OPERATION_TIMEOUT},
293  {"CONNECTION_REFUSED", GRN_CONNECTION_REFUSED},
294  {"RANGE_ERROR", GRN_RANGE_ERROR},
295  {"TOKENIZER_ERROR", GRN_TOKENIZER_ERROR},
296  {"FILE_CORRUPT", GRN_FILE_CORRUPT},
297  {"INVALID_FORMAT", GRN_INVALID_FORMAT},
298  {"OBJECT_CORRUPT", GRN_OBJECT_CORRUPT},
299  {"TOO_MANY_SYMBOLIC_LINKS", GRN_TOO_MANY_SYMBOLIC_LINKS},
300  {"NOT_SOCKET", GRN_NOT_SOCKET},
301  {"OPERATION_NOT_SUPPORTED", GRN_OPERATION_NOT_SUPPORTED},
302  {"ADDRESS_IS_IN_USE", GRN_ADDRESS_IS_IN_USE},
303  {"ZLIB_ERROR", GRN_ZLIB_ERROR},
304  {"LZO_ERROR", GRN_LZO_ERROR},
305  /* grn_encoding */
306  {"ENC_DEFAULT", GRN_ENC_DEFAULT},
307  {"ENC_NONE", GRN_ENC_NONE},
308  {"ENC_EUC_JP", GRN_ENC_EUC_JP},
309  {"ENC_UTF8", GRN_ENC_UTF8},
310  {"ENC_SJIS", GRN_ENC_SJIS},
311  {"ENC_LATIN1", GRN_ENC_LATIN1},
312  {"ENC_KOI8R", GRN_ENC_KOI8R},
313  /* grn_ctx flags */
314  {"CTX_USE_QL", GRN_CTX_USE_QL},
315  {"CTX_BATCH_MODE", GRN_CTX_BATCH_MODE},
316  {"CTX_MORE", GRN_CTX_MORE},
317  {"CTX_TAIL", GRN_CTX_TAIL},
318  {"CTX_HEAD", GRN_CTX_HEAD},
319  {"CTX_QUIET", GRN_CTX_QUIET},
320  {"CTX_QUIT", GRN_CTX_QUIT},
321  {"CTX_FIN", GRN_CTX_FIN},
322  /* end */
323  {NULL, 0}
324 };
325 
326 #ifndef PyMODINIT_FUNC
327 #define PyMODINIT_FUNC void
328 #endif
331 {
332  unsigned int i;
333  PyObject *m, *dict;
334 
335  if (!(m = Py_InitModule3("groongaql", module_methods,
336  "groonga ql module."))) {
337  goto exit;
338  }
339  grn_init();
340 
341  /* register classes */
342 
343  if (PyType_Ready(&groongaql_ContextType) < 0) { goto exit; }
344  Py_INCREF(&groongaql_ContextType);
345  PyModule_AddObject(m, "Context", (PyObject *)&groongaql_ContextType);
346 
347  /* register consts */
348 
349  if (!(dict = PyModule_GetDict(m))) { goto exit; }
350 
351  for (i = 0; consts[i].name; i++) {
352  PyObject *v;
353  if (!(v = PyInt_FromLong(consts[i].value))) {
354  goto exit;
355  }
356  PyDict_SetItemString(dict, consts[i].name, v);
357  Py_DECREF(v);
358  }
359  if (Py_AtExit((void (*)(void))grn_fin)) { goto exit; }
360 exit:
361  if (PyErr_Occurred()) {
362  PyErr_SetString(PyExc_ImportError, "groongaql: init failed");
363  }
364 }