ia64/xen-unstable

view tools/python/xen/lowlevel/xs/xs.c @ 6673:63e226a5e272

Add python bindings for watches.
Uses a watcher thread with per-watch registered callbacks.
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Wed Sep 07 12:47:45 2005 +0000 (2005-09-07)
parents dd668f7527cb
children a75b08af8d19
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 *
19 */
21 #include <Python.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
30 #include "xs.h"
32 /** @file
33 * Python interface to the Xen Store Daemon (xs).
34 */
36 /* Needed for Python versions earlier than 2.3. */
37 #ifndef PyMODINIT_FUNC
38 #define PyMODINIT_FUNC DL_EXPORT(void)
39 #endif
41 #define PYPKG "xen.lowlevel.xs"
43 /** Python wrapper round an xs handle.
44 */
45 typedef struct XsHandle {
46 PyObject_HEAD;
47 struct xs_handle *xh;
48 PyObject *watches;
49 } XsHandle;
51 static inline struct xs_handle *xshandle(PyObject *self)
52 {
53 struct xs_handle *xh = ((XsHandle*)self)->xh;
54 if (!xh)
55 PyErr_SetString(PyExc_RuntimeError, "invalid xenstore daemon handle");
56 return xh;
57 }
59 static inline PyObject *pyvalue_int(int val) {
60 return (val
61 ? PyInt_FromLong(val)
62 : PyErr_SetFromErrno(PyExc_RuntimeError));
63 }
65 static inline PyObject *pyvalue_str(char *val) {
66 return (val
67 ? PyString_FromString(val)
68 : PyErr_SetFromErrno(PyExc_RuntimeError));
69 }
71 #define xspy_read_doc "\n" \
72 "Read data from a path.\n" \
73 " path [string]: xenstore path\n" \
74 "\n" \
75 "Returns: [string] data read.\n" \
76 "Raises RuntimeError on error.\n" \
77 "\n"
79 static PyObject *xspy_read(PyObject *self, PyObject *args, PyObject *kwds)
80 {
81 static char *kwd_spec[] = { "path", NULL };
82 static char *arg_spec = "s|";
83 char *path = NULL;
85 struct xs_handle *xh = xshandle(self);
86 char *xsval = NULL;
87 unsigned int xsval_n = 0;
88 PyObject *val = NULL;
90 if (!xh)
91 goto exit;
92 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
93 &path))
94 goto exit;
95 xsval = xs_read(xh, path, &xsval_n);
96 if (!xsval) {
97 val = pyvalue_int(0);
98 goto exit;
99 }
100 val = PyString_FromStringAndSize(xsval, xsval_n);
101 exit:
102 if (xsval)
103 free(xsval);
104 return val;
105 }
107 #define xspy_write_doc "\n" \
108 "Write data to a path.\n" \
109 " path [string] : xenstore path to write to\n." \
110 " data [string] : data to write.\n" \
111 " create [int] : create flag, default 0.\n" \
112 " excl [int] : exclusive flag, default 0.\n" \
113 "\n" \
114 "Returns: [int] 0 on success.\n" \
115 "Raises RuntimeError on error.\n" \
116 "\n"
118 static PyObject *xspy_write(PyObject *self, PyObject *args, PyObject *kwds)
119 {
120 static char *kwd_spec[] = { "path", "data", "create", "excl", NULL };
121 static char *arg_spec = "ss#|ii";
122 char *path = NULL;
123 char *data = NULL;
124 int data_n = 0;
125 int create = 0;
126 int excl = 0;
128 struct xs_handle *xh = xshandle(self);
129 PyObject *val = NULL;
130 int flags = 0;
131 int xsval = 0;
133 if (!xh)
134 goto exit;
135 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
136 &path, &data, &data_n, &create, &excl))
137 goto exit;
138 if (create)
139 flags |= O_CREAT;
140 if (excl)
141 flags |= O_EXCL;
142 xsval = xs_write(xh, path, data, data_n, flags);
143 val = pyvalue_int(xsval);
144 exit:
145 return val;
146 }
148 #define xspy_ls_doc "\n" \
149 "List a directory.\n" \
150 " path [string]: path to list.\n" \
151 "\n" \
152 "Returns: [string array] list of subdirectory names.\n" \
153 "Raises RuntimeError on error.\n" \
154 "\n"
156 static PyObject *xspy_ls(PyObject *self, PyObject *args, PyObject *kwds)
157 {
158 static char *kwd_spec[] = { "path", NULL };
159 static char *arg_spec = "s|";
160 char *path = NULL;
162 struct xs_handle *xh = xshandle(self);
163 PyObject *val = NULL;
164 char **xsval = NULL;
165 unsigned int xsval_n = 0;
166 int i;
168 if (!xh)
169 goto exit;
170 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
171 goto exit;
172 xsval = xs_directory(xh, path, &xsval_n);
173 if (!xsval) {
174 val = pyvalue_int(0);
175 goto exit;
176 }
177 val = PyList_New(xsval_n);
178 for (i = 0; i < xsval_n; i++)
179 PyList_SetItem(val, i, PyString_FromString(xsval[i]));
180 exit:
181 return val;
182 }
184 #define xspy_mkdir_doc "\n" \
185 "Make a directory.\n" \
186 " path [string]: path to directory to create.\n" \
187 "\n" \
188 "Returns: [int] 0 on success.\n" \
189 "Raises RuntimeError on error.\n" \
190 "\n"
192 static PyObject *xspy_mkdir(PyObject *self, PyObject *args, PyObject *kwds)
193 {
194 static char *kwd_spec[] = { "path", NULL };
195 static char *arg_spec = "s|";
196 char *path = NULL;
198 struct xs_handle *xh = xshandle(self);
199 PyObject *val = NULL;
200 int xsval = 0;
202 if (!xh)
203 goto exit;
204 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
205 goto exit;
206 xsval = xs_mkdir(xh, path);
207 val = pyvalue_int(xsval);
208 exit:
209 return val;
210 }
212 #define xspy_rm_doc "\n" \
213 "Remove a path.\n" \
214 " path [string] : path to remove\n" \
215 "\n" \
216 "Returns: [int] 0 on success.\n" \
217 "Raises RuntimeError on error.\n" \
218 "\n"
220 static PyObject *xspy_rm(PyObject *self, PyObject *args, PyObject *kwds)
221 {
222 static char *kwd_spec[] = { "path", NULL };
223 static char *arg_spec = "s|";
224 char *path = NULL;
226 struct xs_handle *xh = xshandle(self);
227 PyObject *val = NULL;
228 int xsval = 0;
230 if (!xh)
231 goto exit;
232 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
233 goto exit;
234 xsval = xs_rm(xh, path);
235 val = pyvalue_int(xsval);
236 exit:
237 return val;
238 }
240 #define xspy_get_permissions_doc "\n" \
241 "Get the permissions for a path\n" \
242 " path [string]: xenstore path.\n" \
243 "\n" \
244 "Returns: permissions array.\n" \
245 "Raises RuntimeError on error.\n" \
246 "\n"
248 static PyObject *xspy_get_permissions(PyObject *self, PyObject *args,
249 PyObject *kwds)
250 {
251 static char *kwd_spec[] = { "path", NULL };
252 static char *arg_spec = "s|";
253 char *path = NULL;
255 struct xs_handle *xh = xshandle(self);
256 PyObject *val = NULL;
257 struct xs_permissions *perms;
258 unsigned int perms_n = 0;
259 int i;
261 if (!xh)
262 goto exit;
263 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
264 goto exit;
265 perms = xs_get_permissions(xh, path, &perms_n);
266 if (!perms) {
267 PyErr_SetFromErrno(PyExc_RuntimeError);
268 goto exit;
269 }
270 val = PyList_New(perms_n);
271 for (i = 0; i < perms_n; i++, perms++) {
272 PyObject *p = Py_BuildValue("{s:i,s:i,s:i}",
273 "dom", perms->id,
274 "read", (perms->perms & XS_PERM_READ),
275 "write", (perms->perms & XS_PERM_WRITE));
276 PyList_SetItem(val, i, p);
277 }
278 exit:
279 return val;
280 }
282 #define xspy_set_permissions_doc "\n" \
283 "Set the permissions for a path\n" \
284 " path [string] : xenstore path.\n" \
285 " perms : permissions.\n" \
286 "\n" \
287 "Returns: [int] 0 on success.\n" \
288 "Raises RuntimeError on error.\n" \
289 "\n"
291 static PyObject *xspy_set_permissions(PyObject *self, PyObject *args,
292 PyObject *kwds)
293 {
294 static char *kwd_spec[] = { "path", "perms", NULL };
295 static char *arg_spec = "sO";
296 char *path = NULL;
297 PyObject *perms = NULL;
298 static char *perm_names[] = { "dom", "read", "write", NULL };
299 static char *perm_spec = "i|iiii";
301 struct xs_handle *xh = xshandle(self);
302 int i, xsval;
303 struct xs_permissions *xsperms = NULL;
304 int xsperms_n = 0;
305 PyObject *tuple0 = NULL;
306 PyObject *val = NULL;
308 if (!xh)
309 goto exit;
310 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
311 &path, &perms))
312 goto exit;
313 if (!PyList_Check(perms)) {
314 PyErr_SetString(PyExc_RuntimeError, "perms must be a list");
315 goto exit;
316 }
317 xsperms_n = PyList_Size(perms);
318 xsperms = calloc(xsperms_n, sizeof(struct xs_permissions));
319 if (!xsperms) {
320 PyErr_SetString(PyExc_RuntimeError, "out of memory");
321 goto exit;
322 }
323 tuple0 = PyTuple_New(0);
324 if (!tuple0)
325 goto exit;
326 for (i = 0; i < xsperms_n; i++) {
327 /* Domain the permissions apply to. */
328 int dom = 0;
329 /* Read/write perms. Set these. */
330 int p_read = 0, p_write = 0;
331 PyObject *p = PyList_GetItem(perms, i);
332 if (!PyArg_ParseTupleAndKeywords(tuple0, p, perm_spec, perm_names,
333 &dom, &p_read, &p_write))
334 goto exit;
335 xsperms[i].id = dom;
336 if (p_read)
337 xsperms[i].perms |= XS_PERM_READ;
338 if (p_write)
339 xsperms[i].perms |= XS_PERM_WRITE;
340 }
341 xsval = xs_set_permissions(xh, path, xsperms, xsperms_n);
342 val = pyvalue_int(xsval);
343 exit:
344 Py_XDECREF(tuple0);
345 if (xsperms)
346 free(xsperms);
347 return val;
348 }
350 #define xspy_watch_doc "\n" \
351 "Watch a path, get notifications when it changes.\n" \
352 " path [string] : xenstore path.\n" \
353 " token [string] : returned in watch notification.\n" \
354 "\n" \
355 "Returns: [int] 0 on success.\n" \
356 "Raises RuntimeError on error.\n" \
357 "\n"
359 /* Each 10 bits takes ~ 3 digits, plus one, plus one for nul terminator. */
360 #define MAX_STRLEN(x) ((sizeof(x) * CHAR_BIT + CHAR_BIT-1) / 10 * 3 + 2)
362 static PyObject *xspy_watch(PyObject *self, PyObject *args, PyObject *kwds)
363 {
364 static char *kwd_spec[] = { "path", "token", NULL };
365 static char *arg_spec = "sO";
366 char *path = NULL;
367 PyObject *token;
368 char token_str[MAX_STRLEN(unsigned long) + 1];
369 int i;
371 XsHandle *xsh = (XsHandle *)self;
372 struct xs_handle *xh = xshandle(self);
373 PyObject *val = NULL;
374 int xsval = 0;
376 if (!xh)
377 goto exit;
378 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
379 &path, &token))
380 goto exit;
381 Py_INCREF(token);
382 sprintf(token_str, "%li", (unsigned long)token);
383 xsval = xs_watch(xh, path, token_str);
384 val = pyvalue_int(xsval);
385 if (xsval) {
386 for (i = 0; i < PyList_Size(xsh->watches); i++) {
387 if (PyList_GetItem(xsh->watches, i) == Py_None) {
388 PyList_SetItem(xsh->watches, i, token);
389 break;
390 }
391 }
392 if (i == PyList_Size(xsh->watches))
393 PyList_Append(xsh->watches, token);
394 } else
395 Py_DECREF(token);
396 exit:
397 return val;
398 }
400 #define xspy_read_watch_doc "\n" \
401 "Read a watch notification.\n" \
402 "The notification must be acknowledged by passing\n" \
403 "the token to acknowledge_watch().\n" \
404 " path [string]: xenstore path.\n" \
405 "\n" \
406 "Returns: [tuple] (path, token).\n" \
407 "Raises RuntimeError on error.\n" \
408 "\n"
410 static PyObject *xspy_read_watch(PyObject *self, PyObject *args,
411 PyObject *kwds)
412 {
413 static char *kwd_spec[] = { NULL };
414 static char *arg_spec = "";
416 XsHandle *xsh = (XsHandle *)self;
417 struct xs_handle *xh = xshandle(self);
418 PyObject *val = NULL;
419 char **xsval = NULL;
420 PyObject *token;
421 int i;
423 if (!xh)
424 goto exit;
425 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
426 goto exit;
427 xsval = xs_read_watch(xh);
428 if (!xsval) {
429 val = PyErr_SetFromErrno(PyExc_RuntimeError);
430 goto exit;
431 }
432 if (sscanf(xsval[1], "%li", (unsigned long *)&token) != 1) {
433 PyErr_SetString(PyExc_RuntimeError, "invalid token");
434 goto exit;
435 }
436 for (i = 0; i < PyList_Size(xsh->watches); i++) {
437 if (token == PyList_GetItem(xsh->watches, i))
438 break;
439 }
440 if (i == PyList_Size(xsh->watches)) {
441 PyErr_SetString(PyExc_RuntimeError, "invalid token");
442 goto exit;
443 }
444 /* Create tuple (path, token). */
445 val = Py_BuildValue("(sO)", xsval[0], token);
446 exit:
447 if (xsval)
448 free(xsval);
449 return val;
450 }
452 #define xspy_acknowledge_watch_doc "\n" \
453 "Acknowledge a watch notification that has been read.\n" \
454 " token [string] : from the watch notification\n" \
455 "\n" \
456 "Returns: [int] 0 on success.\n" \
457 "Raises RuntimeError on error.\n" \
458 "\n"
460 static PyObject *xspy_acknowledge_watch(PyObject *self, PyObject *args,
461 PyObject *kwds)
462 {
463 static char *kwd_spec[] = { "token", NULL };
464 static char *arg_spec = "O";
465 PyObject *token;
466 char token_str[MAX_STRLEN(unsigned long) + 1];
468 struct xs_handle *xh = xshandle(self);
469 PyObject *val = NULL;
470 int xsval = 0;
472 if (!xh)
473 goto exit;
474 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &token))
475 goto exit;
476 sprintf(token_str, "%li", (unsigned long)token);
477 xsval = xs_acknowledge_watch(xh, token_str);
478 val = pyvalue_int(xsval);
479 exit:
480 return val;
481 }
483 #define xspy_unwatch_doc "\n" \
484 "Stop watching a path.\n" \
485 " path [string] : xenstore path.\n" \
486 " token [string] : token from the watch.\n" \
487 "\n" \
488 "Returns: [int] 0 on success.\n" \
489 "Raises RuntimeError on error.\n" \
490 "\n"
492 static PyObject *xspy_unwatch(PyObject *self, PyObject *args, PyObject *kwds)
493 {
494 static char *kwd_spec[] = { "path", "token", NULL };
495 static char *arg_spec = "sO";
496 char *path = NULL;
497 PyObject *token;
498 char token_str[MAX_STRLEN(unsigned long) + 1];
499 int i;
501 XsHandle *xsh = (XsHandle *)self;
502 struct xs_handle *xh = xshandle(self);
503 PyObject *val = NULL;
504 int xsval = 0;
506 if (!xh)
507 goto exit;
508 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path,
509 &token))
510 goto exit;
511 sprintf(token_str, "%li", (unsigned long)token);
512 xsval = xs_unwatch(xh, path, token_str);
513 val = pyvalue_int(xsval);
514 for (i = 0; i < PyList_Size(xsh->watches); i++) {
515 if (token == PyList_GetItem(xsh->watches, i)) {
516 Py_INCREF(Py_None);
517 PyList_SetItem(xsh->watches, i, Py_None);
518 break;
519 }
520 }
521 exit:
522 return val;
523 }
525 #define xspy_transaction_start_doc "\n" \
526 "Start a transaction on a path.\n" \
527 "Only one transaction can be active at a time.\n" \
528 " path [string]: xenstore path.\n" \
529 "\n" \
530 "Returns: [int] 0 on success.\n" \
531 "Raises RuntimeError on error.\n" \
532 "\n"
534 static PyObject *xspy_transaction_start(PyObject *self, PyObject *args,
535 PyObject *kwds)
536 {
537 static char *kwd_spec[] = { "path", NULL };
538 static char *arg_spec = "s|";
539 char *path = NULL;
541 struct xs_handle *xh = xshandle(self);
542 PyObject *val = NULL;
543 int xsval = 0;
545 if (!xh)
546 goto exit;
547 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
548 goto exit;
549 xsval = xs_transaction_start(xh, path);
550 val = pyvalue_int(xsval);
551 exit:
552 return val;
553 }
555 #define xspy_transaction_end_doc "\n" \
556 "End the current transaction.\n" \
557 "Attempts to commit the transaction unless abort is true.\n" \
558 " abort [int]: abort flag (default 0).\n" \
559 "\n" \
560 "Returns: [int] 0 on success.\n" \
561 "Raises RuntimeError on error.\n" \
562 "\n"
564 static PyObject *xspy_transaction_end(PyObject *self, PyObject *args,
565 PyObject *kwds)
566 {
567 static char *kwd_spec[] = { "abort", NULL };
568 static char *arg_spec = "|i";
569 int abort = 0;
571 struct xs_handle *xh = xshandle(self);
572 PyObject *val = NULL;
573 int xsval = 0;
575 if (!xh)
576 goto exit;
577 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &abort))
578 goto exit;
579 xsval = xs_transaction_end(xh, abort);
580 val = pyvalue_int(xsval);
581 exit:
582 return val;
583 }
585 #define xspy_introduce_domain_doc "\n" \
586 "Tell xenstore about a domain so it can talk to it.\n" \
587 " dom [int] : domain id\n" \
588 " page [long] : address of domain's xenstore page\n" \
589 " port [int] : port the domain is using for xenstore\n" \
590 " path [string]: path to the domain's data in xenstore\n" \
591 "\n" \
592 "Returns: [int] 0 on success.\n" \
593 "Raises RuntimeError on error.\n" \
594 "\n"
596 static PyObject *xspy_introduce_domain(PyObject *self, PyObject *args,
597 PyObject *kwds)
598 {
599 static char *kwd_spec[] = { "dom", "page", "port", "path", NULL };
600 static char *arg_spec = "iiis|";
601 domid_t dom = 0;
602 unsigned long page = 0;
603 unsigned int port = 0;
604 char *path = NULL;
606 struct xs_handle *xh = xshandle(self);
607 PyObject *val = NULL;
608 int xsval = 0;
610 if (!xh)
611 goto exit;
612 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
613 &dom, &page, &port, &path))
614 goto exit;
615 xsval = xs_introduce_domain(xh, dom, page, port, path);
616 val = pyvalue_int(xsval);
617 exit:
618 return val;
619 }
621 #define xspy_release_domain_doc "\n" \
622 "Tell xenstore to release its channel to a domain.\n" \
623 "Unless this is done the domain will not be released.\n" \
624 " dom [int]: domain id\n" \
625 "\n" \
626 "Returns: [int] 0 on success.\n" \
627 "Raises RuntimeError on error.\n" \
628 "\n"
630 static PyObject *xspy_release_domain(PyObject *self, PyObject *args,
631 PyObject *kwds)
632 {
633 static char *kwd_spec[] = { "dom", NULL };
634 static char *arg_spec = "i|";
635 domid_t dom;
637 struct xs_handle *xh = xshandle(self);
638 PyObject *val = NULL;
639 int xsval = 0;
641 if (!xh)
642 goto exit;
643 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
644 &dom))
645 goto exit;
646 xsval = xs_release_domain(xh, dom);
647 val = pyvalue_int(xsval);
648 exit:
649 return val;
650 }
652 #define xspy_close_doc "\n" \
653 "Close the connection to xenstore.\n" \
654 "\n" \
655 "Returns: [int] 0 on success.\n" \
656 "Raises RuntimeError on error.\n" \
657 "\n"
659 static PyObject *xspy_close(PyObject *self, PyObject *args, PyObject *kwds)
660 {
661 static char *kwd_spec[] = { NULL };
662 static char *arg_spec = "";
663 int i;
665 XsHandle *xsh = (XsHandle *)self;
666 struct xs_handle *xh = xshandle(self);
667 PyObject *val = NULL;
668 int xsval = 1;
670 if (!xh)
671 goto exit;
672 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
673 goto exit;
674 for (i = 0; i < PyList_Size(xsh->watches); i++) {
675 /* TODO: xs_unwatch watches */
676 Py_INCREF(Py_None);
677 PyList_SetItem(xsh->watches, i, Py_None);
678 }
679 xs_daemon_close(xh);
680 xsh->xh = NULL;
681 val = pyvalue_int(xsval);
682 exit:
683 return val;
684 }
686 #define xspy_shutdown_doc "\n" \
687 "Shutdown the xenstore daemon.\n" \
688 "\n" \
689 "Returns: [int] 0 on success.\n" \
690 "Raises RuntimeError on error.\n" \
691 "\n"
693 static PyObject *xspy_shutdown(PyObject *self, PyObject *args, PyObject *kwds)
694 {
695 static char *kwd_spec[] = { NULL };
696 static char *arg_spec = "";
698 struct xs_handle *xh = xshandle(self);
699 PyObject *val = NULL;
700 int xsval = 0;
702 if (!xh)
703 goto exit;
704 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
705 goto exit;
706 xsval = xs_shutdown(xh);
707 val = pyvalue_int(xsval);
708 exit:
709 return val;
710 }
712 #define xspy_fileno_doc "\n" \
713 "Get the file descriptor of the xenstore socket.\n" \
714 "Allows an xs object to be passed to select().\n" \
715 "\n" \
716 "Returns: [int] file descriptor.\n" \
717 "\n"
719 static PyObject *xspy_fileno(PyObject *self, PyObject *args, PyObject *kwds)
720 {
721 static char *kwd_spec[] = { NULL };
722 static char *arg_spec = "";
724 struct xs_handle *xh = xshandle(self);
725 PyObject *val = NULL;
727 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
728 goto exit;
729 val = PyInt_FromLong((xh ? xs_fileno(xh) : -1));
730 exit:
731 return val;
732 }
734 #define XSPY_METH(_name) { \
735 .ml_name = #_name, \
736 .ml_meth = (PyCFunction) xspy_ ## _name, \
737 .ml_flags = (METH_VARARGS | METH_KEYWORDS), \
738 .ml_doc = xspy_ ## _name ## _doc }
740 static PyMethodDef xshandle_methods[] = {
741 XSPY_METH(read),
742 XSPY_METH(write),
743 XSPY_METH(ls),
744 XSPY_METH(mkdir),
745 XSPY_METH(rm),
746 XSPY_METH(get_permissions),
747 XSPY_METH(set_permissions),
748 XSPY_METH(watch),
749 XSPY_METH(read_watch),
750 XSPY_METH(acknowledge_watch),
751 XSPY_METH(unwatch),
752 XSPY_METH(transaction_start),
753 XSPY_METH(transaction_end),
754 XSPY_METH(introduce_domain),
755 XSPY_METH(release_domain),
756 XSPY_METH(close),
757 XSPY_METH(shutdown),
758 XSPY_METH(fileno),
759 { /* Terminator. */ },
760 };
762 static PyObject *xshandle_getattr(PyObject *self, char *name)
763 {
764 PyObject *val = NULL;
765 val = Py_FindMethod(xshandle_methods, self, name);
766 return val;
767 }
769 static void xshandle_dealloc(PyObject *self)
770 {
771 XsHandle *xh = (XsHandle*)self;
772 if (xh->xh) {
773 xs_daemon_close(xh->xh);
774 xh->xh = NULL;
775 }
776 PyObject_Del(self);
777 }
779 static PyTypeObject xshandle_type = {
780 PyObject_HEAD_INIT(&PyType_Type)
781 0,
782 "xshandle",
783 sizeof(XsHandle),
784 0,
785 xshandle_dealloc, /* tp_dealloc */
786 NULL, /* tp_print */
787 xshandle_getattr, /* tp_getattr */
788 NULL, /* tp_setattr */
789 NULL, /* tp_compare */
790 NULL, /* tp_repr */
791 NULL, /* tp_as_number */
792 NULL, /* tp_as_sequence */
793 NULL, /* tp_as_mapping */
794 NULL /* tp_hash */
795 };
797 static PyObject *xshandle_open(PyObject *self, PyObject *args, PyObject *kwds)
798 {
799 static char *kwd_spec[] = { "readonly", NULL };
800 static char *arg_spec = "|i";
801 int readonly = 0;
803 XsHandle *xsh = NULL;
804 PyObject *val = NULL;
806 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
807 &readonly))
808 return NULL;
810 xsh = PyObject_New(XsHandle, &xshandle_type);
811 if (!xsh)
812 return NULL;
813 xsh->watches = PyList_New(0);
814 if (!xsh->watches)
815 goto exit;
816 xsh->xh = (readonly ? xs_daemon_open_readonly() : xs_daemon_open());
817 if (!xsh->xh) {
818 Py_DECREF(xsh->watches);
819 goto exit;
820 }
821 val = (PyObject *)xsh;
822 return val;
823 exit:
824 PyObject_Del(xsh);
825 return NULL;
826 }
828 static PyMethodDef xs_methods[] = {
829 { .ml_name = "open",
830 .ml_meth = (PyCFunction)xshandle_open,
831 .ml_flags = (METH_VARARGS | METH_KEYWORDS),
832 .ml_doc = "\n"
833 "Open a connection to the xenstore daemon.\n"
834 "Returns: xs connection object.\n"
835 "Raises RuntimeError on error.\n"
836 "\n"
837 },
838 { /* Terminator. */ }
839 };
841 PyMODINIT_FUNC initxs (void)
842 {
843 PyObject *module;
845 module = Py_InitModule(PYPKG, xs_methods);
846 }