aerospike_native 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +17 -2
- data/Rakefile +25 -12
- data/examples/common/common.rb +10 -2
- data/examples/lua/.keep +0 -0
- data/examples/lua/test_udf.lua +16 -0
- data/examples/query_udf.rb +31 -0
- data/examples/scan_udf.rb +36 -0
- data/ext/aerospike_native/aerospike_native.c +2 -0
- data/ext/aerospike_native/client.c +58 -4
- data/ext/aerospike_native/extconf.rb +1 -1
- data/ext/aerospike_native/query.c +81 -11
- data/ext/aerospike_native/scan.c +35 -18
- data/ext/aerospike_native/udf.c +245 -0
- data/ext/aerospike_native/udf.h +10 -0
- data/lib/aerospike_native/version.rb +1 -1
- metadata +8 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a5ac04c52b55cb401bde39b9679e8fa73501e212
|
4
|
+
data.tar.gz: 5e1123f5afc9602e456c8b3f974f850039f281e5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 498fc7414a0759ae4961cd2450e31b6d321031c71a27f1f5ec6ec1f6cdb5fa08ff4135205da193ad9f5229b1254ddedbe85312d0922ec9b4db9c982ea506314e
|
7
|
+
data.tar.gz: 56446e89c9ae3923d583bcaa29122a97ab5830601a4e017daf8141963c2b71e7e2fd494beebf66441fa2517fb2188dcc116e6bc89f8e9c23992d7a58cf0a6c9c
|
data/README.md
CHANGED
@@ -26,7 +26,10 @@ Or install it yourself as:
|
|
26
26
|
* `remove` command
|
27
27
|
* `select` command
|
28
28
|
* `exixts?` command
|
29
|
-
* `query` command (where and
|
29
|
+
* `query` command (where, select and udf support)
|
30
|
+
* `scan` command (select and udf support)
|
31
|
+
* `batch` command (get and exists support)
|
32
|
+
* `udf` command (udf management: put, remove, list, get)
|
30
33
|
* Supported bytes type for non-native object types(string or fixnum) via [msgpack](https://github.com/msgpack/msgpack-ruby)
|
31
34
|
* lists and maps for bin value not supported yet (stored as bytes at the moment)
|
32
35
|
* Supported policies with all parameters for described commands
|
@@ -36,7 +39,19 @@ Or install it yourself as:
|
|
36
39
|
|
37
40
|
## Examples
|
38
41
|
|
39
|
-
|
42
|
+
Located in path `examples`
|
43
|
+
|
44
|
+
Execute in gem root path command `ruby -Ilib:ext -r aerospike_native ./examples/batch.rb` or another example
|
45
|
+
|
46
|
+
Here is a list of examples:
|
47
|
+
|
48
|
+
* _batch.rb_ - batch command example
|
49
|
+
* _operate.rb_ - operate command example
|
50
|
+
* _put_get_remove.rb_ - key-value operatations example
|
51
|
+
* _query_and_index.rb_ - create/drop index and execute query
|
52
|
+
* _query_udf.rb_ - apply udf function to query operation
|
53
|
+
* _scan.rb_ - scan records
|
54
|
+
* _scan_udf.rb_ - apply udf function to scan operation
|
40
55
|
|
41
56
|
## Usage
|
42
57
|
|
data/Rakefile
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'rake/extensiontask'
|
4
4
|
require 'rubygems/package_task'
|
5
|
-
|
5
|
+
require_relative './lib/aerospike_native/version'
|
6
6
|
|
7
7
|
##
|
8
8
|
# Rake::ExtensionTask comes from the rake-compiler and understands how to
|
@@ -20,17 +20,30 @@ Rake::ExtensionTask.new 'aerospike_native' do |ext|
|
|
20
20
|
ext.lib_dir = 'lib/aerospike_native'
|
21
21
|
end
|
22
22
|
|
23
|
-
s = Gem::Specification.new 'aerospike_native', AerospikeNative::VERSION do |
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
23
|
+
s = Gem::Specification.new 'aerospike_native', AerospikeNative::VERSION do |spec|
|
24
|
+
spec.name = "aerospike_native"
|
25
|
+
spec.version = AerospikeNative::VERSION
|
26
|
+
spec.platform = Gem::Platform::RUBY
|
27
|
+
spec.authors = ["Vladimir Ziablitskii"]
|
28
|
+
spec.email = ["zyablitskiy@gmail.com"]
|
29
|
+
spec.summary = %q{Aerospike native client}
|
30
|
+
spec.description = %q{Unofficial Aerospike Client for ruby with c extension (official aerospike c client)}
|
31
|
+
spec.homepage = "https://github.com/rainlabs/aerospike_native"
|
32
|
+
spec.license = "MIT"
|
33
|
+
# spec.required_ruby_version = '>= 1.9.3'
|
34
|
+
|
35
|
+
spec.files = `git ls-files -z`.split("\x0")
|
36
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
37
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
38
|
+
spec.require_paths = ["lib", "ext"]
|
39
|
+
spec.extensions = %w[ext/aerospike_native/extconf.rb]
|
40
|
+
|
41
|
+
spec.add_dependency "msgpack", "~> 0.6"
|
42
|
+
|
43
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
44
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
45
|
+
spec.add_development_dependency "rake-compiler", "~> 0.9"
|
46
|
+
spec.add_development_dependency "rspec", "~> 3.3"
|
34
47
|
end
|
35
48
|
|
36
49
|
# The package task builds the gem in pkg/my_malloc-1.0.gem so you can test
|
data/examples/common/common.rb
CHANGED
@@ -6,7 +6,7 @@ module Common
|
|
6
6
|
class << self
|
7
7
|
def namespace; 'test' end
|
8
8
|
def set; 'examples' end
|
9
|
-
def client; @@client ||= AerospikeNative::Client.new([{
|
9
|
+
def client; @@client ||= AerospikeNative::Client.new([{host: '127.0.0.1', port: 3010}], {lua: {system_path: udf_system_path, user_path: udf_user_path}}) end
|
10
10
|
|
11
11
|
def cleanup
|
12
12
|
client.query(namespace, set).exec{ |record| client.remove(record.key) }
|
@@ -26,6 +26,14 @@ module Common
|
|
26
26
|
client
|
27
27
|
end
|
28
28
|
|
29
|
+
def udf_system_path
|
30
|
+
'./ext/aerospike_native/aerospike-client-c/modules/lua-core/src'
|
31
|
+
end
|
32
|
+
|
33
|
+
def udf_user_path
|
34
|
+
'./examples/lua'
|
35
|
+
end
|
36
|
+
|
29
37
|
def run_example
|
30
38
|
init
|
31
39
|
custom_logger.info "Example started"
|
@@ -35,4 +43,4 @@ module Common
|
|
35
43
|
end
|
36
44
|
end
|
37
45
|
end
|
38
|
-
end
|
46
|
+
end
|
data/examples/lua/.keep
ADDED
File without changes
|
@@ -0,0 +1,16 @@
|
|
1
|
+
local function get_number(rec)
|
2
|
+
return rec['number']
|
3
|
+
end
|
4
|
+
|
5
|
+
local function add(a, b)
|
6
|
+
return a + b
|
7
|
+
end
|
8
|
+
|
9
|
+
function sum_number(stream)
|
10
|
+
return stream : map(get_number) : reduce(add)
|
11
|
+
end
|
12
|
+
|
13
|
+
function add_testbin_to_number(rec)
|
14
|
+
rec['number'] = rec['number'] + rec['testbin'];
|
15
|
+
aerospike:update(rec)
|
16
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require_relative './common/common'
|
2
|
+
|
3
|
+
def main
|
4
|
+
Common::Common.run_example do |client, namespace, set, logger|
|
5
|
+
logger.info "Found user scripts: #{client.udf.list}"
|
6
|
+
|
7
|
+
ruby_sum = 0
|
8
|
+
20.times do |i|
|
9
|
+
ruby_sum += i
|
10
|
+
client.put(AerospikeNative::Key.new(namespace, set, i), {'number' => i, 'key' => 'number', 'testbin' => i.to_s})
|
11
|
+
end
|
12
|
+
|
13
|
+
client.udf.put("./examples/lua/test_udf.lua")
|
14
|
+
logger.info "adding user script..."
|
15
|
+
client.udf.wait("test_udf.lua", 1000)
|
16
|
+
logger.info "Found user scripts: #{client.udf.list}"
|
17
|
+
logger.info "user script already added"
|
18
|
+
|
19
|
+
logger.info "perform a aggregate query"
|
20
|
+
sum = client.query(namespace, set).apply("test_udf", "sum_number").exec.first
|
21
|
+
logger.info "ruby sum #{ruby_sum}"
|
22
|
+
logger.info "aerospike sum #{sum}"
|
23
|
+
|
24
|
+
logger.info "removing user script..."
|
25
|
+
client.udf.remove("test_udf.lua")
|
26
|
+
logger.info "Found user scripts: #{client.udf.list}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
main
|
31
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require_relative './common/common'
|
2
|
+
|
3
|
+
def main
|
4
|
+
Common::Common.run_example do |client, namespace, set, logger|
|
5
|
+
logger.info "Found user scripts: #{client.udf.list}"
|
6
|
+
|
7
|
+
3.times do |i|
|
8
|
+
client.put(AerospikeNative::Key.new(namespace, set, i), {'number' => i, 'key' => 'number', 'testbin' => i})
|
9
|
+
end
|
10
|
+
|
11
|
+
client.udf.put("./examples/lua/test_udf.lua")
|
12
|
+
logger.info "adding user script..."
|
13
|
+
client.udf.wait("test_udf.lua", 1000)
|
14
|
+
logger.info "Found user scripts: #{client.udf.list}"
|
15
|
+
logger.info "user script already added"
|
16
|
+
|
17
|
+
logger.info "performing update scan..."
|
18
|
+
scan_id = client.scan(namespace, set).apply("test_udf", "add_testbin_to_number").exec
|
19
|
+
loop do
|
20
|
+
info = client.scan_info(scan_id)
|
21
|
+
logger.info "scan info: #{info}"
|
22
|
+
break if info['status'] == AerospikeNative::Scan::STATUS_COMPLETED
|
23
|
+
sleep 1
|
24
|
+
end
|
25
|
+
records = client.query(namespace, set).exec
|
26
|
+
logger.info records.map(&:bins).inspect
|
27
|
+
|
28
|
+
logger.info "removing user script..."
|
29
|
+
client.udf.remove("test_udf.lua")
|
30
|
+
logger.info "Found user scripts: #{client.udf.list}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
main
|
35
|
+
|
36
|
+
|
@@ -7,6 +7,7 @@
|
|
7
7
|
#include "query.h"
|
8
8
|
#include "batch.h"
|
9
9
|
#include "scan.h"
|
10
|
+
#include "udf.h"
|
10
11
|
|
11
12
|
VALUE AerospikeNativeClass;
|
12
13
|
VALUE MsgPackClass;
|
@@ -17,6 +18,7 @@ void Init_aerospike_native()
|
|
17
18
|
AerospikeNativeClass = rb_define_module("AerospikeNative");
|
18
19
|
define_exception();
|
19
20
|
define_logger();
|
21
|
+
define_udf();
|
20
22
|
define_query();
|
21
23
|
define_scan();
|
22
24
|
define_batch();
|
@@ -5,6 +5,7 @@
|
|
5
5
|
#include "query.h"
|
6
6
|
#include "batch.h"
|
7
7
|
#include "scan.h"
|
8
|
+
#include "udf.h"
|
8
9
|
#include <aerospike/as_key.h>
|
9
10
|
#include <aerospike/as_operations.h>
|
10
11
|
#include <aerospike/aerospike_key.h>
|
@@ -51,32 +52,76 @@ static VALUE client_allocate(VALUE klass)
|
|
51
52
|
*/
|
52
53
|
VALUE client_initialize(int argc, VALUE* argv, VALUE self)
|
53
54
|
{
|
54
|
-
VALUE ary = Qnil;
|
55
|
+
VALUE ary = Qnil, vSettings = Qnil;
|
55
56
|
aerospike *ptr;
|
56
57
|
as_config config;
|
57
58
|
as_error err;
|
58
59
|
long idx = 0, n = 0;
|
59
60
|
|
60
|
-
if (argc >
|
61
|
-
rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..
|
61
|
+
if (argc > 2) { // there should only be 0, 1 or 2 arguments
|
62
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..2)", argc);
|
62
63
|
}
|
63
64
|
|
64
65
|
if (argc == 1) {
|
65
66
|
ary = argv[0];
|
66
67
|
}
|
67
68
|
|
68
|
-
switch (TYPE(
|
69
|
+
switch (TYPE(argv[0])) {
|
69
70
|
case T_NIL:
|
70
71
|
case T_ARRAY:
|
72
|
+
ary = argv[0];
|
73
|
+
break;
|
74
|
+
case T_HASH:
|
75
|
+
vSettings = argv[0];
|
76
|
+
if (argc > 1) {
|
77
|
+
rb_raise(rb_eArgError, "wrong number of arguments (detected settings hash as first parameter)", argc);
|
78
|
+
}
|
71
79
|
break;
|
72
80
|
default:
|
73
81
|
/* raise exception */
|
74
82
|
Check_Type(ary, T_ARRAY);
|
75
83
|
break;
|
76
84
|
}
|
85
|
+
|
86
|
+
if(argc == 2) {
|
87
|
+
switch (TYPE(argv[1])) {
|
88
|
+
case T_NIL:
|
89
|
+
case T_HASH:
|
90
|
+
vSettings = argv[1];
|
91
|
+
break;
|
92
|
+
default:
|
93
|
+
/* raise exception */
|
94
|
+
Check_Type(ary, T_HASH);
|
95
|
+
break;
|
96
|
+
}
|
97
|
+
}
|
98
|
+
|
77
99
|
Data_Get_Struct(self, aerospike, ptr);
|
78
100
|
|
79
101
|
as_config_init(&config);
|
102
|
+
if (TYPE(vSettings) != T_NIL) {
|
103
|
+
VALUE vLua = rb_hash_aref(vSettings, rb_str_new2("lua"));
|
104
|
+
if (TYPE(vLua) == T_NIL) {
|
105
|
+
vLua = rb_hash_aref(vSettings, ID2SYM( rb_intern("lua") ));
|
106
|
+
}
|
107
|
+
if (TYPE(vLua) == T_HASH) {
|
108
|
+
VALUE vSystemPath = rb_hash_aref(vLua, rb_str_new2("system_path"));
|
109
|
+
VALUE vUserPath = rb_hash_aref(vLua, rb_str_new2("user_path"));
|
110
|
+
if (TYPE(vSystemPath) == T_NIL) {
|
111
|
+
vSystemPath = rb_hash_aref(vLua, ID2SYM( rb_intern("system_path") ));
|
112
|
+
}
|
113
|
+
if (TYPE(vUserPath) == T_NIL) {
|
114
|
+
vUserPath = rb_hash_aref(vLua, ID2SYM( rb_intern("user_path") ));
|
115
|
+
}
|
116
|
+
|
117
|
+
if (TYPE(vSystemPath) == T_STRING) {
|
118
|
+
strcpy(config.lua.system_path, StringValueCStr(vSystemPath));
|
119
|
+
}
|
120
|
+
if (TYPE(vUserPath) == T_STRING) {
|
121
|
+
strcpy(config.lua.user_path, StringValueCStr(vUserPath));
|
122
|
+
}
|
123
|
+
}
|
124
|
+
}
|
80
125
|
|
81
126
|
if (TYPE(ary) == T_ARRAY) {
|
82
127
|
idx = RARRAY_LEN(ary);
|
@@ -708,6 +753,14 @@ VALUE client_scan_info(int argc, VALUE* vArgs, VALUE vSelf)
|
|
708
753
|
return rb_funcall2(ScanClass, rb_intern("info"), 3, vParams);
|
709
754
|
}
|
710
755
|
|
756
|
+
VALUE client_udf(VALUE vSelf)
|
757
|
+
{
|
758
|
+
VALUE vParams[1];
|
759
|
+
vParams[0] = vSelf;
|
760
|
+
|
761
|
+
return rb_class_new_instance(1, vParams, UdfClass);
|
762
|
+
}
|
763
|
+
|
711
764
|
void define_client()
|
712
765
|
{
|
713
766
|
ClientClass = rb_define_class_under(AerospikeNativeClass, "Client", rb_cObject);
|
@@ -725,6 +778,7 @@ void define_client()
|
|
725
778
|
rb_define_method(ClientClass, "batch", client_batch, 0);
|
726
779
|
rb_define_method(ClientClass, "scan", client_scan, 2);
|
727
780
|
rb_define_method(ClientClass, "scan_info", client_scan_info, -1);
|
781
|
+
rb_define_method(ClientClass, "udf", client_udf, 0);
|
728
782
|
|
729
783
|
LoggerInstance = rb_class_new_instance(0, NULL, LoggerClass);
|
730
784
|
rb_cv_set(ClientClass, "@@logger", LoggerInstance);
|
@@ -10,7 +10,7 @@ have_library('crypto')
|
|
10
10
|
|
11
11
|
headers_path = File.expand_path(File.join(File.dirname(__FILE__), "include"))
|
12
12
|
lib_path = File.expand_path(File.join(File.dirname(__FILE__), "lib"))
|
13
|
-
aerospike_client_c_dir = File.expand_path(File.join(File.dirname(__FILE__), "aerospike-client-c"))
|
13
|
+
aerospike_client_c_dir = "aerospike-client-c" #File.expand_path(File.join(File.dirname(__FILE__), "aerospike-client-c"))
|
14
14
|
`git clone https://github.com/aerospike/aerospike-client-c.git`
|
15
15
|
Dir.chdir(aerospike_client_c_dir) do
|
16
16
|
`git reset --hard f4aa41fc237fca3e25110d15e72b7735262e6653`
|
@@ -143,26 +143,77 @@ VALUE query_where(VALUE vSelf, VALUE vHash)
|
|
143
143
|
return vSelf;
|
144
144
|
}
|
145
145
|
|
146
|
+
VALUE query_apply(int argc, VALUE* vArgs, VALUE vSelf)
|
147
|
+
{
|
148
|
+
if (argc < 2 || argc > 3) { // there should only be 2 or 3 arguments
|
149
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%d for 2..3)", argc);
|
150
|
+
}
|
151
|
+
|
152
|
+
Check_Type(vArgs[0], T_STRING);
|
153
|
+
Check_Type(vArgs[1], T_STRING);
|
154
|
+
rb_iv_set(vSelf, "@udf_module", vArgs[0]);
|
155
|
+
rb_iv_set(vSelf, "@udf_function", vArgs[1]);
|
156
|
+
|
157
|
+
if (argc == 3 && TYPE(vArgs[2]) != T_NIL) {
|
158
|
+
Check_Type(vArgs[2], T_ARRAY);
|
159
|
+
}
|
160
|
+
|
161
|
+
return vSelf;
|
162
|
+
}
|
163
|
+
|
146
164
|
bool query_callback(const as_val *value, void *udata) {
|
147
165
|
VALUE vRecord;
|
148
|
-
as_record *record;
|
149
166
|
|
150
167
|
if (value == NULL) {
|
151
168
|
// query is complete
|
152
169
|
return true;
|
153
170
|
}
|
154
171
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
if ( rb_block_given_p() ) {
|
161
|
-
rb_yield(vRecord);
|
162
|
-
} else {
|
163
|
-
VALUE *vArray = (VALUE*) udata;
|
164
|
-
rb_ary_push(*vArray, vRecord);
|
172
|
+
switch(as_val_type(value)) {
|
173
|
+
case AS_REC: {
|
174
|
+
as_record* record = as_record_fromval(value);
|
175
|
+
if (record != NULL) {
|
176
|
+
vRecord = rb_record_from_c(record, NULL);
|
165
177
|
}
|
178
|
+
break;
|
179
|
+
}
|
180
|
+
case AS_INTEGER: {
|
181
|
+
as_integer* integer = as_integer_fromval(value);
|
182
|
+
if (integer != NULL) {
|
183
|
+
vRecord = LONG2NUM( as_integer_get(integer) );
|
184
|
+
}
|
185
|
+
break;
|
186
|
+
}
|
187
|
+
case AS_STRING: {
|
188
|
+
as_string* string = as_string_fromval(value);
|
189
|
+
if (string != NULL) {
|
190
|
+
vRecord = LONG2NUM( as_string_get(string) );
|
191
|
+
}
|
192
|
+
break;
|
193
|
+
}
|
194
|
+
case AS_NIL:
|
195
|
+
vRecord = Qnil;
|
196
|
+
break;
|
197
|
+
case AS_BOOLEAN: {
|
198
|
+
as_integer* integer = as_integer_fromval(value);
|
199
|
+
if (integer != NULL) {
|
200
|
+
vRecord = LONG2NUM( as_integer_get(integer) );
|
201
|
+
}
|
202
|
+
break;
|
203
|
+
}
|
204
|
+
case AS_LIST:
|
205
|
+
case AS_MAP:
|
206
|
+
case AS_PAIR:
|
207
|
+
case AS_UNDEF:
|
208
|
+
default:
|
209
|
+
break;
|
210
|
+
}
|
211
|
+
|
212
|
+
if ( rb_block_given_p() ) {
|
213
|
+
rb_yield(vRecord);
|
214
|
+
} else {
|
215
|
+
VALUE *vArray = (VALUE*) udata;
|
216
|
+
rb_ary_push(*vArray, vRecord);
|
166
217
|
}
|
167
218
|
|
168
219
|
return true;
|
@@ -175,6 +226,7 @@ VALUE query_exec(int argc, VALUE* vArgs, VALUE vSelf)
|
|
175
226
|
VALUE vArray;
|
176
227
|
VALUE vClient;
|
177
228
|
VALUE vWhere, vSelect, vOrder;
|
229
|
+
VALUE vUdfModule;
|
178
230
|
VALUE vWhereKeys, vOrderKeys;
|
179
231
|
|
180
232
|
aerospike *ptr;
|
@@ -293,6 +345,19 @@ VALUE query_exec(int argc, VALUE* vArgs, VALUE vSelf)
|
|
293
345
|
}
|
294
346
|
}
|
295
347
|
|
348
|
+
vUdfModule = rb_iv_get(vSelf, "@udf_module");
|
349
|
+
switch(TYPE(vUdfModule)) {
|
350
|
+
case T_NIL:
|
351
|
+
break;
|
352
|
+
case T_STRING: {
|
353
|
+
VALUE vUdfFunction = rb_iv_get(vSelf, "@udf_function");
|
354
|
+
as_query_apply(&query, StringValueCStr(vUdfModule), StringValueCStr(vUdfFunction), NULL);
|
355
|
+
break;
|
356
|
+
}
|
357
|
+
default:
|
358
|
+
rb_raise(rb_eTypeError, "wrong argument type for udf module (expected String or Nil)");
|
359
|
+
}
|
360
|
+
|
296
361
|
vArray = rb_ary_new();
|
297
362
|
if (aerospike_query_foreach(ptr, &err, &policy, &query, query_callback, &vArray) != AEROSPIKE_OK) {
|
298
363
|
as_query_destroy(&query);
|
@@ -314,6 +379,7 @@ void define_query()
|
|
314
379
|
rb_define_method(QueryClass, "select", query_select, -1);
|
315
380
|
rb_define_method(QueryClass, "order", query_order, 1);
|
316
381
|
rb_define_method(QueryClass, "where", query_where, 1);
|
382
|
+
rb_define_method(QueryClass, "apply", query_apply, -1);
|
317
383
|
rb_define_method(QueryClass, "exec", query_exec, -1);
|
318
384
|
|
319
385
|
rb_define_attr(QueryClass, "client", 1, 0);
|
@@ -322,4 +388,8 @@ void define_query()
|
|
322
388
|
rb_define_attr(QueryClass, "select_bins", 1, 0);
|
323
389
|
rb_define_attr(QueryClass, "where_bins", 1, 0);
|
324
390
|
rb_define_attr(QueryClass, "order_bins", 1, 0);
|
391
|
+
|
392
|
+
rb_define_attr(QueryClass, "udf_module", 1, 0);
|
393
|
+
rb_define_attr(QueryClass, "udf_function", 1, 0);
|
394
|
+
rb_define_attr(QueryClass, "udf_arglist", 1, 0);
|
325
395
|
}
|
data/ext/aerospike_native/scan.c
CHANGED
@@ -5,12 +5,6 @@
|
|
5
5
|
|
6
6
|
VALUE ScanClass;
|
7
7
|
|
8
|
-
static void scan_deallocate(void *p)
|
9
|
-
{
|
10
|
-
as_scan* ptr = p;
|
11
|
-
as_scan_destroy(ptr);
|
12
|
-
}
|
13
|
-
|
14
8
|
VALUE scan_initialize(VALUE vSelf, VALUE vClient, VALUE vNamespace, VALUE vSet)
|
15
9
|
{
|
16
10
|
Check_Type(vNamespace, T_STRING);
|
@@ -90,9 +84,21 @@ VALUE scan_no_bins(VALUE vSelf, VALUE vValue)
|
|
90
84
|
return vSelf;
|
91
85
|
}
|
92
86
|
|
93
|
-
VALUE
|
87
|
+
VALUE scan_apply(int argc, VALUE* vArgs, VALUE vSelf)
|
94
88
|
{
|
95
|
-
|
89
|
+
if (argc < 2 || argc > 3) { // there should only be 2 or 3 arguments
|
90
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%d for 2..3)", argc);
|
91
|
+
}
|
92
|
+
|
93
|
+
Check_Type(vArgs[0], T_STRING);
|
94
|
+
Check_Type(vArgs[1], T_STRING);
|
95
|
+
rb_iv_set(vSelf, "@udf_module", vArgs[0]);
|
96
|
+
rb_iv_set(vSelf, "@udf_function", vArgs[1]);
|
97
|
+
|
98
|
+
if (argc == 3 && TYPE(vArgs[2]) != T_NIL) {
|
99
|
+
Check_Type(vArgs[2], T_ARRAY);
|
100
|
+
}
|
101
|
+
|
96
102
|
return vSelf;
|
97
103
|
}
|
98
104
|
|
@@ -109,7 +115,7 @@ VALUE scan_exec(int argc, VALUE* vArgs, VALUE vSelf)
|
|
109
115
|
{
|
110
116
|
VALUE vClient, vNamespace, vSet;
|
111
117
|
VALUE vArray;
|
112
|
-
VALUE vConcurrent, vPercent, vPriority, vBins, vNoBins,
|
118
|
+
VALUE vConcurrent, vPercent, vPriority, vBins, vNoBins, vUdfModule;
|
113
119
|
as_scan scan;
|
114
120
|
as_policy_scan policy;
|
115
121
|
as_error err;
|
@@ -135,7 +141,6 @@ VALUE scan_exec(int argc, VALUE* vArgs, VALUE vSelf)
|
|
135
141
|
vPriority = rb_iv_get(vSelf, "@priority");
|
136
142
|
vNoBins = rb_iv_get(vSelf, "@no_bins");
|
137
143
|
vBins = rb_iv_get(vSelf, "@select_bins");
|
138
|
-
vBackground = rb_iv_get(vSelf, "@background");
|
139
144
|
as_scan_init(&scan, StringValueCStr(vNamespace), StringValueCStr(vSet));
|
140
145
|
|
141
146
|
if (TYPE(vPercent) == T_FIXNUM) {
|
@@ -154,10 +159,6 @@ VALUE scan_exec(int argc, VALUE* vArgs, VALUE vSelf)
|
|
154
159
|
as_scan_set_nobins(&scan, RTEST(vNoBins));
|
155
160
|
}
|
156
161
|
|
157
|
-
if (TYPE(vBackground) != T_NIL) {
|
158
|
-
is_background = RTEST(vBackground);
|
159
|
-
}
|
160
|
-
|
161
162
|
if (TYPE(vBins) == T_ARRAY && (idx = RARRAY_LEN(vBins)) > 0) {
|
162
163
|
as_scan_select_inita(&scan, idx);
|
163
164
|
for(n = 0; n < idx; n++) {
|
@@ -166,6 +167,20 @@ VALUE scan_exec(int argc, VALUE* vArgs, VALUE vSelf)
|
|
166
167
|
}
|
167
168
|
}
|
168
169
|
|
170
|
+
vUdfModule = rb_iv_get(vSelf, "@udf_module");
|
171
|
+
switch(TYPE(vUdfModule)) {
|
172
|
+
case T_NIL:
|
173
|
+
break;
|
174
|
+
case T_STRING: {
|
175
|
+
VALUE vUdfFunction = rb_iv_get(vSelf, "@udf_function");
|
176
|
+
as_scan_apply_each(&scan, StringValueCStr(vUdfModule), StringValueCStr(vUdfFunction), NULL);
|
177
|
+
is_background = true;
|
178
|
+
break;
|
179
|
+
}
|
180
|
+
default:
|
181
|
+
rb_raise(rb_eTypeError, "wrong argument type for udf module (expected String or Nil)");
|
182
|
+
}
|
183
|
+
|
169
184
|
Data_Get_Struct(vClient, aerospike, ptr);
|
170
185
|
|
171
186
|
vArray = rb_ary_new();
|
@@ -216,8 +231,8 @@ VALUE scan_info(int argc, VALUE* vArgs, VALUE vSelf)
|
|
216
231
|
vClient = vArgs[0];
|
217
232
|
check_aerospike_client(vClient);
|
218
233
|
|
219
|
-
Check_Type(vArgs[1],
|
220
|
-
scan_id =
|
234
|
+
// Check_Type(vArgs[1], T_BIGNUM);
|
235
|
+
scan_id = NUM2ULONG(vArgs[1]);
|
221
236
|
|
222
237
|
as_policy_scan_init(&policy);
|
223
238
|
if(argc == 3 && TYPE(vArgs[2]) != T_NIL) {
|
@@ -248,7 +263,7 @@ void define_scan()
|
|
248
263
|
rb_define_method(ScanClass, "set_percent", scan_percent, 1);
|
249
264
|
rb_define_method(ScanClass, "set_priority", scan_priority, 1);
|
250
265
|
rb_define_method(ScanClass, "set_no_bins", scan_no_bins, 1);
|
251
|
-
|
266
|
+
rb_define_method(ScanClass, "apply", scan_apply, -1);
|
252
267
|
rb_define_singleton_method(ScanClass, "info", scan_info, -1);
|
253
268
|
|
254
269
|
rb_define_attr(ScanClass, "client", 1, 0);
|
@@ -257,7 +272,9 @@ void define_scan()
|
|
257
272
|
rb_define_attr(ScanClass, "percent", 1, 0);
|
258
273
|
rb_define_attr(ScanClass, "priority", 1, 0);
|
259
274
|
rb_define_attr(ScanClass, "no_bins", 1, 0);
|
260
|
-
rb_define_attr(
|
275
|
+
rb_define_attr(QueryClass, "udf_module", 1, 0);
|
276
|
+
rb_define_attr(QueryClass, "udf_function", 1, 0);
|
277
|
+
rb_define_attr(QueryClass, "udf_arglist", 1, 0);
|
261
278
|
|
262
279
|
rb_define_const(ScanClass, "STATUS_UNDEFINED", INT2FIX(AS_SCAN_STATUS_UNDEF));
|
263
280
|
rb_define_const(ScanClass, "STATUS_INPROGRESS", INT2FIX(AS_SCAN_STATUS_INPROGRESS));
|
@@ -0,0 +1,245 @@
|
|
1
|
+
#include "udf.h"
|
2
|
+
#include "client.h"
|
3
|
+
#include <aerospike/aerospike_udf.h>
|
4
|
+
|
5
|
+
VALUE UdfClass;
|
6
|
+
|
7
|
+
VALUE udf_initialize(VALUE vSelf, VALUE vClient)
|
8
|
+
{
|
9
|
+
check_aerospike_client(vClient);
|
10
|
+
rb_iv_set(vSelf, "@client", vClient);
|
11
|
+
|
12
|
+
return vSelf;
|
13
|
+
}
|
14
|
+
|
15
|
+
VALUE udf_put(int argc, VALUE* vArgs, VALUE vSelf)
|
16
|
+
{
|
17
|
+
VALUE vClient;
|
18
|
+
FILE* file;
|
19
|
+
aerospike* ptr;
|
20
|
+
// uint8_t* content; //, p_write;
|
21
|
+
int read, size;
|
22
|
+
as_error err;
|
23
|
+
as_string base_string;
|
24
|
+
as_bytes udf_content;
|
25
|
+
as_policy_info policy;
|
26
|
+
|
27
|
+
if (argc > 2 || argc < 1) { // there should only be 1 or 2 argument
|
28
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..2)", argc);
|
29
|
+
}
|
30
|
+
|
31
|
+
Check_Type(vArgs[0], T_STRING);
|
32
|
+
file = fopen(StringValueCStr(vArgs[0]), "r");
|
33
|
+
|
34
|
+
if (!file) {
|
35
|
+
rb_funcall(LoggerInstance, rb_intern("warn"), 1, rb_str_new2("register UDF: File Not Found"));
|
36
|
+
return Qfalse;
|
37
|
+
}
|
38
|
+
|
39
|
+
as_policy_info_init(&policy);
|
40
|
+
if(argc == 2 && TYPE(vArgs[1]) != T_NIL) {
|
41
|
+
SET_INFO_POLICY(policy, vArgs[1]);
|
42
|
+
}
|
43
|
+
|
44
|
+
// Read the file's content into a local buffer.
|
45
|
+
|
46
|
+
uint8_t* content = (uint8_t*)malloc(1024 * 1024);
|
47
|
+
|
48
|
+
if (! content) {
|
49
|
+
rb_funcall(LoggerInstance, rb_intern("warn"), 1, rb_str_new2("script content allocation failed"));
|
50
|
+
return Qfalse;
|
51
|
+
}
|
52
|
+
|
53
|
+
uint8_t* p_write = content;
|
54
|
+
read = (int)fread(p_write, 1, 512, file);
|
55
|
+
size = 0;
|
56
|
+
|
57
|
+
while (read) {
|
58
|
+
size += read;
|
59
|
+
p_write += read;
|
60
|
+
read = (int)fread(p_write, 1, 512, file);
|
61
|
+
}
|
62
|
+
|
63
|
+
fclose(file);
|
64
|
+
|
65
|
+
// Wrap the local buffer as an as_bytes object.
|
66
|
+
as_bytes_init_wrap(&udf_content, content, size, true);
|
67
|
+
|
68
|
+
vClient = rb_iv_get(vSelf, "@client");
|
69
|
+
Data_Get_Struct(vClient, aerospike, ptr);
|
70
|
+
|
71
|
+
// Register the UDF file in the database cluster.
|
72
|
+
if (aerospike_udf_put(ptr, &err, &policy, as_basename(&base_string, StringValueCStr(vArgs[0])), AS_UDF_TYPE_LUA,
|
73
|
+
&udf_content) != AEROSPIKE_OK) {
|
74
|
+
as_bytes_destroy(&udf_content);
|
75
|
+
raise_aerospike_exception(err.code, err.message);
|
76
|
+
}
|
77
|
+
|
78
|
+
// This frees the local buffer.
|
79
|
+
as_bytes_destroy(&udf_content);
|
80
|
+
|
81
|
+
return Qtrue;
|
82
|
+
}
|
83
|
+
|
84
|
+
VALUE udf_remove(int argc, VALUE* vArgs, VALUE vSelf)
|
85
|
+
{
|
86
|
+
VALUE vClient;
|
87
|
+
aerospike* ptr;
|
88
|
+
as_error err;
|
89
|
+
as_policy_info policy;
|
90
|
+
|
91
|
+
if (argc > 2 || argc < 1) { // there should only be 1 or 2 argument
|
92
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..2)", argc);
|
93
|
+
}
|
94
|
+
|
95
|
+
Check_Type(vArgs[0], T_STRING);
|
96
|
+
|
97
|
+
as_policy_info_init(&policy);
|
98
|
+
if(argc == 2 && TYPE(vArgs[1]) != T_NIL) {
|
99
|
+
SET_INFO_POLICY(policy, vArgs[1]);
|
100
|
+
}
|
101
|
+
|
102
|
+
vClient = rb_iv_get(vSelf, "@client");
|
103
|
+
Data_Get_Struct(vClient, aerospike, ptr);
|
104
|
+
|
105
|
+
// Remove the UDF file in the database cluster.
|
106
|
+
if (aerospike_udf_remove(ptr, &err, &policy, StringValueCStr(vArgs[0])) != AEROSPIKE_OK) {
|
107
|
+
raise_aerospike_exception(err.code, err.message);
|
108
|
+
}
|
109
|
+
|
110
|
+
return Qtrue;
|
111
|
+
}
|
112
|
+
|
113
|
+
VALUE udf_list(int argc, VALUE* vArgs, VALUE vSelf)
|
114
|
+
{
|
115
|
+
VALUE vClient, vHash;
|
116
|
+
aerospike* ptr;
|
117
|
+
as_error err;
|
118
|
+
as_policy_info policy;
|
119
|
+
as_udf_files files;
|
120
|
+
|
121
|
+
int n;
|
122
|
+
|
123
|
+
if (argc > 1) { // there should only be 0 or 1 argument
|
124
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..1)", argc);
|
125
|
+
}
|
126
|
+
|
127
|
+
as_policy_info_init(&policy);
|
128
|
+
if(argc == 1 && TYPE(vArgs[0]) != T_NIL) {
|
129
|
+
SET_INFO_POLICY(policy, vArgs[0]);
|
130
|
+
}
|
131
|
+
|
132
|
+
vClient = rb_iv_get(vSelf, "@client");
|
133
|
+
Data_Get_Struct(vClient, aerospike, ptr);
|
134
|
+
|
135
|
+
vHash = rb_hash_new();
|
136
|
+
as_udf_files_init(&files, 0);
|
137
|
+
if (aerospike_udf_list(ptr, &err, &policy, &files) != AEROSPIKE_OK) {
|
138
|
+
raise_aerospike_exception(err.code, err.message);
|
139
|
+
}
|
140
|
+
|
141
|
+
for(n = 0; n < files.size; n++) {
|
142
|
+
as_udf_file file = files.entries[n];
|
143
|
+
VALUE vParamHash = rb_hash_new();
|
144
|
+
rb_hash_aset(vParamHash, rb_str_new2("type"), INT2FIX(file.type));
|
145
|
+
rb_hash_aset(vParamHash, rb_str_new2("hash"), rb_str_new(file.hash, AS_UDF_FILE_HASH_SIZE));
|
146
|
+
rb_hash_aset(vHash, rb_str_new2(file.name), vParamHash);
|
147
|
+
}
|
148
|
+
|
149
|
+
return vHash;
|
150
|
+
}
|
151
|
+
|
152
|
+
VALUE udf_get(int argc, VALUE* vArgs, VALUE vSelf)
|
153
|
+
{
|
154
|
+
VALUE vClient, vHash, vParamHash;
|
155
|
+
aerospike* ptr;
|
156
|
+
as_error err;
|
157
|
+
as_policy_info policy;
|
158
|
+
as_udf_file file;
|
159
|
+
|
160
|
+
if (argc > 2 || argc < 1) { // there should only be 1 or 2 argument
|
161
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..2)", argc);
|
162
|
+
}
|
163
|
+
|
164
|
+
as_policy_info_init(&policy);
|
165
|
+
if(argc == 2 && TYPE(vArgs[1]) != T_NIL) {
|
166
|
+
SET_INFO_POLICY(policy, vArgs[1]);
|
167
|
+
}
|
168
|
+
|
169
|
+
vClient = rb_iv_get(vSelf, "@client");
|
170
|
+
Data_Get_Struct(vClient, aerospike, ptr);
|
171
|
+
|
172
|
+
vHash = rb_hash_new();
|
173
|
+
as_udf_file_init(&file);
|
174
|
+
if (aerospike_udf_get(ptr, &err, &policy, StringValueCStr(vArgs[0]), AS_UDF_TYPE_LUA, &file) != AEROSPIKE_OK) {
|
175
|
+
raise_aerospike_exception(err.code, err.message);
|
176
|
+
}
|
177
|
+
|
178
|
+
vParamHash = rb_hash_new();
|
179
|
+
rb_hash_aset(vParamHash, rb_str_new2("type"), INT2FIX(file.type));
|
180
|
+
rb_hash_aset(vParamHash, rb_str_new2("hash"), rb_str_new(file.hash, AS_UDF_FILE_HASH_SIZE));
|
181
|
+
rb_hash_aset(vHash, rb_str_new2(file.name), vParamHash);
|
182
|
+
|
183
|
+
return vHash;
|
184
|
+
}
|
185
|
+
|
186
|
+
VALUE udf_wait(int argc, VALUE* vArgs, VALUE vSelf)
|
187
|
+
{
|
188
|
+
VALUE vClient, vSettings = Qnil;
|
189
|
+
aerospike* ptr;
|
190
|
+
as_error err;
|
191
|
+
as_policy_info policy;
|
192
|
+
|
193
|
+
uint32_t timeout = 1000;
|
194
|
+
|
195
|
+
if (argc > 3 || argc < 1) { // there should only be 1, 2 or 3 argument
|
196
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..3)", argc);
|
197
|
+
}
|
198
|
+
|
199
|
+
if (argc == 3) {
|
200
|
+
Check_Type(vArgs[1], T_FIXNUM);
|
201
|
+
timeout = FIX2ULONG(vArgs[1]);
|
202
|
+
vSettings = vArgs[2];
|
203
|
+
} else if (argc == 2) {
|
204
|
+
switch(TYPE(vArgs[1])) {
|
205
|
+
case T_NIL:
|
206
|
+
break;
|
207
|
+
case T_FIXNUM:
|
208
|
+
timeout = FIX2ULONG(vArgs[1]);
|
209
|
+
break;
|
210
|
+
case T_HASH:
|
211
|
+
vSettings = vArgs[1];
|
212
|
+
break;
|
213
|
+
default:
|
214
|
+
rb_raise(rb_eTypeError, "wrong argument type (expected Hash or Fixnum)");
|
215
|
+
}
|
216
|
+
}
|
217
|
+
|
218
|
+
as_policy_info_init(&policy);
|
219
|
+
if(TYPE(vSettings) != T_NIL) {
|
220
|
+
SET_INFO_POLICY(policy, vSettings);
|
221
|
+
}
|
222
|
+
|
223
|
+
vClient = rb_iv_get(vSelf, "@client");
|
224
|
+
Data_Get_Struct(vClient, aerospike, ptr);
|
225
|
+
|
226
|
+
if (aerospike_udf_put_wait(ptr, &err, &policy, StringValueCStr(vArgs[0]), timeout) != AEROSPIKE_OK) {
|
227
|
+
raise_aerospike_exception(err.code, err.message);
|
228
|
+
}
|
229
|
+
|
230
|
+
return Qtrue;
|
231
|
+
}
|
232
|
+
|
233
|
+
void define_udf()
|
234
|
+
{
|
235
|
+
UdfClass = rb_define_class_under(AerospikeNativeClass, "Udf", rb_cObject);
|
236
|
+
rb_define_method(UdfClass, "initialize", udf_initialize, 1);
|
237
|
+
rb_define_method(UdfClass, "put", udf_put, -1);
|
238
|
+
rb_define_method(UdfClass, "remove", udf_remove, -1);
|
239
|
+
rb_define_method(UdfClass, "list", udf_list, -1);
|
240
|
+
rb_define_method(UdfClass, "get", udf_get, -1);
|
241
|
+
rb_define_method(UdfClass, "wait", udf_wait, -1);
|
242
|
+
|
243
|
+
rb_define_attr(UdfClass, "client", 1, 0);
|
244
|
+
rb_define_const(UdfClass, "LUA", INT2FIX(AS_UDF_TYPE_LUA));
|
245
|
+
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aerospike_native
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vladimir Ziablitskii
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-08-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: msgpack
|
@@ -97,10 +97,14 @@ files:
|
|
97
97
|
- aerospike_native.gemspec
|
98
98
|
- examples/batch.rb
|
99
99
|
- examples/common/common.rb
|
100
|
+
- examples/lua/.keep
|
101
|
+
- examples/lua/test_udf.lua
|
100
102
|
- examples/operate.rb
|
101
103
|
- examples/put_get_remove.rb
|
102
104
|
- examples/query_and_index.rb
|
105
|
+
- examples/query_udf.rb
|
103
106
|
- examples/scan.rb
|
107
|
+
- examples/scan_udf.rb
|
104
108
|
- ext/aerospike_native/aerospike_native.c
|
105
109
|
- ext/aerospike_native/aerospike_native.h
|
106
110
|
- ext/aerospike_native/batch.c
|
@@ -128,6 +132,8 @@ files:
|
|
128
132
|
- ext/aerospike_native/record.h
|
129
133
|
- ext/aerospike_native/scan.c
|
130
134
|
- ext/aerospike_native/scan.h
|
135
|
+
- ext/aerospike_native/udf.c
|
136
|
+
- ext/aerospike_native/udf.h
|
131
137
|
- lib/aerospike_native.rb
|
132
138
|
- lib/aerospike_native/version.rb
|
133
139
|
homepage: https://github.com/rainlabs/aerospike_native
|
@@ -156,4 +162,3 @@ signing_key:
|
|
156
162
|
specification_version: 4
|
157
163
|
summary: Aerospike native client
|
158
164
|
test_files: []
|
159
|
-
has_rdoc:
|