/*
 * 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);
		}
	}
}
Exemple #2
0
/*
 * 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));
	}
}