/* * Internal Function: Entry function from UDF code path to send * success result to the caller. Performs * value translation. */ void send_result(as_result * res, udf_call * call) { as_val * v = res->value; if ( res->is_success ) { if ( cf_context_at_severity(AS_UDF, CF_DETAIL) ) { char * str = as_val_tostring(v); cf_detail(AS_UDF, "SUCCESS: %s", str); cf_free(str); } send_success(call, v); } else { // Else -- NOT success if (as_val_type(v) == AS_STRING) { send_udf_failure(call, as_string_fromval(v)); } else { char lua_err_str[1024]; size_t len = (size_t)sprintf(lua_err_str, "%s:0: in function %s() - error() argument type not handled", call->def.filename, call->def.function); call->tr->result_code = AS_PROTO_RESULT_FAIL_UDF_EXECUTION; send_failure_str(call, lua_err_str, len); } } }
/* * Internal Function: Entry function from UDF code path to send * success result to the caller. Performs * value translation. */ void send_result(as_result * res, udf_call * call, void *udata) { // The following "no-op" line serves to quiet the compiler warning of an // otherwise unused variable. udata = udata; as_val * v = res->value; if ( res->is_success ) { if ( cf_context_at_severity(AS_UDF, CF_DETAIL) ) { char * str = as_val_tostring(v); cf_detail(AS_UDF, "SUCCESS: %s", str); cf_free(str); } if ( v != NULL ) { switch( as_val_type(v) ) { case AS_NIL: { send_success(call, AS_PARTICLE_TYPE_NULL, NULL, 0); break; } case AS_BOOLEAN: { as_boolean * b = as_boolean_fromval(v); int64_t bi = as_boolean_tobool(b) == true ? 1 : 0; send_success(call, AS_PARTICLE_TYPE_INTEGER, &bi, 8); break; } case AS_INTEGER: { as_integer * i = as_integer_fromval(v); int64_t ri = as_integer_toint(i); send_success(call, AS_PARTICLE_TYPE_INTEGER, &ri, 8); break; } case AS_STRING: { // this looks bad but it just pulls the pointer // out of the object as_string * s = as_string_fromval(v); char * rs = (char *) as_string_tostring(s); send_success(call, AS_PARTICLE_TYPE_STRING, rs, as_string_len(s)); break; } case AS_BYTES: { as_bytes * b = as_bytes_fromval(v); uint8_t * rs = as_bytes_get(b); send_success(call, AS_PARTICLE_TYPE_BLOB, rs, as_bytes_size(b)); break; } case AS_MAP: case AS_LIST: { as_buffer buf; as_buffer_init(&buf); as_serializer s; as_msgpack_init(&s); int res = as_serializer_serialize(&s, v, &buf); if (res != 0) { const char * error = "Complex Data Type Serialization failure"; cf_warning(AS_UDF, "%s (%d)", (char *)error, res); as_buffer_destroy(&buf); send_cdt_failure(call, AS_PARTICLE_TYPE_STRING, (char *)error, strlen(error)); } else { // Do not use this until after cf_detail_binary() can accept larger buffers. // cf_detail_binary(AS_UDF, buf.data, buf.size, CF_DISPLAY_HEX_COLUMNS, // "serialized %d bytes: ", buf.size); send_success(call, to_particle_type(as_val_type(v)), buf.data, buf.size); // Not needed stack allocated - unless serialize has internal state // as_serializer_destroy(&s); as_buffer_destroy(&buf); } break; } default: { cf_debug(AS_UDF, "SUCCESS: VAL TYPE UNDEFINED %d\n", as_val_type(v)); send_success(call, AS_PARTICLE_TYPE_STRING, NULL, 0); break; } } } else { send_success(call, AS_PARTICLE_TYPE_NULL, NULL, 0); } } else { // Else -- NOT success as_string * s = as_string_fromval(v); char * rs = (char *) as_string_tostring(s); cf_debug(AS_UDF, "FAILURE when calling %s %s %s", call->filename, call->function, rs); send_udf_failure(call, AS_PARTICLE_TYPE_STRING, rs, as_string_len(s)); } }