cmpi-bindings 0.5.2 → 0.9.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.
@@ -46,10 +46,12 @@
46
46
  /* Needed for kill() */
47
47
  #include <signal.h>
48
48
 
49
+ static int cmpi_bindings_trace_level = 0; /* increase by setenv CMPI_BINDINGS_TRACE_LEVEL */
50
+
49
51
  /* A simple stderr logging/tracing facility. */
50
52
  #ifndef _SBLIM_TRACE
51
- #define _SBLIM_TRACE(tracelevel,args) _logstderr args
52
- void _logstderr(char *fmt,...)
53
+ #define _SBLIM_TRACE(tracelevel,args) if (tracelevel <= cmpi_bindings_trace_level) { _logstderr args; }
54
+ static void _logstderr(char *fmt,...)
53
55
  {
54
56
  va_list ap;
55
57
  va_start(ap,fmt);
@@ -142,20 +144,23 @@ proplist2target(const char** cplist)
142
144
  static char *
143
145
  fmtstr(const char* fmt, ...)
144
146
  {
147
+ static char buf[1];
145
148
  va_list ap;
146
149
  int len;
147
150
  char* str;
148
151
 
149
152
  va_start(ap, fmt);
150
- len = vsnprintf(NULL, 0, fmt, ap);
153
+ len = vsnprintf(buf, 1, fmt, ap); /* vsnprintf(NULL, 0, ...) should work. bnc#762684 */
151
154
  va_end(ap);
152
155
  if (len <= 0)
153
156
  {
157
+ fprintf(stderr, "*Err: vsnprintf(%s) = %d\n", fmt, len);
154
158
  return NULL;
155
159
  }
156
160
  str = (char*)malloc(len+1);
157
161
  if (str == NULL)
158
162
  {
163
+ fprintf(stderr, "*Err: malloc(%d) failed\n", len+1);
159
164
  return NULL;
160
165
  }
161
166
  va_start(ap, fmt);
@@ -868,6 +873,28 @@ references(
868
873
  return status;
869
874
  }
870
875
 
876
+
877
+ #if defined(SWIGRUBY)
878
+ /*
879
+ * Check type of VALUE
880
+ *
881
+ * return 0 if ok
882
+ * return -1 if bad type, set status accordingly
883
+ *
884
+ */
885
+
886
+ static int
887
+ check_ruby_type( VALUE value, int type, const char *message, CMPIStatus *status, ProviderMIHandle* hdl )
888
+ {
889
+ if (TYPE(value) != type) {
890
+ status->rc = CMPI_RC_ERR_TYPE_MISMATCH;
891
+ status->msg = CMNewString(hdl->broker, message, NULL);
892
+ return -1;
893
+ }
894
+ return 0;
895
+ }
896
+ #endif
897
+
871
898
  /*
872
899
  * invokeMethod
873
900
  */
@@ -891,55 +918,72 @@ invokeMethod(
891
918
  TARGET_THREAD_BEGIN_BLOCK;
892
919
  _ctx = SWIG_NewPointerObj((void*) ctx, SWIGTYPE_p__CMPIContext, 0);
893
920
  _objName = SWIG_NewPointerObj((void*) objName, SWIGTYPE_p__CMPIObjectPath, 0);
921
+
922
+ /* Ruby style method invocation */
894
923
  #if defined(SWIGRUBY)
924
+
925
+ /* de-camelize method name, might need 2time length */
895
926
  char *methodname = alloca(strlen(method) * 2 + 1);
896
927
  decamelize(method, methodname);
928
+
929
+ /* access method arguments information via <decamelized>_args */
897
930
  int argsnamesize = strlen(methodname) + 5 + 1;
898
931
  char *argsname = alloca(argsnamesize); /* "<name>_args" */
899
932
  snprintf(argsname, argsnamesize, "%s_args", methodname);
933
+
900
934
  /* get the args array, gives names of input and output arguments */
901
935
  VALUE args = rb_funcall(((ProviderMIHandle*)self->hdl)->implementation, rb_intern(argsname), 0);
902
- Check_Type(args, T_ARRAY);
936
+ if (check_ruby_type(args, T_ARRAY, "invoke: <method>_args must be Array", &status, (ProviderMIHandle*)self->hdl ) < 0)
937
+ return status;
938
+
903
939
  VALUE argsin = rb_ary_entry(args, 0); /* array of input arg names */
904
- Check_Type(argsin, T_ARRAY);
940
+ if (check_ruby_type(argsin, T_ARRAY, "invoke: Input arguments must be Array", &status, (ProviderMIHandle*)self->hdl ) < 0)
941
+ return status;
942
+
905
943
  int number_of_arguments = RARRAY_LEN(argsin) / 2;
944
+ _SBLIM_TRACE(1,("%s -> %d input args", argsname, number_of_arguments));
906
945
  /* 3 args will be added by TargetCall, 2 args are added here, others are input args to function */
907
946
  VALUE *input = alloca((3 + 2 + number_of_arguments) * sizeof(VALUE));
908
947
  input[3] = _ctx;
909
948
  input[4] = _objName;
910
949
  /* loop over input arg names and types and get CMPIData via CMGetArg() */
911
950
  int i;
912
- for (i = 0; i < number_of_arguments; i += 2) {
951
+ for (i = 0; i < number_of_arguments; ++i) {
913
952
  const char *argname;
914
953
  CMPIData data;
915
- argname = target_charptr(rb_ary_entry(argsin, i));
954
+ argname = target_charptr(rb_ary_entry(argsin, i*2));
916
955
  data = CMGetArg(in, argname, &status);
917
956
  if (status.rc != CMPI_RC_OK) {
918
957
  if ((data.state & CMPI_nullValue)
919
958
  ||(data.state & CMPI_notFound)) {
920
- input[5+(i>>1)] = Target_Null;
959
+ input[5+i] = Target_Null;
921
960
  continue;
922
961
  }
923
962
  _SBLIM_TRACE(1,("Failed (rc %d) to get input arg %d:%s for %s", status.rc, i>>1, argname, method));
924
963
  return status;
925
964
  }
926
- input[5+(i>>1)] = data_value(&data);
965
+ input[5+i] = data_value(&data);
927
966
  }
967
+
968
+ /* actual provider call, passes output args and return value via 'result' */
928
969
  VALUE result = TargetCall((ProviderMIHandle*)self->hdl, &status, methodname, -(2+number_of_arguments), input);
970
+
929
971
  /* argsout is array of [<return_type>, <output_arg_name>, <output_arg_type>, ... */
930
972
  VALUE argsout = rb_ary_entry(args, 1);
931
973
  CMPIValue value;
932
974
  CMPIType expected_type;
933
975
  CMPIType actual_type;
934
- Check_Type(argsout, T_ARRAY);
935
- number_of_arguments = (RARRAY_LEN(argsout) - 1) / 2;
976
+ if (check_ruby_type(argsout, T_ARRAY, "invoke: Output arguments must be Array", &status, (ProviderMIHandle*)self->hdl) < 0)
977
+ return status;
978
+ number_of_arguments = (RARRAY_LEN(argsout) - 1);
936
979
 
937
980
  if (number_of_arguments > 0) {
938
981
  /* if output args are defined, result must be an array
939
982
  * result[0] is the return value
940
983
  * result[1..n] are the output args in argsout order
941
984
  */
942
- Check_Type(result, T_ARRAY);
985
+ if (check_ruby_type(result, T_ARRAY, "invoke: function with output arguments must return Array", &status, (ProviderMIHandle*)self->hdl) < 0)
986
+ return status;
943
987
 
944
988
  /* loop over output arg names and types and set CMPIData via CMSetArg() */
945
989
  for (i = 0; i < number_of_arguments; i += 2) {
@@ -1260,7 +1304,13 @@ static CMPIInstanceMIFT InstanceMIFT__={
1260
1304
  static int
1261
1305
  createInit(ProviderMIHandle* miHdl, CMPIStatus* st)
1262
1306
  {
1263
- _SBLIM_TRACE(1,("\n>>>>> createInit() called, broker %p, miname= %s (ctx=%p), status %p\n", miHdl->broker, miHdl->miName, miHdl->context, st));
1307
+ const char *trace_level = getenv("CMPI_BINDINGS_TRACE_LEVEL");
1308
+ _SBLIM_TRACE(0,("\n>>>>> createInit() called, broker %p, miname= %s (ctx=%p), status %p, trace_level %s\n", miHdl->broker, miHdl->miName, miHdl->context, st, trace_level?trace_level:"(null)"));
1309
+
1310
+ if (trace_level) {
1311
+ cmpi_bindings_trace_level = *trace_level - '0';
1312
+ _SBLIM_TRACE(0,("tracing at level %d\n", cmpi_bindings_trace_level));
1313
+ }
1264
1314
  return TargetInitialize(miHdl, st);
1265
1315
  }
1266
1316
 
@@ -117,7 +117,7 @@ load_provider(VALUE arg)
117
117
  char *filename = alloca(strlen(classname) * 2 + 1);
118
118
  decamelize(classname, filename);
119
119
  ruby_script(filename);
120
- _SBLIM_TRACE(1,("Ruby: loading (%s)", filename));
120
+ _SBLIM_TRACE(1,("<%d> Ruby: loading (%s)", getpid(), filename));
121
121
  req = rb_require(filename);
122
122
  /* Qtrue == just loaded, Qfalse = already loaded, else: fail */
123
123
  if ((req != Qtrue) && (req != Qfalse)) {
@@ -126,12 +126,12 @@ load_provider(VALUE arg)
126
126
  }
127
127
  /* Get Cmpi::Provider */
128
128
  VALUE val = rb_const_get(rb_cObject, rb_intern(RB_MODULE_NAME));
129
- if (val == Qnil) {
129
+ if (NIL_P(val)) {
130
130
  _SBLIM_TRACE(1,("<%d> No such module '%s'", getpid(), RB_MODULE_NAME));
131
131
  return val;
132
132
  }
133
133
  val = rb_const_get(val, rb_intern(classname));
134
- if (val == Qnil) {
134
+ if (NIL_P(val)) {
135
135
  _SBLIM_TRACE(1,("<%d> No such class '%s::%s'", getpid(), RB_MODULE_NAME, classname));
136
136
  }
137
137
  return val;
@@ -161,19 +161,28 @@ call_mi(VALUE args)
161
161
  /*
162
162
  * get Ruby exception trace -> CMPIString
163
163
  *
164
+ * returns NULL if called without exception
164
165
  */
165
166
 
166
167
  #define TB_ERROR(str) {tbstr = str; goto cleanup;}
167
168
  static CMPIString *
168
169
  get_exc_trace(const CMPIBroker* broker)
169
170
  {
170
- VALUE exception = rb_gv_get("$!"); /* get last exception */
171
- VALUE reason = rb_funcall(exception, rb_intern("to_s"), 0 );
172
- VALUE trace = rb_gv_get("$@"); /* get last exception trace */
173
- VALUE backtrace = rb_funcall(trace, rb_intern("join"), 1, rb_str_new("\n\t", 2));
174
-
175
- char* tmp = fmtstr("%s\n\t%s", StringValuePtr(reason), StringValuePtr(backtrace));
176
- return broker->eft->newString(broker, tmp, NULL);
171
+ VALUE exception = rb_gv_get("$!"); /* get last exception */
172
+ VALUE reason = rb_funcall(exception, rb_intern("to_s"), 0 );
173
+ VALUE trace = rb_gv_get("$@"); /* get last exception trace */
174
+ VALUE backtrace;
175
+ char* tmp;
176
+ CMPIString *result;
177
+
178
+ if (NIL_P(exception)) {
179
+ return NULL;
180
+ }
181
+ backtrace = rb_funcall(trace, rb_intern("join"), 1, rb_str_new("\n\t", 2));
182
+ tmp = fmtstr("%s\n\t%s", StringValuePtr(reason), StringValuePtr(backtrace));
183
+ result = broker->eft->newString(broker, tmp, NULL);
184
+ free(tmp);
185
+ return result;
177
186
  }
178
187
 
179
188
 
@@ -189,19 +198,13 @@ get_exc_trace(const CMPIBroker* broker)
189
198
  static int
190
199
  RbGlobalInitialize(const CMPIBroker* broker, CMPIStatus* st)
191
200
  {
192
- int error = 0;
193
201
  char *loadpath;
194
202
  VALUE searchpath;
195
203
 
196
- if (_TARGET_INIT) {
197
- return error;
198
- }
199
- _TARGET_INIT=1; /* safe, since mutex is locked */
200
-
201
- _SBLIM_TRACE(1,("<%d> Ruby: Loading", getpid()));
202
-
204
+ _SBLIM_TRACE(1,("<%d> Ruby: RbGlobalInitialize, stack @ %p", getpid(), &searchpath));
203
205
  ruby_init();
204
206
  ruby_init_loadpath();
207
+
205
208
  extern void SWIG_init();
206
209
  SWIG_init();
207
210
 
@@ -214,16 +217,20 @@ RbGlobalInitialize(const CMPIBroker* broker, CMPIStatus* st)
214
217
  if (loadpath) {
215
218
  struct stat buf;
216
219
  if (stat(loadpath, &buf)) {
217
- _SBLIM_TRACE(1,("<%d> Can't stat $RUBY_PROVIDERS_DIR '%s'", getpid(), loadpath));
220
+ _SBLIM_TRACE(1,("<%d> Can't stat $%s '%s'", getpid(), RUBY_PROVIDERS_DIR_ENV, loadpath));
218
221
  return -1;
219
222
  }
220
223
  if ((buf.st_mode & S_IFDIR) == 0) {
221
- _SBLIM_TRACE(1,("<%d> Not a directory: $RUBY_PROVIDERS_DIR '%s'", getpid(), loadpath));
224
+ _SBLIM_TRACE(1,("<%d> Not a directory: $%s '%s'", getpid(), RUBY_PROVIDERS_DIR_ENV, loadpath));
222
225
  return -1;
223
226
  }
227
+ _SBLIM_TRACE(1,("<%d> Loading providers from: $%s '%s'", getpid(), RUBY_PROVIDERS_DIR_ENV, loadpath));
224
228
  rb_ary_push(searchpath, rb_str_new2(loadpath));
225
229
  }
226
- return error;
230
+ else {
231
+ _SBLIM_TRACE(0, ("<%d> Hmm, %s not set ?!", getpid(), RUBY_PROVIDERS_DIR_ENV));
232
+ }
233
+ return 0;
227
234
  }
228
235
 
229
236
 
@@ -238,8 +245,9 @@ RbGlobalInitialize(const CMPIBroker* broker, CMPIStatus* st)
238
245
  static int
239
246
  TargetInitialize(ProviderMIHandle* hdl, CMPIStatus* st)
240
247
  {
241
- VALUE args[6];
242
- int error;
248
+ VALUE args[6] = { Qnil };
249
+ VALUE gc = Qnil;
250
+ int error = 0;
243
251
  int have_lock = 0;
244
252
 
245
253
  /* Set _CMPI_INIT, protected by _CMPI_INIT_MUTEX
@@ -249,7 +257,22 @@ TargetInitialize(ProviderMIHandle* hdl, CMPIStatus* st)
249
257
  perror("Can't lock _CMPI_INIT_MUTEX");
250
258
  abort();
251
259
  }
252
- error = RbGlobalInitialize(hdl->broker, st);
260
+ if (_TARGET_INIT == 0) {
261
+ _TARGET_INIT = 1; /* safe, since mutex is locked */
262
+ error = RbGlobalInitialize(hdl->broker, st);
263
+ }
264
+ #if 0
265
+ else {
266
+ /* Enforce GC.disable in provider upcalls; Ruby 1.9 crashes without */
267
+ gc = rb_const_get(rb_cObject, rb_intern("GC"));
268
+ if (NIL_P(gc)) {
269
+ _SBLIM_TRACE(0,("<%d> No such module 'GC'", getpid()));
270
+ }
271
+ else {
272
+ rb_funcall(gc, rb_intern("disable"), 0 );
273
+ }
274
+ }
275
+ #endif
253
276
  pthread_mutex_unlock(&_CMPI_INIT_MUTEX);
254
277
  if (error != 0) {
255
278
  if (st != NULL) {
@@ -259,10 +282,11 @@ TargetInitialize(ProviderMIHandle* hdl, CMPIStatus* st)
259
282
  goto fail;
260
283
  }
261
284
 
262
- _SBLIM_TRACE(1,("<%d> TargetInitialize(Ruby) called, miName '%s'", getpid(), hdl->miName));
285
+ _SBLIM_TRACE(1,("<%d> TargetInitialize(Ruby) called, miName '%s', stack @ %p, pthread %p", getpid(), hdl->miName, &have_lock, pthread_self()));
263
286
 
264
287
  if (pthread_mutex_trylock(&_stack_init_mutex) == 0) {
265
288
  have_lock = 1;
289
+ _SBLIM_TRACE(1,("<%d> RUBY_INIT_STACK for pthread %p", getpid(), pthread_self()));
266
290
  RUBY_INIT_STACK
267
291
  }
268
292
 
@@ -271,6 +295,7 @@ TargetInitialize(ProviderMIHandle* hdl, CMPIStatus* st)
271
295
  */
272
296
  args[0] = rb_protect(load_provider, (VALUE)hdl->miName, &error);
273
297
  if (error) {
298
+ _SBLIM_TRACE(1,("Ruby: load_provider(%s) failed !", hdl->miName));
274
299
  if (st != NULL) {
275
300
  st->rc = CMPI_RC_ERR_INVALID_CLASS;
276
301
  st->msg = CMNewString(hdl->broker, "Failed to load provider", NULL);
@@ -284,11 +309,13 @@ TargetInitialize(ProviderMIHandle* hdl, CMPIStatus* st)
284
309
  args[4] = SWIG_NewPointerObj((void*) hdl->broker, SWIGTYPE_p__CMPIBroker, 0);
285
310
  args[5] = SWIG_NewPointerObj((void*) hdl->context, SWIGTYPE_p__CMPIContext, 0);
286
311
  hdl->implementation = rb_protect(call_mi, (VALUE)args, &error);
312
+ if (error) {
313
+ _SBLIM_TRACE(1,("Ruby: %s.new() failed !", hdl->miName));
314
+ }
287
315
 
288
316
  fail:
289
317
  if (error) {
290
318
  CMPIString *trace = get_exc_trace(hdl->broker);
291
- _SBLIM_TRACE(1,("Ruby: FAILED creating %s: %s", hdl->miName, CMGetCharPtr(trace)));
292
319
  if (st != NULL) {
293
320
  st->rc = CMPI_RC_ERR_INVALID_CLASS;
294
321
  st->msg = trace;
@@ -302,7 +329,10 @@ fail:
302
329
  }
303
330
  if (have_lock)
304
331
  pthread_mutex_unlock(&_stack_init_mutex);
305
- _SBLIM_TRACE(1,("Initialize() %s", (error == 0)?"succeeded":"failed"));
332
+ if (!NIL_P(gc)) {
333
+ rb_funcall(gc, rb_intern("enable"), 0 );
334
+ }
335
+ _SBLIM_TRACE(1,("TargetInitialize() %s", (error == 0)?"succeeded":"failed"));
306
336
  return error;
307
337
  }
308
338
 
@@ -311,6 +341,15 @@ fail:
311
341
  * TargetCall
312
342
  *
313
343
  * Call function 'opname' with nargs arguments within managed interface hdl->implementation
344
+ *
345
+ * If nargs < 0: 'invoke method' call to provider
346
+ * nargs is followed by a VALUE* array of -nargs+3 elements
347
+ * [0] = undef
348
+ * [1] = undef
349
+ * [2] = undef
350
+ * [3] = _ctx;
351
+ * [4] = _objName;
352
+ * [5...] = function arguments
314
353
  */
315
354
 
316
355
  static Target_Type
@@ -322,12 +361,17 @@ TargetCall(ProviderMIHandle* hdl, CMPIStatus* st,
322
361
  int i;
323
362
  VALUE *args, result, op = rb_intern(opname);
324
363
  va_list vargs;
364
+ _SBLIM_TRACE(5,("TargetCall([hdl %p]%s:%d args, pthread %p)", hdl, opname, nargs, pthread_self()));
325
365
 
326
366
  if (pthread_mutex_trylock(&_stack_init_mutex) == 0) {
327
367
  have_lock = 1;
368
+ #if (RUBY_API_VERSION_MAJOR > 1) || (RUBY_API_VERSION_MAJOR == 1 && RUBY_API_VERSION_MINOR < 9)
369
+ _SBLIM_TRACE(1,("<%d> RUBY_INIT_STACK", getpid()));
328
370
  RUBY_INIT_STACK
371
+ #endif
329
372
  }
330
373
  if (invoke) {
374
+ /* invoke style: get pre-allocated array of arguments */
331
375
  va_start(vargs, nargs);
332
376
  args = va_arg(vargs, VALUE *);
333
377
  va_end(vargs);
@@ -345,17 +389,15 @@ TargetCall(ProviderMIHandle* hdl, CMPIStatus* st,
345
389
  args[0] = (VALUE)(hdl->implementation);
346
390
  args[1] = op;
347
391
  args[2] = (VALUE)(nargs-3);
348
- if (!invoke && (nargs > 3))
349
- {
350
- va_start(vargs, nargs);
351
- for (i = 3; i < nargs; ++i)
352
- {
353
- VALUE value;
354
- value = va_arg(vargs, VALUE);
355
- args[i] = (value == (VALUE)NULL) ? Qnil : value;
356
- }
357
- va_end(vargs);
392
+ if (!invoke && (nargs > 3)) {
393
+ va_start(vargs, nargs);
394
+ for (i = 3; i < nargs; ++i) {
395
+ VALUE value;
396
+ value = va_arg(vargs, VALUE);
397
+ args[i] = (value == (VALUE)NULL) ? Qnil : value;
358
398
  }
399
+ va_end(vargs);
400
+ }
359
401
 
360
402
  /* call the Ruby function
361
403
  * possible results:
@@ -366,51 +408,59 @@ TargetCall(ProviderMIHandle* hdl, CMPIStatus* st,
366
408
  */
367
409
  result = rb_protect(call_mi, (VALUE)args, &i);
368
410
 
369
- if (i) /* exception ? */
370
- {
371
- CMPIString *trace = get_exc_trace(hdl->broker);
372
- char* str = fmtstr("Ruby: calling '%s' failed: %s", opname, CMGetCharPtr(trace));
373
- _SBLIM_TRACE(1,("%s", str));
374
- st->rc = CMPI_RC_ERR_FAILED;
375
- st->msg = hdl->broker->eft->newString(hdl->broker, str, NULL);
376
- goto done;
411
+ if (i) { /* exception ? */
412
+ CMPIString *trace = get_exc_trace(hdl->broker);
413
+ char *trace_s;
414
+ char* str;
415
+ if (trace) {
416
+ trace_s = CMGetCharPtr(trace);
377
417
  }
378
- if (NIL_P(result)) /* not or wrongly implemented */
379
- {
380
- st->rc = CMPI_RC_ERR_NOT_SUPPORTED;
381
- goto done;
418
+ else {
419
+ trace_s = "Unknown reason";
382
420
  }
421
+ str = fmtstr("Ruby: calling '%s' failed: %s", opname, trace_s);
422
+ if (trace)
423
+ trace->ft->release(trace);
424
+ _SBLIM_TRACE(1,("%s", str));
425
+ st->rc = CMPI_RC_ERR_FAILED;
426
+ st->msg = hdl->broker->eft->newString(hdl->broker, str, NULL);
427
+ free(str);
428
+ goto done;
429
+ }
430
+ if (NIL_P(result)) { /* not or wrongly implemented */
431
+ st->rc = CMPI_RC_ERR_NOT_SUPPORTED;
432
+ goto done;
433
+ }
383
434
 
384
435
  if (invoke) {
385
436
  st->rc = CMPI_RC_OK;
386
437
  goto done;
387
438
  }
388
439
 
389
- if (result != Qtrue)
390
- {
391
- VALUE resulta = rb_check_array_type(result);
392
- VALUE rc, msg;
393
- if (NIL_P(resulta))
394
- {
395
- char* str = fmtstr("Ruby: calling '%s' returned unknown result", opname);
396
- st->rc = CMPI_RC_ERR_FAILED;
397
- st->msg = hdl->broker->eft->newString(hdl->broker, str, NULL);
398
- goto done;
399
- }
400
-
401
- rc = rb_ary_entry(resulta, 0);
402
- msg = rb_ary_entry(resulta, 1);
403
- if (!FIXNUM_P(rc))
404
- {
405
- char* str = fmtstr("Ruby: calling '%s' returned non-numeric rc code", opname);
406
- st->rc = CMPI_RC_ERR_FAILED;
407
- st->msg = hdl->broker->eft->newString(hdl->broker, str, NULL);
408
- goto done;
409
- }
410
- st->rc = FIX2LONG(rc);
411
- st->msg = hdl->broker->eft->newString(hdl->broker, StringValuePtr(msg), NULL);
440
+ if (result != Qtrue) {
441
+ VALUE resulta = rb_check_array_type(result);
442
+ VALUE rc, msg;
443
+ if (NIL_P(resulta)) {
444
+ char* str = fmtstr("Ruby: calling '%s' returned unknown result", opname);
445
+ st->rc = CMPI_RC_ERR_FAILED;
446
+ st->msg = hdl->broker->eft->newString(hdl->broker, str, NULL);
447
+ free(str);
448
+ goto done;
449
+ }
450
+
451
+ rc = rb_ary_entry(resulta, 0);
452
+ msg = rb_ary_entry(resulta, 1);
453
+ if (!FIXNUM_P(rc)){
454
+ char* str = fmtstr("Ruby: calling '%s' returned non-numeric rc code", opname);
455
+ st->rc = CMPI_RC_ERR_FAILED;
456
+ st->msg = hdl->broker->eft->newString(hdl->broker, str, NULL);
457
+ free(str);
412
458
  goto done;
413
459
  }
460
+ st->rc = FIX2LONG(rc);
461
+ st->msg = hdl->broker->eft->newString(hdl->broker, StringValuePtr(msg), NULL);
462
+ goto done;
463
+ }
414
464
 
415
465
  /* all is fine */
416
466
  st->rc = CMPI_RC_OK;
@@ -428,7 +478,7 @@ done:
428
478
  static void
429
479
  TargetCleanup(ProviderMIHandle * hdl)
430
480
  {
431
- _SBLIM_TRACE(1,("TargetCleanup(hdl %p)", hdl));
481
+ _SBLIM_TRACE(1,("Ruby: TargetCleanup(hdl %p)", hdl));
432
482
  /* free() provider instance */
433
483
  if (hdl && hdl->implementation) {
434
484
  _SBLIM_TRACE(1,("unregister(%p)", hdl->implementation));
@@ -454,7 +504,7 @@ TargetCleanup(ProviderMIHandle * hdl)
454
504
  {
455
505
  _SBLIM_TRACE(1,("Calling ruby_finalize()"));
456
506
  ruby_finalize();
457
- _TARGET_INIT=0; // false
507
+ _TARGET_INIT = 0; // false
458
508
  }
459
509
  pthread_mutex_unlock(&_CMPI_INIT_MUTEX);
460
510
  return;
data/lib/cmpi/provider.rb CHANGED
@@ -50,6 +50,9 @@ public
50
50
  # call-seq:
51
51
  # ProviderIF.new broker
52
52
  #
53
+ # Attn: This is different from the derived provider
54
+ # which gets name, broker, context passed to initialize
55
+ #
53
56
  def initialize broker
54
57
  Cmpi::broker = broker
55
58
  end
data/lib/cmpi.rb CHANGED
@@ -179,6 +179,83 @@ module Cmpi
179
179
  CMPI_ARRAY | self.charsptrA
180
180
  end
181
181
 
182
+ #
183
+ # Convert CIM DateTime string representation (see DSP0004, 2.2.1)
184
+ # to Ruby Time (timestamp) or Float (interval, as seconds with fraction)
185
+ # 00000000001111111111222222
186
+ # 01234567890123456789012345
187
+ # East: yyyymmddhhmmss.mmmmmm+utc -> Time (utc = offset in minutes)
188
+ # West: yyyymmddhhmmss.mmmmmm-utc -> Time
189
+ # Interval: ddddddddhhmmss.mmmmmm:000 -> Float (interval in seconds, with fraction)
190
+ #
191
+ def self.cimdatetime_to_ruby str
192
+ # puts "Cmpi.cimdatetime_to_ruby(#{str})"
193
+ case str[21,1]
194
+ when '+', '-'
195
+ # create Time from yyyymmddhhmmss and utc
196
+ t = Time.new(str[0,4].to_i, str[4,2].to_i, str[6,2].to_i, str[8,2].to_i, str[10,2].to_i, str[12,2].to_i, str[22,3].to_i * ((str[21,1]=='+')?60:-60))
197
+ off = str[15,6].to_i / 1000
198
+ # Add fractional part
199
+ return t + off
200
+ when ':'
201
+ # time offset
202
+ off = str[0,8].to_i * 24 * 60 * 60
203
+ off += str[8,2].to_i * 60 * 60 + str[10,2].to_i * 60 + str[12,2].to_i
204
+ off += str[15,6].to_i / 1000
205
+ return off
206
+ else
207
+ raise "Invalid CIM DateTime '#{str}'"
208
+ end
209
+ end
210
+
211
+ #
212
+ # Convert Ruby value to CIM DateTime string representation (see DSP0004, 2.2.1)
213
+ # 00000000001111111111222222
214
+ # 01234567890123456789012345
215
+ # East: yyyymmddhhmmss.mmmmmm+utc -> Time (utc = offset in minutes, mmmmmm is the microsecond within the second
216
+ # West: yyyymmddhhmmss.mmmmmm-utc -> Time
217
+ # Interval: ddddddddhhmmss.mmmmmm:000 -> Float (interval in seconds, with fraction)
218
+ #
219
+ def self.ruby_to_cimdatetime val
220
+ require 'date'
221
+ # puts "Cmpi.ruby_to_cimdatetime(#{val}[#{val.class}])"
222
+ t = nil
223
+ case val
224
+ when Time
225
+ s = val.strftime "%Y%m%d%H%M%S.%6N"
226
+ utc = val.utc_offset # offset in seconds
227
+ if utc < 0
228
+ s << "-"
229
+ utc = -utc
230
+ else
231
+ s << "+"
232
+ end
233
+ val = s + ("%03d" % (utc/60))
234
+ when Numeric
235
+ if val < 0
236
+ # treat it as seconds before epoch
237
+ val = self.ruby_to_cimdatetime( Time.at(val) )
238
+ else
239
+ # treat as interval in microseconds
240
+ secs = (val / 1000000).to_i
241
+ usecs = (val % 1000000).to_i
242
+ days = secs / (24 * 60 * 60)
243
+ secs = secs % (24 * 60 * 60) # seconds within the day
244
+ hours = (secs / (60 * 60)).to_i
245
+ secs = secs % (60 * 60)
246
+ mins = (secs / 60).to_i
247
+ secs = secs % 60
248
+ val = "%08d%02d%02d%02d.%06d:000" % [ days, hours, mins, secs, usecs ]
249
+ end
250
+ when /^\d{14}\.\d{6}[-+:]\d{3}$/
251
+ # fallthru
252
+ when String
253
+ val = self.ruby_to_cimdatetime val.to_f # retry as Numeric
254
+ else
255
+ val = self.ruby_to_cimdatetime val.to_s # retry as string
256
+ end
257
+ val
258
+ end
182
259
  #
183
260
  # Base class for ValueMap/Values classes from genprovider
184
261
  #
@@ -247,7 +324,8 @@ module Cmpi
247
324
  # -> http://blog.sidu.in/2008/02/loading-classes-from-strings-in-ruby.html
248
325
  @typemap ||= Cmpi.const_get(self.objectpath.classname).typemap
249
326
  t = @typemap[n] if @typemap
250
- # STDERR.puts "Instance.#{n} = #{v}:#{t}"
327
+ # STDERR.printf "Instance.#{n} = #{v}[#{v.class}]:#{t}" % [n, v, v.class, t]
328
+ STDERR.printf "Instance.%s = %s[%s]:%04x\n" % [n, v, v.class, t]
251
329
  self[n,v] = t
252
330
  else
253
331
  # STDERR.puts "CMPIInstance.#{name} -> #{self[s].inspect}"