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.
- In my shared library I invoke
Invoke aerospike_query_foreach
. - 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 invokesas_query_aggregate
. - Finally, I suspect, the error is generated either on line 992 or 1002.
Does anyone understand what is wrong with my solution?