cmpi-bindings 0.5.2 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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}"