direct-io.hg

view tools/python/xen/lowlevel/xs/xs.c @ 7956:52f80621b889

Tidy use of module / package names.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author emellor@leeni.uk.xensource.com
date Mon Nov 21 18:34:25 2005 +0100 (2005-11-21)
parents 6738fd14cb58
children f5f703ec5223
line source
1 /*
2 * Python interface to the Xen Store Daemon.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of version 2.1 of the GNU Lesser General Public
6 * License as published by the Free Software Foundation.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Copyright (C) 2005 Mike Wray Hewlett-Packard
18 * Copyright (C) 2005 Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
19 * Copyright (C) 2005 XenSource Ltd.
20 */
22 #include <Python.h>
24 #include <stdbool.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
32 #include <xenctrl.h>
33 #include "xs.h"
35 /** @file
36 * Python interface to the Xen Store Daemon (xs).
37 */
39 /* Needed for Python versions earlier than 2.3. */
40 #ifndef PyMODINIT_FUNC
41 #define PyMODINIT_FUNC DL_EXPORT(void)
42 #endif
44 #define PKG "xen.lowlevel.xs"
45 #define CLS "xs"
47 /** Python wrapper round an xs handle.
48 */
49 typedef struct XsHandle {
50 PyObject_HEAD;
51 struct xs_handle *xh;
52 PyObject *watches;
53 } XsHandle;
55 static inline struct xs_handle *xshandle(XsHandle *self)
56 {
57 struct xs_handle *xh = self->xh;
58 if (!xh)
59 PyErr_SetString(PyExc_RuntimeError, "invalid xenstore daemon handle");
60 return xh;
61 }
63 static void remove_watch(XsHandle *xsh, PyObject *token);
65 static PyObject *none(bool result);
67 static int parse_transaction_path(XsHandle *self, PyObject *args,
68 struct xs_handle **xh,
69 struct xs_transaction_handle **th,
70 char **path);
73 #define xspy_read_doc "\n" \
74 "Read data from a path.\n" \
75 " transaction [string]: transaction handle\n" \
76 " path [string]: xenstore path\n" \
77 "\n" \
78 "Returns: [string] data read.\n" \
79 " None if key doesn't exist.\n" \
80 "Raises RuntimeError on error.\n" \
81 "\n"
83 static PyObject *xspy_read(XsHandle *self, PyObject *args)
84 {
85 struct xs_handle *xh;
86 struct xs_transaction_handle *th;
87 char *path;
89 char *xsval;
90 unsigned int xsval_n;
92 if (!parse_transaction_path(self, args, &xh, &th, &path))
93 return NULL;
95 Py_BEGIN_ALLOW_THREADS
96 xsval = xs_read(xh, th, path, &xsval_n);
97 Py_END_ALLOW_THREADS
98 if (xsval) {
99 PyObject *val = PyString_FromStringAndSize(xsval, xsval_n);
100 free(xsval);
101 return val;
102 }
103 else {
104 return none(errno == ENOENT);
105 }
106 }
109 #define xspy_write_doc "\n" \
110 "Write data to a path.\n" \
111 " transaction [string]: transaction handle\n" \
112 " path [string] : xenstore path to write to\n." \
113 " data [string] : data to write.\n" \
114 "\n" \
115 "Returns None on success.\n" \
116 "Raises RuntimeError on error.\n" \
117 "\n"
119 static PyObject *xspy_write(XsHandle *self, PyObject *args)
120 {
121 static char *arg_spec = "sss#";
122 struct xs_handle *xh = xshandle(self);
123 struct xs_transaction_handle *th;
124 char *thstr;
125 char *path;
126 char *data;
127 int data_n;
128 bool result;
130 if (!xh)
131 return NULL;
132 if (!PyArg_ParseTuple(args, arg_spec, &thstr, &path, &data, &data_n))
133 return NULL;
135 th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
137 Py_BEGIN_ALLOW_THREADS
138 result = xs_write(xh, th, path, data, data_n);
139 Py_END_ALLOW_THREADS
141 return none(result);
142 }
145 #define xspy_ls_doc "\n" \
146 "List a directory.\n" \
147 " transaction [string]: transaction handle\n" \
148 " path [string]: path to list.\n" \
149 "\n" \
150 "Returns: [string array] list of subdirectory names.\n" \
151 " None if key doesn't exist.\n" \
152 "Raises RuntimeError on error.\n" \
153 "\n"
155 static PyObject *xspy_ls(XsHandle *self, PyObject *args)
156 {
157 struct xs_handle *xh;
158 struct xs_transaction_handle *th;
159 char *path;
161 char **xsval;
162 unsigned int xsval_n;
164 if (!parse_transaction_path(self, args, &xh, &th, &path))
165 return NULL;
167 Py_BEGIN_ALLOW_THREADS
168 xsval = xs_directory(xh, th, path, &xsval_n);
169 Py_END_ALLOW_THREADS
171 if (xsval) {
172 int i;
173 PyObject *val = PyList_New(xsval_n);
174 for (i = 0; i < xsval_n; i++)
175 PyList_SetItem(val, i, PyString_FromString(xsval[i]));
176 free(xsval);
177 return val;
178 }
179 else {
180 return none(errno == ENOENT);
181 }
182 }
185 #define xspy_mkdir_doc "\n" \
186 "Make a directory.\n" \
187 " path [string]: path to directory to create.\n" \
188 "\n" \
189 "Returns None on success.\n" \
190 "Raises RuntimeError on error.\n" \
191 "\n"
193 static PyObject *xspy_mkdir(XsHandle *self, PyObject *args)
194 {
195 struct xs_handle *xh;
196 struct xs_transaction_handle *th;
197 char *path;
199 bool result;
201 if (!parse_transaction_path(self, args, &xh, &th, &path))
202 return NULL;
204 Py_BEGIN_ALLOW_THREADS
205 result = xs_mkdir(xh, th, path);
206 Py_END_ALLOW_THREADS
208 return none(result);
209 }
212 #define xspy_rm_doc "\n" \
213 "Remove a path.\n" \
214 " transaction [string]: transaction handle\n" \
215 " path [string] : path to remove\n" \
216 "\n" \
217 "Returns None on success.\n" \
218 "Raises RuntimeError on error.\n" \
219 "\n"
221 static PyObject *xspy_rm(XsHandle *self, PyObject *args)
222 {
223 struct xs_handle *xh;
224 struct xs_transaction_handle *th;
225 char *path;
227 bool result;
229 if (!parse_transaction_path(self, args, &xh, &th, &path))
230 return NULL;
232 Py_BEGIN_ALLOW_THREADS
233 result = xs_rm(xh, th, path);
234 Py_END_ALLOW_THREADS
236 return none(result || errno == ENOENT);
237 }
240 #define xspy_get_permissions_doc "\n" \
241 "Get the permissions for a path\n" \
242 " transaction [string]: transaction handle\n" \
243 " path [string]: xenstore path.\n" \
244 "\n" \
245 "Returns: permissions array.\n" \
246 "Raises RuntimeError on error.\n" \
247 "\n"
249 static PyObject *xspy_get_permissions(XsHandle *self, PyObject *args)
250 {
251 static char *arg_spec = "ss";
252 char *path = NULL;
254 struct xs_handle *xh = xshandle(self);
255 struct xs_permissions *perms;
256 unsigned int perms_n = 0;
257 int i;
259 struct xs_transaction_handle *th;
260 char *thstr;
262 if (!xh)
263 return NULL;
264 if (!PyArg_ParseTuple(args, arg_spec, &thstr, &path))
265 return NULL;
267 th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
269 Py_BEGIN_ALLOW_THREADS
270 perms = xs_get_permissions(xh, th, path, &perms_n);
271 Py_END_ALLOW_THREADS
273 if (perms) {
274 PyObject *val = PyList_New(perms_n);
275 for (i = 0; i < perms_n; i++, perms++) {
276 PyObject *p = Py_BuildValue("{s:i,s:i,s:i}",
277 "dom", perms->id,
278 "read", perms->perms & XS_PERM_READ,
279 "write",perms->perms & XS_PERM_WRITE);
280 PyList_SetItem(val, i, p);
281 }
283 free(perms);
284 return val;
285 }
286 else {
287 PyErr_SetFromErrno(PyExc_RuntimeError);
288 return NULL;
289 }
290 }
292 #define xspy_set_permissions_doc "\n" \
293 "Set the permissions for a path\n" \
294 " transaction [string]: transaction handle\n" \
295 " path [string] : xenstore path.\n" \
296 " perms : permissions.\n" \
297 "\n" \
298 "Returns None on success.\n" \
299 "Raises RuntimeError on error.\n" \
300 "\n"
302 static PyObject *xspy_set_permissions(XsHandle *self, PyObject *args)
303 {
304 char *path;
305 PyObject *perms;
306 static char *perm_names[] = { "dom", "read", "write", NULL };
307 static char *perm_spec = "i|ii";
309 struct xs_handle *xh = xshandle(self);
310 int i, result;
311 struct xs_permissions *xsperms = NULL;
312 int xsperms_n;
313 PyObject *tuple0 = NULL;
315 struct xs_transaction_handle *th;
316 char *thstr;
318 if (!xh)
319 goto exit;
320 if (!PyArg_ParseTuple(args, "ssO", &thstr, &path, &perms))
321 goto exit;
323 th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
325 if (!PyList_Check(perms)) {
326 PyErr_SetString(PyExc_RuntimeError, "perms must be a list");
327 goto exit;
328 }
329 xsperms_n = PyList_Size(perms);
330 xsperms = calloc(xsperms_n, sizeof(struct xs_permissions));
331 if (!xsperms) {
332 PyErr_SetString(PyExc_RuntimeError, "out of memory");
333 goto exit;
334 }
335 tuple0 = PyTuple_New(0);
336 if (!tuple0)
337 goto exit;
338 for (i = 0; i < xsperms_n; i++) {
339 /* Read/write perms. Set these. */
340 int p_read = 0, p_write = 0;
341 PyObject *p = PyList_GetItem(perms, i);
342 if (!PyArg_ParseTupleAndKeywords(tuple0, p, perm_spec, perm_names,
343 &xsperms[i].id, &p_read, &p_write))
344 goto exit;
345 if (p_read)
346 xsperms[i].perms |= XS_PERM_READ;
347 if (p_write)
348 xsperms[i].perms |= XS_PERM_WRITE;
349 }
350 Py_BEGIN_ALLOW_THREADS
351 result = xs_set_permissions(xh, th, path, xsperms, xsperms_n);
352 Py_END_ALLOW_THREADS
353 if (!result) {
354 PyErr_SetFromErrno(PyExc_RuntimeError);
355 goto exit;
356 }
358 Py_INCREF(Py_None);
359 return Py_None;
361 exit:
362 Py_XDECREF(tuple0);
363 free(xsperms);
364 return NULL;
365 }
367 #define xspy_watch_doc "\n" \
368 "Watch a path, get notifications when it changes.\n" \
369 " path [string] : xenstore path.\n" \
370 " token [string] : returned in watch notification.\n" \
371 "\n" \
372 "Returns None on success.\n" \
373 "Raises RuntimeError on error.\n" \
374 "\n"
376 /* Each 10 bits takes ~ 3 digits, plus one, plus one for nul terminator. */
377 #define MAX_STRLEN(x) ((sizeof(x) * CHAR_BIT + CHAR_BIT-1) / 10 * 3 + 2)
379 static PyObject *xspy_watch(XsHandle *self, PyObject *args)
380 {
381 struct xs_handle *xh = xshandle(self);
382 char *path;
383 PyObject *token;
384 char token_str[MAX_STRLEN(unsigned long) + 1];
385 int result;
386 int i;
388 if (!xh)
389 return NULL;
390 if (!PyArg_ParseTuple(args, "sO", &path, &token))
391 return NULL;
393 /* Note that we have to store the watch token in the xs->watches list
394 before registering the watch with xs_watch, otherwise this function
395 races with xs_read_watch.
396 */
398 for (i = 0; i < PyList_Size(self->watches); i++) {
399 if (PyList_GetItem(self->watches, i) == Py_None) {
400 PySequence_SetItem(self->watches, i, token);
401 break;
402 }
403 }
404 if (i == PyList_Size(self->watches))
405 PyList_Append(self->watches, token);
407 sprintf(token_str, "%li", (unsigned long)token);
408 Py_BEGIN_ALLOW_THREADS
409 result = xs_watch(xh, path, token_str);
410 Py_END_ALLOW_THREADS
412 if (!result)
413 remove_watch(self, token);
415 return none(result);
416 }
419 #define xspy_read_watch_doc "\n" \
420 "Read a watch notification.\n" \
421 "\n" \
422 "Returns: [tuple] (path, token).\n" \
423 "Raises RuntimeError on error.\n" \
424 "\n"
426 static PyObject *xspy_read_watch(XsHandle *self, PyObject *args)
427 {
428 struct xs_handle *xh = xshandle(self);
429 PyObject *val = NULL;
430 char **xsval;
431 PyObject *token;
432 int i;
433 unsigned int num;
435 if (!xh)
436 return NULL;
438 again:
439 Py_BEGIN_ALLOW_THREADS
440 xsval = xs_read_watch(xh, &num);
441 Py_END_ALLOW_THREADS
442 if (!xsval) {
443 PyErr_SetFromErrno(PyExc_RuntimeError);
444 goto exit;
445 }
446 if (sscanf(xsval[XS_WATCH_TOKEN], "%li", (unsigned long *)&token) != 1) {
447 PyErr_SetString(PyExc_RuntimeError, "invalid token");
448 goto exit;
449 }
450 for (i = 0; i < PyList_Size(self->watches); i++) {
451 if (token == PyList_GetItem(self->watches, i))
452 break;
453 }
454 if (i == PyList_Size(self->watches)) {
455 /* We do not have a registered watch for the one that has just fired.
456 Ignore this -- a watch that has been recently deregistered can still
457 have watches in transit. This is a blocking method, so go back to
458 read again.
459 */
460 free(xsval);
461 goto again;
462 }
463 /* Create tuple (path, token). */
464 val = Py_BuildValue("(sO)", xsval[XS_WATCH_PATH], token);
465 exit:
466 free(xsval);
467 return val;
468 }
470 #define xspy_unwatch_doc "\n" \
471 "Stop watching a path.\n" \
472 " path [string] : xenstore path.\n" \
473 " token [string] : token from the watch.\n" \
474 "\n" \
475 "Returns None on success.\n" \
476 "Raises RuntimeError on error.\n" \
477 "\n"
479 static PyObject *xspy_unwatch(XsHandle *self, PyObject *args)
480 {
481 struct xs_handle *xh = xshandle(self);
482 char *path;
483 PyObject *token;
484 char token_str[MAX_STRLEN(unsigned long) + 1];
485 int result;
487 if (!xh)
488 return NULL;
489 if (!PyArg_ParseTuple(args, "sO", &path, &token))
490 return NULL;
492 sprintf(token_str, "%li", (unsigned long)token);
493 Py_BEGIN_ALLOW_THREADS
494 result = xs_unwatch(xh, path, token_str);
495 Py_END_ALLOW_THREADS
497 remove_watch(self, token);
499 return none(result);
500 }
502 #define xspy_transaction_start_doc "\n" \
503 "Start a transaction.\n" \
504 "\n" \
505 "Returns transaction handle on success.\n" \
506 "Raises RuntimeError on error.\n" \
507 "\n"
509 static PyObject *xspy_transaction_start(XsHandle *self)
510 {
511 struct xs_handle *xh = xshandle(self);
512 struct xs_transaction_handle *th;
513 char thstr[MAX_STRLEN(unsigned long) + 1];
515 if (!xh)
516 return NULL;
518 Py_BEGIN_ALLOW_THREADS
519 th = xs_transaction_start(xh);
520 Py_END_ALLOW_THREADS
522 if (th == NULL) {
523 PyErr_SetFromErrno(PyExc_RuntimeError);
524 return NULL;
525 }
527 sprintf(thstr, "%lX", (unsigned long)th);
528 return PyString_FromString(thstr);
529 }
531 #define xspy_transaction_end_doc "\n" \
532 "End the current transaction.\n" \
533 "Attempts to commit the transaction unless abort is true.\n" \
534 " abort [int]: abort flag (default 0).\n" \
535 "\n" \
536 "Returns True on success, False if you need to try again.\n" \
537 "Raises RuntimeError on error.\n" \
538 "\n"
540 static PyObject *xspy_transaction_end(XsHandle *self, PyObject *args,
541 PyObject *kwds)
542 {
543 static char *kwd_spec[] = { "transaction", "abort", NULL };
544 static char *arg_spec = "s|i";
545 int abort = 0;
547 struct xs_handle *xh = xshandle(self);
548 bool result;
550 struct xs_transaction_handle *th;
551 char *thstr;
553 if (!xh)
554 return NULL;
555 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
556 &thstr, &abort))
557 return NULL;
559 th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
561 Py_BEGIN_ALLOW_THREADS
562 result = xs_transaction_end(xh, th, abort);
563 Py_END_ALLOW_THREADS
565 if (result) {
566 Py_INCREF(Py_True);
567 return Py_True;
568 }
569 else if (errno == EAGAIN) {
570 Py_INCREF(Py_False);
571 return Py_False;
572 }
573 else {
574 PyErr_SetFromErrno(PyExc_RuntimeError);
575 return NULL;
576 }
577 }
580 #define xspy_introduce_domain_doc "\n" \
581 "Tell xenstore about a domain so it can talk to it.\n" \
582 " dom [int] : domain id\n" \
583 " page [long] : address of domain's xenstore page\n" \
584 " port [int] : port the domain is using for xenstore\n" \
585 "\n" \
586 "Returns None on success.\n" \
587 "Raises RuntimeError on error.\n" \
588 "\n"
590 static PyObject *xspy_introduce_domain(XsHandle *self, PyObject *args)
591 {
592 domid_t dom;
593 unsigned long page;
594 unsigned int port;
596 struct xs_handle *xh = xshandle(self);
597 bool result = 0;
599 if (!xh)
600 return NULL;
601 if (!PyArg_ParseTuple(args, "ili", &dom, &page, &port))
602 return NULL;
604 Py_BEGIN_ALLOW_THREADS
605 result = xs_introduce_domain(xh, dom, page, port);
606 Py_END_ALLOW_THREADS
608 return none(result);
609 }
612 #define xspy_release_domain_doc "\n" \
613 "Tell xenstore to release its channel to a domain.\n" \
614 "Unless this is done the domain will not be released.\n" \
615 " dom [int]: domain id\n" \
616 "\n" \
617 "Returns None on success.\n" \
618 "Raises RuntimeError on error.\n" \
619 "\n"
621 static PyObject *xspy_release_domain(XsHandle *self, PyObject *args)
622 {
623 domid_t dom;
625 struct xs_handle *xh = xshandle(self);
626 bool result = 0;
628 if (!xh)
629 return NULL;
630 if (!PyArg_ParseTuple(args, "i", &dom))
631 return NULL;
633 Py_BEGIN_ALLOW_THREADS
634 result = xs_release_domain(xh, dom);
635 Py_END_ALLOW_THREADS
637 return none(result);
638 }
641 #define xspy_close_doc "\n" \
642 "Close the connection to xenstore.\n" \
643 "\n" \
644 "Returns None on success.\n" \
645 "Raises RuntimeError on error.\n" \
646 "\n"
648 static PyObject *xspy_close(XsHandle *self)
649 {
650 struct xs_handle *xh = xshandle(self);
651 int i;
653 if (!xh)
654 return NULL;
656 for (i = 0; i < PyList_Size(self->watches); i++) {
657 /* TODO: xs_unwatch watches */
658 PySequence_SetItem(self->watches, i, Py_None);
659 }
661 xs_daemon_close(xh);
662 self->xh = NULL;
664 Py_INCREF(Py_None);
665 return Py_None;
666 }
669 #define xspy_get_domain_path_doc "\n" \
670 "Return store path of domain, whether or not the domain exists.\n" \
671 " domid [int]: domain id\n" \
672 "\n" \
673 "Returns: [string] domain store path.\n" \
674 "Raises RuntimeError on error.\n" \
675 "\n"
677 static PyObject *xspy_get_domain_path(XsHandle *self, PyObject *args)
678 {
679 struct xs_handle *xh = xshandle(self);
680 int domid;
681 char *xsval;
683 if (!xh)
684 return NULL;
685 if (!PyArg_ParseTuple(args, "i", &domid))
686 return NULL;
688 Py_BEGIN_ALLOW_THREADS
689 xsval = xs_get_domain_path(xh, domid);
690 Py_END_ALLOW_THREADS
692 if (xsval) {
693 PyObject *val = PyString_FromString(xsval);
694 free(xsval);
695 return val;
696 }
697 else {
698 return none(errno == ENOENT);
699 }
700 }
703 /**
704 * Remove the given token from the watches list belonging to the given
705 * XsHandle, if present.
706 */
707 static void remove_watch(XsHandle *self, PyObject *token)
708 {
709 int i;
711 for (i = 0; i < PyList_Size(self->watches); i++) {
712 if (PyList_GetItem(self->watches, i) == token) {
713 PySequence_SetItem(self->watches, i, Py_None);
714 return;
715 }
716 }
717 }
720 /**
721 * Parse transaction and path arguments from the given args and kwds,
722 * convert the given self value to an xs_handle, and return all three by
723 * reference.
724 *
725 * @return 1 on success, in which case *xh, *th, and *path are valid, or 0 on
726 * failure.
727 */
728 static int parse_transaction_path(XsHandle *self, PyObject *args,
729 struct xs_handle **xh,
730 struct xs_transaction_handle **th,
731 char **path)
732 {
733 char *thstr;
735 *xh = xshandle(self);
737 if (!xh)
738 return 0;
740 if (!PyArg_ParseTuple(args, "ss", &thstr, path))
741 return 0;
743 *th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
745 return 1;
746 }
749 static PyObject *none(bool result)
750 {
751 if (result) {
752 Py_INCREF(Py_None);
753 return Py_None;
754 }
755 else {
756 PyErr_SetFromErrno(PyExc_RuntimeError);
757 return NULL;
758 }
759 }
762 #define XSPY_METH(_name, _args) { \
763 .ml_name = #_name, \
764 .ml_meth = (PyCFunction) xspy_ ## _name, \
765 .ml_flags = _args, \
766 .ml_doc = xspy_ ## _name ## _doc }
768 static PyMethodDef xshandle_methods[] = {
769 XSPY_METH(read, METH_VARARGS),
770 XSPY_METH(write, METH_VARARGS),
771 XSPY_METH(ls, METH_VARARGS),
772 XSPY_METH(mkdir, METH_VARARGS),
773 XSPY_METH(rm, METH_VARARGS),
774 XSPY_METH(get_permissions, METH_VARARGS),
775 XSPY_METH(set_permissions, METH_VARARGS),
776 XSPY_METH(watch, METH_VARARGS),
777 XSPY_METH(read_watch, METH_NOARGS),
778 XSPY_METH(unwatch, METH_VARARGS),
779 XSPY_METH(transaction_start, METH_NOARGS),
780 XSPY_METH(transaction_end, METH_VARARGS | METH_KEYWORDS),
781 XSPY_METH(introduce_domain, METH_VARARGS),
782 XSPY_METH(release_domain, METH_VARARGS),
783 XSPY_METH(close, METH_NOARGS),
784 XSPY_METH(get_domain_path, METH_VARARGS),
785 { NULL /* Sentinel. */ },
786 };
788 static PyObject *xshandle_getattr(PyObject *self, char *name)
789 {
790 return Py_FindMethod(xshandle_methods, self, name);
791 }
793 static PyObject *
794 xshandle_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
795 {
796 XsHandle *self = (XsHandle *)type->tp_alloc(type, 0);
798 if (self == NULL)
799 return NULL;
801 self->xh = NULL;
802 self->watches = PyList_New(0);
803 if (!self->watches)
804 goto fail;
806 return (PyObject *)self;
807 fail:
808 /* Decreasing the object's reference to 0 will result in xshandle_dealloc
809 being called. */
810 Py_DECREF(self);
811 return NULL;
812 }
814 static int
815 xshandle_init(XsHandle *self, PyObject *args, PyObject *kwds)
816 {
817 static char *kwd_spec[] = { "readonly", NULL };
818 static char *arg_spec = "|i";
819 int readonly = 0;
821 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
822 &readonly))
823 goto fail;
825 self->xh = (readonly ? xs_daemon_open_readonly() : xs_daemon_open());
826 if (!self->xh)
827 goto fail;
829 return 0;
831 fail:
832 PyErr_SetFromErrno(PyExc_RuntimeError);
833 return -1;
834 }
836 static void xshandle_dealloc(XsHandle *self)
837 {
838 if (self->xh) {
839 xs_daemon_close(self->xh);
840 self->xh = NULL;
841 }
843 Py_XDECREF(self->watches);
845 self->ob_type->tp_free((PyObject *)self);
846 }
848 static PyTypeObject xshandle_type = {
849 PyObject_HEAD_INIT(NULL)
850 0,
851 PKG "." CLS,
852 sizeof(XsHandle),
853 0,
854 (destructor)xshandle_dealloc, /* tp_dealloc */
855 NULL, /* tp_print */
856 xshandle_getattr, /* tp_getattr */
857 NULL, /* tp_setattr */
858 NULL, /* tp_compare */
859 NULL, /* tp_repr */
860 NULL, /* tp_as_number */
861 NULL, /* tp_as_sequence */
862 NULL, /* tp_as_mapping */
863 NULL, /* tp_hash */
864 NULL, /* tp_call */
865 NULL, /* tp_str */
866 NULL, /* tp_getattro */
867 NULL, /* tp_setattro */
868 NULL, /* tp_as_buffer */
869 Py_TPFLAGS_DEFAULT, /* tp_flags */
870 "Xenstore connections", /* tp_doc */
871 NULL, /* tp_traverse */
872 NULL, /* tp_clear */
873 NULL, /* tp_richcompare */
874 0, /* tp_weaklistoffset */
875 NULL, /* tp_iter */
876 NULL, /* tp_iternext */
877 xshandle_methods, /* tp_methods */
878 NULL, /* tp_members */
879 NULL, /* tp_getset */
880 NULL, /* tp_base */
881 NULL, /* tp_dict */
882 NULL, /* tp_descr_get */
883 NULL, /* tp_descr_set */
884 0, /* tp_dictoffset */
885 (initproc)xshandle_init, /* tp_init */
886 NULL, /* tp_alloc */
887 xshandle_new, /* tp_new */
888 };
890 static PyMethodDef xs_methods[] = { { NULL } };
892 PyMODINIT_FUNC initxs(void)
893 {
894 PyObject* m;
896 if (PyType_Ready(&xshandle_type) < 0)
897 return;
899 m = Py_InitModule(PKG, xs_methods);
901 if (m == NULL)
902 return;
904 Py_INCREF(&xshandle_type);
905 PyModule_AddObject(m, CLS, (PyObject *)&xshandle_type);
906 }
909 /*
910 * Local variables:
911 * c-indent-level: 4
912 * c-basic-offset: 4
913 * End:
914 */