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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c1d71f1edfd8c586f26365cc3d4164e82bd3edf7
4
- data.tar.gz: c3a672ce0944477a43dae020b55e5656b438e933
3
+ metadata.gz: a5ac04c52b55cb401bde39b9679e8fa73501e212
4
+ data.tar.gz: 5e1123f5afc9602e456c8b3f974f850039f281e5
5
5
  SHA512:
6
- metadata.gz: 2f47a757e7d62cc85edec99c5912b581892d286b9fea1b630d4bd95f55e3d7d34159877304aa9d858995e176e23b23fe463bb2d401ebd79ba71ca1dd69af9430
7
- data.tar.gz: ded5c49c747f022322ddd58c3a4cdf257f0a01195e31315cd7759d87fb7c5cfd16da4b1fae529d0c6b84043d86cfb3b5852bbffa7c34706704ce54e2296ed0af
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 select support)
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
- In path `examples`
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
- require 'aerospike_native/version'
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 |s|
24
- s.summary = 'Aerospike ruby client with c extension'
25
- s.authors = %w[zyablitskiy@gmail.com]
26
-
27
- # this tells RubyGems to build an extension upon install
28
-
29
- s.extensions = %w[ext/aerospike_native/extconf.rb]
30
-
31
- # naturally you must include the extension source in the gem
32
-
33
- s.files = `git ls-files`.split($/)
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
@@ -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([{'host' => '127.0.0.1', 'port' => 3010}]) end
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
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 > 1) { // there should only be 0 or 1 arguments
61
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..1)", argc);
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(ary)) {
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
- record = as_record_fromval(value);
156
-
157
- if (record != NULL) {
158
- vRecord = rb_record_from_c(record, NULL);
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
  }
@@ -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 scan_background(VALUE vSelf, VALUE vValue)
87
+ VALUE scan_apply(int argc, VALUE* vArgs, VALUE vSelf)
94
88
  {
95
- rb_iv_set(vSelf, "@background", vValue);
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, vBackground;
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], T_FIXNUM);
220
- scan_id = FIX2ULONG(vArgs[1]);
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
- // rb_define_method(ScanClass, "set_background", scan_background, 1);
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(ScanClass, "background", 1, 0);
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
+ }
@@ -0,0 +1,10 @@
1
+ #ifndef UDF_H
2
+ #define UDF_H
3
+
4
+ #include "aerospike_native.h"
5
+
6
+ RUBY_EXTERN VALUE UdfClass;
7
+ void define_udf();
8
+
9
+ #endif // UDF_H
10
+
@@ -1,3 +1,3 @@
1
1
  module AerospikeNative
2
- VERSION = "0.4.0"
2
+ VERSION = "0.5.0"
3
3
  end
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.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-07-25 00:00:00.000000000 Z
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: