bf972e9e0e4f771549872398e535fbb0bd5a0d93
[ocaml-libvirt.git] / libvirt / libvirt_c_prologue.c
1 /* OCaml bindings for libvirt.
2  * (C) Copyright 2007 Richard W.M. Jones, Red Hat Inc.
3  * http://libvirt.org/
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version,
9  * with the OCaml linking exception described in ../COPYING.LIB.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
19  */
20
21 /* Please read libvirt/README file. */
22
23 static char *Optstring_val (value strv);
24 typedef value (*Val_ptr_t) (void *);
25 static value Val_opt (void *ptr, Val_ptr_t Val_ptr);
26 /*static value option_default (value option, value deflt);*/
27 static void _raise_virterror (const char *fn) Noreturn;
28 static void not_supported (const char *fn) Noreturn;
29 static value Val_virterror (virErrorPtr err);
30
31 /* Use this around synchronous libvirt API calls to release the OCaml
32  * lock, allowing other threads to run simultaneously.  'code' must not
33  * perform any caml_* calls, run any OCaml code, or raise any exception.
34  * http://web.archive.org/web/20030521020915/http://caml.inria.fr/archives/200106/msg00199.html
35  */
36 #define NONBLOCKING(code)                       \
37   do {                                          \
38     caml_enter_blocking_section ();             \
39     code;                                       \
40     caml_leave_blocking_section ();             \
41   } while (0)
42
43 /* Check error condition from a libvirt function, and automatically raise
44  * an exception if one is found.
45  */
46 #define CHECK_ERROR(cond, fn) \
47   do { if (cond) _raise_virterror (fn); } while (0)
48
49 /*----------------------------------------------------------------------*/
50
51 /* Some notes about the use of custom blocks to store virConnectPtr,
52  * virDomainPtr and virNetworkPtr.
53  *------------------------------------------------------------------
54  *
55  * Libvirt does some tricky reference counting to keep track of
56  * virConnectPtr's, virDomainPtr's and virNetworkPtr's.
57  *
58  * There is only one function which can return a virConnectPtr
59  * (virConnectOpen*) and that allocates a new one each time.
60  *
61  * virDomainPtr/virNetworkPtr's on the other hand can be returned
62  * repeatedly (for the same underlying domain/network), and we must
63  * keep track of each one and explicitly free it with virDomainFree
64  * or virNetworkFree.  If we lose track of one then the reference
65  * counting in libvirt will keep it open.  We therefore wrap these
66  * in a custom block with a finalizer function.
67  *
68  * We also have to allow the user to explicitly free them, in
69  * which case we set the pointer inside the custom block to NULL.
70  * The finalizer notices this and doesn't free the object.
71  *
72  * Domains and networks "belong to" a connection.  We have to avoid
73  * the situation like this:
74  *
75  *   let conn = Connect.open ... in
76  *   let dom = Domain.lookup_by_id conn 0 in
77  *   (* conn goes out of scope and is garbage collected *)
78  *   printf "dom name = %s\n" (Domain.get_name dom)
79  *
80  * The reason is that when conn is garbage collected, virConnectClose
81  * is called and any subsequent operations on dom will fail (in fact
82  * will probably segfault).  To stop this from happening, the OCaml
83  * wrappers store domains (and networks) as explicit (dom, conn)
84  * pairs.
85  *
86  * Update 2008/01: Storage pools and volumes work the same way as
87  * domains and networks.
88  */
89
90 /* Unwrap a custom block. */
91 #define Connect_val(rv) (*((virConnectPtr *)Data_custom_val(rv)))
92 #define Dom_val(rv) (*((virDomainPtr *)Data_custom_val(rv)))
93 #define Net_val(rv) (*((virNetworkPtr *)Data_custom_val(rv)))
94 #define Pol_val(rv) (*((virStoragePoolPtr *)Data_custom_val(rv)))
95 #define Vol_val(rv) (*((virStorageVolPtr *)Data_custom_val(rv)))
96
97 /* Wrap up a pointer to something in a custom block. */
98 static value Val_connect (virConnectPtr conn);
99 static value Val_dom (virDomainPtr dom);
100 static value Val_net (virNetworkPtr net);
101 static value Val_pol (virStoragePoolPtr pool);
102 static value Val_vol (virStorageVolPtr vol);
103
104 /* Domains and networks are stored as pairs (dom/net, conn), so have
105  * some convenience functions for unwrapping and wrapping them.
106  */
107 #define Domain_val(rv) (Dom_val(Field((rv),0)))
108 #define Network_val(rv) (Net_val(Field((rv),0)))
109 #define Pool_val(rv) (Pol_val(Field((rv),0)))
110 #define Volume_val(rv) (Vol_val(Field((rv),0)))
111 #define Connect_domv(rv) (Connect_val(Field((rv),1)))
112 #define Connect_netv(rv) (Connect_val(Field((rv),1)))
113 #define Connect_polv(rv) (Connect_val(Field((rv),1)))
114 #define Connect_volv(rv) (Connect_val(Field((rv),1)))
115
116 static value Val_domain (virDomainPtr dom, value connv);
117 static value Val_network (virNetworkPtr net, value connv);
118 static value Val_pool (virStoragePoolPtr pol, value connv);
119 static value Val_volume (virStorageVolPtr vol, value connv);