ruby-libvirt 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/ext/libvirt/common.c CHANGED
@@ -2,6 +2,7 @@
2
2
  * common.c: Common utilities for the ruby libvirt bindings
3
3
  *
4
4
  * Copyright (C) 2007,2010 Red Hat Inc.
5
+ * Copyright (C) 2013 Chris Lalancette <clalancette@gmail.com>
5
6
  *
6
7
  * This library is free software; you can redistribute it and/or
7
8
  * modify it under the terms of the GNU Lesser General Public
@@ -26,68 +27,65 @@
26
27
  #include <libvirt/libvirt.h>
27
28
  #include <libvirt/virterror.h>
28
29
  #include "common.h"
30
+ #include "connect.h"
29
31
 
30
32
  struct rb_exc_new2_arg {
31
33
  VALUE error;
32
34
  char *msg;
33
35
  };
34
36
 
35
- static VALUE rb_exc_new2_wrap(VALUE arg) {
37
+ static VALUE ruby_libvirt_exc_new2_wrap(VALUE arg)
38
+ {
36
39
  struct rb_exc_new2_arg *e = (struct rb_exc_new2_arg *)arg;
37
40
 
38
41
  return rb_exc_new2(e->error, e->msg);
39
42
  }
40
43
 
41
- VALUE rb_ary_new2_wrap(VALUE arg) {
44
+ VALUE ruby_libvirt_ary_new2_wrap(VALUE arg)
45
+ {
42
46
  return rb_ary_new2(*((int *)arg));
43
47
  }
44
48
 
45
- VALUE rb_ary_push_wrap(VALUE arg) {
46
- struct rb_ary_push_arg *e = (struct rb_ary_push_arg *)arg;
49
+ VALUE ruby_libvirt_ary_push_wrap(VALUE arg)
50
+ {
51
+ struct ruby_libvirt_ary_push_arg *e = (struct ruby_libvirt_ary_push_arg *)arg;
47
52
 
48
53
  return rb_ary_push(e->arr, e->value);
49
54
  }
50
55
 
51
- VALUE rb_str_new2_wrap(VALUE arg) {
52
- char **str = (char **)arg;
53
-
54
- return rb_str_new2(*str);
55
- }
56
-
57
- VALUE rb_ary_entry_wrap(VALUE arg) {
58
- struct rb_ary_entry_arg *e = (struct rb_ary_entry_arg *)arg;
56
+ VALUE ruby_libvirt_ary_store_wrap(VALUE arg)
57
+ {
58
+ struct ruby_libvirt_ary_store_arg *e = (struct ruby_libvirt_ary_store_arg *)arg;
59
59
 
60
- return rb_ary_entry(e->arr, e->elem);
61
- }
60
+ rb_ary_store(e->arr, e->index, e->elem);
62
61
 
63
- VALUE rb_ary_new_wrap(VALUE arg) {
64
- return rb_ary_new();
62
+ return Qnil;
65
63
  }
66
64
 
67
- VALUE rb_str_new_wrap(VALUE arg) {
68
- struct rb_str_new_arg *e = (struct rb_str_new_arg *)arg;
65
+ VALUE ruby_libvirt_str_new2_wrap(VALUE arg)
66
+ {
67
+ char **str = (char **)arg;
69
68
 
70
- return rb_str_new(e->val, e->size);
69
+ return rb_str_new2(*str);
71
70
  }
72
71
 
73
- VALUE rb_iv_set_wrap(VALUE arg) {
74
- struct rb_iv_set_arg *e = (struct rb_iv_set_arg *)arg;
72
+ VALUE ruby_libvirt_str_new_wrap(VALUE arg)
73
+ {
74
+ struct ruby_libvirt_str_new_arg *e = (struct ruby_libvirt_str_new_arg *)arg;
75
75
 
76
- return rb_iv_set(e->klass, e->member, e->value);
76
+ return rb_str_new(e->val, e->size);
77
77
  }
78
78
 
79
- VALUE rb_class_new_instance_wrap(VALUE arg) {
80
- struct rb_class_new_instance_arg *e = (struct rb_class_new_instance_arg *)arg;
81
-
82
- return rb_class_new_instance(e->argc, e->argv, e->klass);
83
- }
79
+ VALUE ruby_libvirt_hash_aset_wrap(VALUE arg)
80
+ {
81
+ struct ruby_libvirt_hash_aset_arg *e = (struct ruby_libvirt_hash_aset_arg *)arg;
84
82
 
85
- VALUE rb_string_value_cstr_wrap(VALUE arg) {
86
- return (VALUE)rb_string_value_cstr((VALUE *)arg);
83
+ return rb_hash_aset(e->hash, rb_str_new2(e->name), e->val);
87
84
  }
88
85
 
89
- /* Error handling */
90
- VALUE create_error(VALUE error, const char* method, virConnectPtr conn) {
86
+ void ruby_libvirt_raise_error_if(const int condition, VALUE error,
87
+ const char *method, virConnectPtr conn)
88
+ {
91
89
  VALUE ruby_errinfo;
92
90
  virErrorPtr err;
93
91
  char *msg;
@@ -95,15 +93,23 @@ VALUE create_error(VALUE error, const char* method, virConnectPtr conn) {
95
93
  struct rb_exc_new2_arg arg;
96
94
  int exception = 0;
97
95
 
98
- if (conn == NULL)
96
+ if (!condition) {
97
+ return;
98
+ }
99
+
100
+ if (conn == NULL) {
99
101
  err = virGetLastError();
100
- else
102
+ }
103
+ else {
101
104
  err = virConnGetLastError(conn);
105
+ }
102
106
 
103
- if (err != NULL && err->message != NULL)
107
+ if (err != NULL && err->message != NULL) {
104
108
  rc = asprintf(&msg, "Call to %s failed: %s", method, err->message);
105
- else
109
+ }
110
+ else {
106
111
  rc = asprintf(&msg, "Call to %s failed", method);
112
+ }
107
113
 
108
114
  if (rc < 0) {
109
115
  /* there's not a whole lot we can do here; try to raise an
@@ -113,10 +119,12 @@ VALUE create_error(VALUE error, const char* method, virConnectPtr conn) {
113
119
 
114
120
  arg.error = error;
115
121
  arg.msg = msg;
116
- ruby_errinfo = rb_protect(rb_exc_new2_wrap, (VALUE)&arg, &exception);
122
+ ruby_errinfo = rb_protect(ruby_libvirt_exc_new2_wrap, (VALUE)&arg,
123
+ &exception);
117
124
  free(msg);
118
- if (exception)
125
+ if (exception) {
119
126
  rb_jump_tag(exception);
127
+ }
120
128
 
121
129
  rb_iv_set(ruby_errinfo, "@libvirt_function_name", rb_str_new2(method));
122
130
 
@@ -124,80 +132,347 @@ VALUE create_error(VALUE error, const char* method, virConnectPtr conn) {
124
132
  rb_iv_set(ruby_errinfo, "@libvirt_code", INT2NUM(err->code));
125
133
  rb_iv_set(ruby_errinfo, "@libvirt_component", INT2NUM(err->domain));
126
134
  rb_iv_set(ruby_errinfo, "@libvirt_level", INT2NUM(err->level));
127
- if (err->message != NULL)
135
+ if (err->message != NULL) {
128
136
  rb_iv_set(ruby_errinfo, "@libvirt_message",
129
137
  rb_str_new2(err->message));
138
+ }
130
139
  }
131
140
 
132
- return ruby_errinfo;
141
+ rb_exc_raise(ruby_errinfo);
133
142
  };
134
143
 
135
- char *get_string_or_nil(VALUE arg)
144
+ char *ruby_libvirt_get_cstring_or_null(VALUE arg)
136
145
  {
137
- if (TYPE(arg) == T_NIL)
146
+ if (TYPE(arg) == T_NIL) {
138
147
  return NULL;
139
- else if (TYPE(arg) == T_STRING)
148
+ }
149
+ else if (TYPE(arg) == T_STRING) {
140
150
  return StringValueCStr(arg);
141
- else
142
- rb_raise(rb_eTypeError, "wrong argument type (expected String or nil)"); return NULL;
151
+ }
152
+ else {
153
+ rb_raise(rb_eTypeError, "wrong argument type (expected String or nil)");
154
+ }
155
+
156
+ return NULL;
143
157
  }
144
158
 
145
- VALUE generic_new(VALUE klass, void *ptr, VALUE conn,
146
- RUBY_DATA_FUNC free_func) {
159
+ VALUE ruby_libvirt_new_class(VALUE klass, void *ptr, VALUE conn,
160
+ RUBY_DATA_FUNC free_func)
161
+ {
147
162
  VALUE result;
148
163
  result = Data_Wrap_Struct(klass, NULL, free_func, ptr);
149
164
  rb_iv_set(result, "@connection", conn);
150
165
  return result;
151
166
  }
152
167
 
153
- int is_symbol_or_proc(VALUE handle) {
168
+ int ruby_libvirt_is_symbol_or_proc(VALUE handle)
169
+ {
154
170
  return ((strcmp(rb_obj_classname(handle), "Symbol") == 0) ||
155
171
  (strcmp(rb_obj_classname(handle), "Proc") == 0));
156
172
  }
157
173
 
158
- /* this is an odd function, because it has massive side-effects. The first
159
- * tip that something is weird here should be the triple-starred list.
174
+ /* this is an odd function, because it has massive side-effects.
160
175
  * The intended usage of this function is after a list has been collected
161
176
  * from a libvirt list function, and now we want to make an array out of it.
162
177
  * However, it is possible that the act of creating an array causes an
163
178
  * exception, which would lead to a memory leak of the values we got from
164
179
  * libvirt. Therefore, this function not only wraps all of the relevant
165
- * calls with rb_protect, it also frees every individual entry in list
166
- * along with list itself.
180
+ * calls with rb_protect, it also frees every individual entry in list after
181
+ * it is done with it. Freeing list itself is left to the callers.
167
182
  */
168
- VALUE gen_list(int num, char ***list) {
183
+ VALUE ruby_libvirt_generate_list(int num, char **list)
184
+ {
169
185
  VALUE result;
170
186
  int exception = 0;
171
187
  int i, j;
172
- struct rb_ary_push_arg arg;
188
+ struct ruby_libvirt_ary_store_arg arg;
173
189
 
174
- result = rb_protect(rb_ary_new2_wrap, (VALUE)&num, &exception);
190
+ i = 0;
191
+
192
+ result = rb_protect(ruby_libvirt_ary_new2_wrap, (VALUE)&num, &exception);
175
193
  if (exception) {
176
- for (i = 0; i < num; i++)
177
- free((*list)[i]);
178
- xfree(*list);
179
- rb_jump_tag(exception);
194
+ goto exception;
180
195
  }
181
196
  for (i = 0; i < num; i++) {
182
197
  arg.arr = result;
183
- arg.value = rb_protect(rb_str_new2_wrap, (VALUE)&((*list)[i]),
184
- &exception);
198
+ arg.index = i;
199
+ arg.elem = rb_protect(ruby_libvirt_str_new2_wrap, (VALUE)&(list[i]),
200
+ &exception);
185
201
  if (exception) {
186
- for (j = i; j < num; j++)
187
- xfree((*list)[j]);
188
- xfree(*list);
189
- rb_jump_tag(exception);
202
+ goto exception;
190
203
  }
191
- rb_protect(rb_ary_push_wrap, (VALUE)&arg, &exception);
204
+ rb_protect(ruby_libvirt_ary_store_wrap, (VALUE)&arg, &exception);
192
205
  if (exception) {
193
- for (j = i; j < num; j++)
194
- xfree((*list)[j]);
195
- xfree(*list);
196
- rb_jump_tag(exception);
206
+ goto exception;
197
207
  }
198
- xfree((*list)[i]);
208
+ xfree(list[i]);
199
209
  }
200
- xfree(*list);
201
210
 
202
211
  return result;
212
+
213
+ exception:
214
+ for (j = i; j < num; j++) {
215
+ xfree(list[j]);
216
+ }
217
+ rb_jump_tag(exception);
218
+
219
+ /* not needed, but here to shut the compiler up */
220
+ return Qnil;
221
+ }
222
+
223
+ void ruby_libvirt_typed_params_to_hash(void *voidparams, int i, VALUE hash)
224
+ {
225
+ virTypedParameterPtr params = (virTypedParameterPtr)voidparams;
226
+ VALUE val;
227
+
228
+ switch (params[i].type) {
229
+ case VIR_TYPED_PARAM_INT:
230
+ val = INT2NUM(params[i].value.i);
231
+ break;
232
+ case VIR_TYPED_PARAM_UINT:
233
+ val = UINT2NUM(params[i].value.ui);
234
+ break;
235
+ case VIR_TYPED_PARAM_LLONG:
236
+ val = LL2NUM(params[i].value.l);
237
+ break;
238
+ case VIR_TYPED_PARAM_ULLONG:
239
+ val = ULL2NUM(params[i].value.ul);
240
+ break;
241
+ case VIR_TYPED_PARAM_DOUBLE:
242
+ val = rb_float_new(params[i].value.d);
243
+ break;
244
+ case VIR_TYPED_PARAM_BOOLEAN:
245
+ val = (params[i].value.b == 0) ? Qfalse : Qtrue;
246
+ break;
247
+ case VIR_TYPED_PARAM_STRING:
248
+ val = rb_str_new2(params[i].value.s);
249
+ break;
250
+ default:
251
+ rb_raise(rb_eArgError, "Invalid parameter type");
252
+ }
253
+
254
+ rb_hash_aset(hash, rb_str_new2(params[i].field), val);
255
+ }
256
+
257
+ VALUE ruby_libvirt_get_parameters(VALUE d, unsigned int flags, void *opaque,
258
+ unsigned int typesize,
259
+ char *(*nparams_cb)(VALUE d,
260
+ unsigned int flags,
261
+ void *opaque,
262
+ int *nparams),
263
+ char *(*get_cb)(VALUE d, unsigned int flags,
264
+ void *voidparams,
265
+ int *nparams, void *opaque),
266
+ void (*hash_set)(void *voidparams, int i,
267
+ VALUE result))
268
+ {
269
+ int nparams = 0;
270
+ void *params;
271
+ VALUE result;
272
+ char *errname;
273
+ int i;
274
+
275
+ errname = nparams_cb(d, flags, opaque, &nparams);
276
+ ruby_libvirt_raise_error_if(errname != NULL, e_RetrieveError, errname,
277
+ ruby_libvirt_connect_get(d));
278
+
279
+ result = rb_hash_new();
280
+
281
+ if (nparams == 0) {
282
+ return result;
283
+ }
284
+
285
+ params = alloca(typesize * nparams);
286
+
287
+ errname = get_cb(d, flags, params, &nparams, opaque);
288
+ ruby_libvirt_raise_error_if(errname != NULL, e_RetrieveError, errname,
289
+ ruby_libvirt_connect_get(d));
290
+
291
+ for (i = 0; i < nparams; i++) {
292
+ hash_set(params, i, result);
293
+ }
294
+
295
+ return result;
296
+ }
297
+
298
+ VALUE ruby_libvirt_get_typed_parameters(VALUE d, unsigned int flags,
299
+ void *opaque,
300
+ char *(*nparams_cb)(VALUE d,
301
+ unsigned int flags,
302
+ void *opaque,
303
+ int *nparams),
304
+ char *(*get_cb)(VALUE d,
305
+ unsigned int flags,
306
+ void *params,
307
+ int *nparams,
308
+ void *opaque))
309
+ {
310
+ return ruby_libvirt_get_parameters(d, flags, opaque,
311
+ sizeof(virTypedParameter), nparams_cb,
312
+ get_cb,
313
+ ruby_libvirt_typed_params_to_hash);
314
+ }
315
+
316
+ void ruby_libvirt_assign_hash_and_flags(VALUE in, VALUE *hash, VALUE *flags)
317
+ {
318
+ if (TYPE(in) == T_HASH) {
319
+ *hash = in;
320
+ *flags = INT2NUM(0);
321
+ }
322
+ else if (TYPE(in) == T_ARRAY) {
323
+ if (RARRAY_LEN(in) != 2) {
324
+ rb_raise(rb_eArgError, "wrong number of arguments (%ld for 1 or 2)",
325
+ RARRAY_LEN(in));
326
+ }
327
+ *hash = rb_ary_entry(in, 0);
328
+ *flags = rb_ary_entry(in, 1);
329
+ }
330
+ else {
331
+ rb_raise(rb_eTypeError, "wrong argument type (expected Hash or Array)");
332
+ }
333
+ }
334
+
335
+ int ruby_libvirt_typed_parameter_assign(VALUE key, VALUE val, VALUE in)
336
+ {
337
+ struct ruby_libvirt_parameter_assign_args *args = (struct ruby_libvirt_parameter_assign_args *)in;
338
+ char *keyname;
339
+ unsigned int i;
340
+ int found;
341
+
342
+ keyname = StringValueCStr(key);
343
+
344
+ found = 0;
345
+ for (i = 0; i < args->num_allowed; i++) {
346
+ if (strcmp(args->allowed[i].name, keyname) == 0) {
347
+ args->params[args->i].type = args->allowed[i].type;
348
+ switch (args->params[args->i].type) {
349
+ case VIR_TYPED_PARAM_INT:
350
+ args->params[i].value.i = NUM2INT(val);
351
+ break;
352
+ case VIR_TYPED_PARAM_UINT:
353
+ args->params[i].value.ui = NUM2UINT(val);
354
+ break;
355
+ case VIR_TYPED_PARAM_LLONG:
356
+ args->params[i].value.l = NUM2LL(val);
357
+ break;
358
+ case VIR_TYPED_PARAM_ULLONG:
359
+ args->params[args->i].value.ul = NUM2ULL(val);
360
+ break;
361
+ case VIR_TYPED_PARAM_DOUBLE:
362
+ args->params[i].value.d = NUM2DBL(val);
363
+ break;
364
+ case VIR_TYPED_PARAM_BOOLEAN:
365
+ args->params[i].value.b = (val == Qtrue) ? 1 : 0;
366
+ break;
367
+ case VIR_TYPED_PARAM_STRING:
368
+ args->params[args->i].value.s = StringValueCStr(val);
369
+ break;
370
+ default:
371
+ rb_raise(rb_eArgError, "Invalid parameter type");
372
+ }
373
+ strncpy(args->params[args->i].field, keyname,
374
+ VIR_TYPED_PARAM_FIELD_LENGTH);
375
+ (args->i)++;
376
+ found = 1;
377
+ break;
378
+ }
379
+ }
380
+
381
+ if (!found) {
382
+ rb_raise(rb_eArgError, "Unknown key %s", keyname);
383
+ }
384
+
385
+ return ST_CONTINUE;
386
+ }
387
+
388
+ VALUE ruby_libvirt_set_typed_parameters(VALUE d, VALUE input,
389
+ unsigned int flags, void *opaque,
390
+ struct ruby_libvirt_typed_param *allowed,
391
+ unsigned int num_allowed,
392
+ char *(*set_cb)(VALUE d,
393
+ unsigned int flags,
394
+ virTypedParameterPtr params,
395
+ int nparams,
396
+ void *opaque))
397
+ {
398
+ char *errname;
399
+ struct ruby_libvirt_parameter_assign_args args;
400
+ unsigned long hashsize;
401
+
402
+ /* make sure input is a hash */
403
+ Check_Type(input, T_HASH);
404
+
405
+ hashsize = RHASH_SIZE(input);
406
+
407
+ if (hashsize == 0) {
408
+ return Qnil;
409
+ }
410
+
411
+ args.allowed = allowed;
412
+ args.num_allowed = num_allowed;
413
+ args.params = alloca(sizeof(virTypedParameter) * hashsize);
414
+ args.i = 0;
415
+
416
+ rb_hash_foreach(input, ruby_libvirt_typed_parameter_assign, (VALUE)&args);
417
+
418
+ errname = set_cb(d, flags, args.params, args.i, opaque);
419
+ ruby_libvirt_raise_error_if(errname != NULL, e_RetrieveError, errname,
420
+ ruby_libvirt_connect_get(d));
421
+
422
+ return Qnil;
423
+ }
424
+
425
+ unsigned int ruby_libvirt_value_to_uint(VALUE in)
426
+ {
427
+ if (NIL_P(in)) {
428
+ return 0;
429
+ }
430
+
431
+ return NUM2UINT(in);
432
+ }
433
+
434
+ int ruby_libvirt_value_to_int(VALUE in)
435
+ {
436
+ if (NIL_P(in)) {
437
+ return 0;
438
+ }
439
+
440
+ return NUM2INT(in);
441
+ }
442
+
443
+ unsigned long ruby_libvirt_value_to_ulong(VALUE in)
444
+ {
445
+ if (NIL_P(in)) {
446
+ return 0;
447
+ }
448
+
449
+ return NUM2ULONG(in);
450
+ }
451
+
452
+ unsigned long long ruby_libvirt_value_to_ulonglong(VALUE in)
453
+ {
454
+ if (NIL_P(in)) {
455
+ return 0;
456
+ }
457
+
458
+ return NUM2ULL(in);
459
+ }
460
+
461
+ int ruby_libvirt_get_maxcpus(virConnectPtr conn)
462
+ {
463
+ int maxcpu = -1;
464
+ virNodeInfo nodeinfo;
465
+
466
+ #if HAVE_VIRNODEGETCPUMAP
467
+ maxcpu = virNodeGetCPUMap(conn, NULL, NULL, 0);
468
+ #endif
469
+ if (maxcpu < 0) {
470
+ /* fall back to nodeinfo */
471
+ ruby_libvirt_raise_error_if(virNodeGetInfo(conn, &nodeinfo) < 0,
472
+ e_RetrieveError, "virNodeGetInfo", conn);
473
+
474
+ maxcpu = VIR_NODEINFO_MAXCPUS(nodeinfo);
475
+ }
476
+
477
+ return maxcpu;
203
478
  }