UDF: Execution Error 1 while using FFI-Ruby

Hi. This is the continuation of my previous post regarding using Stream UDF from Ruby.

Let me first explain what I did.

I use Ubuntu 18.04 desktop, and Aerospike Community Edition build 4.5.2.1. I have aerospike gem and aerospike-client-c-4.6.2.ubuntu18.04.x86_64 installed on my machine.

My goal is to create a shared library libaggregate.so exporting a single function which takes arguments, runs a stream UDF and (for now) prints the result to stdio. I managed to create the libaggregate.so.

C Client

The following where the function is defined

// `aggregate.h`
#ifndef aggregate_h__
#define aggregate_h__

extern int perform(
	const char* host,
	int port,
	const char* ns,
	const char* set,
	const char* pred_bin,
	const char* pred_val,
	const char* mdl,
	const char* fnc,
	const char* arg);

#endif  // aggregate_h__

I simply pass host, port, namespace, set, bin name and value for where-predicate, module name, module function, and a single argument.

I also registered my module using aql and ran aggregation queries. It works fine as expected. Then I create a C client like following

#include <stdio.h>
#include "aggregate.h"

int main()
{
  perform("127.0.0.1", 3000, "myNS", "mySET",
	         "myBIN", "foo", "myMOD", "myFUNC", "myARG");
  return 0;
}

which gives exactly the same!!! output as

aql> AGGREGATE myMOD.myFUNC("myARG") ON myNS.mySET where myBIN="foo"

I experimented with different args, by excluding where predicates and modules and always got expected record sets.

Ruby-FFI

Then tried to run the same queries from my ruby client using FFI-Ruby:

require 'ffi'

module Aggregate
  extend FFI::Library
  ffi_lib_flags :now, :global
  ffi_lib 'libcrypto.so'
  ffi_lib 'libssl.so'
  ffi_lib 'libm.so'
  ffi_lib 'libz.so'
  ffi_lib 'libpthread.so'
  ffi_lib 'libaerospike.so'
  ffi_lib 'glib-2.0.so'
  ffi_lib '../libaggregate.so'

  attach_function :perform, [
  	:string,  # host
  	:int,     # port
  	:string,  # ns
  	:string,  # set
  	:string,  # pred_bin
  	:string,  # pred_val
  	:string,  # mdl
  	:string,  # fnc
  	:string ], :int # arg
end

puts Aggregate.perform("127.0.0.1", 3000, "myNS", "mySET",  "myBIN", "foo",
 "myMOD", "myFUNC", "myARG")

It gives me 100 - UDF: Execution Error 1 where 100 corresponds to AEROSPIKE_ERROR_UDF.

Then I invoked the the same function from Ruby but this time without module, it worked like a charm.

puts Aggregate.perform("127.0.0.1", 3000, "myNS", "mySET",  "myBIN", "foo",
 nil, nil, nil)

Rubyinline

I also tried Rubyonline gem, unfortunately it prints the same!!! error

require 'inline'

class InlineTest
  inline do |builder|
    builder.libs = [
    'libaggregate.so',
    '/usr/lib/libaerospike.so',
    '/usr/lib/x86_64-linux-gnu/libglib-2.0.so',
    '/usr/lib/x86_64-linux-gnu/libpthread.so',
    '/usr/lib/x86_64-linux-gnu/libcrypto.so',
    '/usr/lib/x86_64-linux-gnu/libm.so',
    '/usr/lib/x86_64-linux-gnu/libz.so']

    builder.include '"aggregate.h"'
    builder.c '
      void execute() {
         perform("127.0.0.1", 3000, "myNS", "mySET",
	         "myBIN", "foo", "myMOD", "myFUNC", "myARG");
      }
    '
    builder.build
  end
end

t= InlineTest.new()
t.execute

Outputs is 100 - UDF: Execution Error 1.

Fiddle

Using fiddle gem

require 'fiddle'
require 'fiddle/import'

module LibAggr
  extend Fiddle::Importer
  dlload '/usr/lib/x86_64-linux-gnu/libz.so'
  dlload '/usr/lib/x86_64-linux-gnu/libglib-2.0.so'
  dlload '/usr/lib/x86_64-linux-gnu/libcrypto.so'
  dlload '/usr/lib/libaerospike.so'
  dlload 'libaggregate.so'

  extern 'int perform(const char* host, int port,
	const char* ns,
	const char* set,
	const char* pred_bin,
	const char* pred_val,
	const char* mdl,
	const char* fnc,
	const char* arg)'

end

puts LibAggr.perform("127.0.0.1", 3000, "myNS", "mySET",
	         "myBIN", "foo", "myMOD", "myFUNC", "myARG")

Outputs is 100 - UDF: Execution Error 1.

Examining aerospike.c

Later I examined aerospike.c on github.

  1. In my shared library I invoke Invoke aerospike_query_foreach.
  2. Then on line 1087 it invokes lua aggregation in separate thread as_thread_pool_queue_task(&cluster->thread_pool, as_query_aggregate, &task_aggr); This function queues a task onto thread pool. I guess it invokes as_query_aggregate.
  3. Finally, I suspect, the error is generated either on line 992 or 1002.

Does anyone understand what is wrong with my solution?

Did you find a solution to your problem that you could share and potentially help others? This forum is active but I suspect there is limited expertise in this very specific domain.