aerospike_native 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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:
|