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 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: