1

I am trying to create a simple shared library libfoo.so which opens a connection to Aerospike server using a single function, waits for 3 seconds and closes the connection. libfoo.so has a single function open_then_close(char* host, int port).

Then I want to invoke this function from Ruby using FFI:

require 'ffi'

module Aerospike
  extend FFI::Library
  ffi_lib  "./libfoo.so", "libaerospike.so"
  attach_function :connect_then_close, [:string, :int], :int
end

puts Aerospike.connect_then_close("127.0.0.1", 3000)  

I tested foolib.so using a C program, it works fine. However when I try to run the above code I get the following error:

Could not open library '/usr/lib/libaerospike.so': /usr/lib/libaerospike.so: undefined symbol: GENERAL_NAME_free (LoadError)

Additional info:

$ ldd /usr/lib/libaerospike.so
    linux-vdso.so.1 =>  (0x00007ffe413cb000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2ec87a3000)
    /lib64/ld-linux-x86-64.so.2 (0x00005645069a7000)

$ nm -u /usr/lib/libaerospike.so | grep GENERAL_NAME_free
       U GENERAL_NAME_free

Any idea what is wrong?

UPDATE

$ dpkg -l | grep libgcrypt
  ii  libgcrypt11:amd64       1.5.3-2ubuntu4.3        amd64        LGPL Crypto library - runtime library

$ locate libcrypto
  /lib/x86_64-linux-gnu/libcrypto.so.1.0.0
  /usr/lib/x86_64-linux-gnu/libcrypto.a
  /usr/lib/x86_64-linux-gnu/libcrypto.so
  /usr/lib/x86_64-linux-gnu/pkgconfig/libcrypto.pc

This is how I compiled and created libfoo.so

$ gcc -Wall -c -fPIC foo.c -o foo.o -laerospike -lssl -lcrypto -lpthread -lm -lz

Linking the wrong way:

$ gcc -shared -o libfoo.so foo.o
fade2black
  • 546
  • 1
  • 10
  • 26

1 Answers1

2

It looks like the symbol GENERAL_NAME_free is defined by OpenSSL's crypto library according to this man page and this OpenSSL forum post. So you are probably missing the libcrypto library.

But I'm curious, why you are using the Aerospike C client library for your Ruby program instead of using the Aerospike Ruby client? Is there some specific functionality in the C client that is missing from the Ruby client?

Jan Hecking
  • 927
  • 5
  • 12
  • Hi Jan, I have found my mistake. Above I updated my post. The problem was in how I created the shared library. I included them when I compiled but forgot when I created shared library. This is the right way : `gcc -shared -o libfoo.so foo.o -laerospike -lssl -lcrypto -lpthread -lm -lz` – fade2black Mar 29 '17 at 23:17
  • 1
    As for your question, I am trying to implement aggregation from Ruby. As far as I know Aerospike Ruby client does not support aggregation function (map reduce, etc.). Do you have any suggestion for alternative solution? – fade2black Mar 29 '17 at 23:21
  • 1
    @fade2black, you are right, the Ruby client does not support map-reduce-style aggregation using Lua User Defined Functions at the moment. I'm happy to hear that you managed to get your work-around of linking to the C client using FFI working. For now, that's probably the best solution. – Jan Hecking Mar 31 '17 at 00:08
  • Hi Jan, I am curious very much what it is that [does not allow using aggregation from Ruby](https://discuss.aerospike.com/t/udf-execution-error-1-while-using-ffi-ruby/6154). Multithreading? Could you please explain? – fade2black Apr 28 '19 at 14:16
  • @fade2black, it would certainly be technically possible to implement aggregation support for the Ruby client. There seem to be at least two widely used gems that could bridge between Lua and Ruby (rufus-lua and rua), though I have never looked at them in detail. That it never got done is simply a matter of prioritization. We do not see a lot of demand for the Ruby client from our (paying) customers and therefore depend on the community to drive the development of the client. – Jan Hecking Apr 29 '19 at 15:40
  • Cannot understand why I need Lua embedding in Ruby. I have created a C dynamic library (.so) from which I make calls to AS. I tested this library, it works fine from C itself. It works also fine from Ruby when I use non-aggr calls, but fails when aggregation is called. – fade2black Apr 29 '19 at 16:08
  • Lua is required because the last step of the aggregation is executed on the client side. I.e. first each node aggregates the results of the query using the given Lua Stream UDF. All nodes then send their results back to the client. The client executes the same Lua Stream UDF locally to aggregate the partial results from each node. Some Aerospike clients, like e.g. the Node.js client, are implemented as a wrapper around the C client library. The Ruby client on the other hand is implemented as a fully native client, i.e. without using the C client library underneath. – Jan Hecking May 01 '19 at 03:57
  • I'd like to create a simple Ruby community gem that would allow Ruby users make aggregation calls. Could you help at least to start off? – fade2black May 02 '19 at 21:13
  • Even if I was convinced that this is the right way to solve this particular issue, at the moment I do not have the time to contribute to this project myself. – Jan Hecking May 06 '19 at 09:57
  • 1
    @fade2black, see if this library meets your needs: https://github.com/Minus10Degrees/AerospikeCRuby – Jan Hecking May 10 '19 at 13:53
  • Thank you. I'll try it. – fade2black May 10 '19 at 14:23