couchbase 1.1.5-x86-mingw32 → 1.2.0.beta-x86-mingw32
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.
- data/.gitignore +2 -1
- data/.travis.yml +12 -1
- data/HISTORY.markdown +112 -1
- data/README.markdown +149 -6
- data/couchbase.gemspec +5 -1
- data/ext/couchbase_ext/.gitignore +4 -0
- data/ext/couchbase_ext/arguments.c +973 -0
- data/ext/couchbase_ext/arithmetic.c +322 -0
- data/ext/couchbase_ext/bucket.c +1092 -0
- data/ext/couchbase_ext/couchbase_ext.c +618 -3247
- data/ext/couchbase_ext/couchbase_ext.h +519 -0
- data/ext/couchbase_ext/delete.c +167 -0
- data/ext/couchbase_ext/extconf.rb +24 -5
- data/ext/couchbase_ext/get.c +301 -0
- data/ext/couchbase_ext/gethrtime.c +124 -0
- data/ext/couchbase_ext/http.c +402 -0
- data/ext/couchbase_ext/observe.c +174 -0
- data/ext/couchbase_ext/result.c +126 -0
- data/ext/couchbase_ext/stats.c +169 -0
- data/ext/couchbase_ext/store.c +522 -0
- data/ext/couchbase_ext/timer.c +192 -0
- data/ext/couchbase_ext/touch.c +190 -0
- data/ext/couchbase_ext/unlock.c +180 -0
- data/ext/couchbase_ext/utils.c +471 -0
- data/ext/couchbase_ext/version.c +147 -0
- data/lib/action_dispatch/middleware/session/couchbase_store.rb +38 -0
- data/lib/active_support/cache/couchbase_store.rb +356 -0
- data/lib/couchbase.rb +24 -3
- data/lib/couchbase/bucket.rb +372 -9
- data/lib/couchbase/result.rb +26 -0
- data/lib/couchbase/utils.rb +59 -0
- data/lib/couchbase/version.rb +1 -1
- data/lib/couchbase/view.rb +305 -0
- data/lib/couchbase/view_row.rb +230 -0
- data/lib/ext/multi_json_fix.rb +47 -0
- data/lib/rack/session/couchbase.rb +104 -0
- data/tasks/compile.rake +5 -14
- data/test/setup.rb +6 -2
- data/test/test_arithmetic.rb +32 -2
- data/test/test_async.rb +18 -4
- data/test/test_bucket.rb +11 -1
- data/test/test_cas.rb +13 -3
- data/test/test_couchbase_rails_cache_store.rb +294 -0
- data/test/test_delete.rb +60 -3
- data/test/test_format.rb +28 -17
- data/test/test_get.rb +91 -14
- data/test/test_store.rb +31 -1
- data/test/{test_flush.rb → test_timer.rb} +11 -18
- data/test/test_touch.rb +33 -5
- data/test/test_unlock.rb +120 -0
- data/test/test_utils.rb +26 -0
- metadata +102 -12
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -1,6 +1,13 @@
|
|
1
1
|
before_install:
|
2
|
+
- sudo rm -rf /etc/apt/sources.list.d/couchdb-ppa-source.list
|
3
|
+
- sudo rm -rf /etc/apt/sources.list.d/mongodb.list
|
4
|
+
- sudo rm -rf /etc/apt/sources.list.d/datastax-source.list
|
5
|
+
- sudo rm -rf /etc/apt/sources.list.d/rabbitmq-source.list
|
6
|
+
- sudo rm -rf /etc/apt/sources.list.d/mapopa-source.list
|
7
|
+
- sudo rm -rf /etc/apt/sources.list.d/webupd8team-java-ppa-source.list
|
8
|
+
- sudo rm -rf /etc/apt/sources.list.d/maven3-ppa-source.list
|
2
9
|
- wget -O- http://packages.couchbase.com/ubuntu/couchbase.key | sudo apt-key add -
|
3
|
-
- echo deb http://packages.couchbase.com/ubuntu
|
10
|
+
- echo deb http://packages.couchbase.com/snapshot/ubuntu oneiric oneiric/main | sudo tee /etc/apt/sources.list.d/couchbase.list
|
4
11
|
- sudo apt-get update
|
5
12
|
- sudo apt-get -y install libevent-dev libvbucket-dev libcouchbase-dev
|
6
13
|
|
@@ -9,3 +16,7 @@ rvm:
|
|
9
16
|
- 1.9.2
|
10
17
|
- 1.9.3
|
11
18
|
- ree
|
19
|
+
|
20
|
+
notifications:
|
21
|
+
email:
|
22
|
+
- sdk_dev@couchbase.com
|
data/HISTORY.markdown
CHANGED
@@ -1,6 +1,117 @@
|
|
1
|
-
## 1.
|
1
|
+
## 1.2.0.beta / 2012-09-18
|
2
2
|
|
3
|
+
* RCBC-70 return binary keys using Encoding.external value (thanks to Alex Leverington)
|
4
|
+
* Create new key object only if it is necessary
|
5
|
+
* Switch to rbenv because RVM doesn't work with tclsh
|
6
|
+
* [backport] RCBC-37 Bootstrapping using multiple nodes
|
7
|
+
* React on HTTP level errors in view request
|
8
|
+
* Fix typo: check for MultiJson.decode
|
9
|
+
* Use unified HTTP function from the latest libcouchbase
|
10
|
+
* Expose HTTP headers
|
11
|
+
* Update views to meet latest server changes
|
12
|
+
* Add support for spatial views
|
13
|
+
* Use updated libcouchbase_cancel_http_request()
|
14
|
+
* Workaround query issue on group=false&reduce=false
|
15
|
+
* Update windows build
|
16
|
+
* Bump version 1.1.4
|
17
|
+
* Refactor the C extension
|
18
|
+
* Fix CAS conversion for Bucket#delete method for 32-bit systems
|
19
|
+
* RCBC-28 Implement Bucket#unlock
|
20
|
+
* CCBC-98 Expose client temporary failure error
|
21
|
+
* Fix warnings in doc generator and specify return values
|
22
|
+
* Fix -Wreturn-type warning
|
23
|
+
* Add attribute reader for Error::Base status code
|
24
|
+
* Unset RUBYOPT to avoid issues with bundler
|
25
|
+
* Ignore shared object on macos
|
26
|
+
* RCBC-79 Use RESTful flush
|
27
|
+
* Fix build under bundler on MacOS
|
3
28
|
* RCBC-81 Protect against NoMethodError
|
29
|
+
* Fixup MAKEFILE_CONFIG which is copy of the CONFIG
|
30
|
+
* RCBC-81 Protect against NoMethodError
|
31
|
+
* Update windows build
|
32
|
+
|
33
|
+
## 1.2.0.dp6 / 2012-07-28
|
34
|
+
|
35
|
+
* Inherit StandardError instead RuntimeError for errors
|
36
|
+
* Use renamed functions for view requests
|
37
|
+
* Depend on yard-xml plugin to dump docs into single XML
|
38
|
+
* No need to check for NULL before deallocating memory
|
39
|
+
* RCBC-37 Bootstrapping using multiple nodes
|
40
|
+
* More docs and examples on views (fixes RCBC-43)
|
41
|
+
* RCBC-40 Fix Bucket#cas operation behaviour in async mode
|
42
|
+
* RCBC-39 Allow to specify delta for incr/decr in options
|
43
|
+
* Update README
|
44
|
+
* Apply timeout value before connection
|
45
|
+
* Clarify connection exceptions
|
46
|
+
* Remove seqno kludge
|
47
|
+
* rb_hash_delete() function could incorrectly detect block presence
|
48
|
+
* Add example with in-URL credentials
|
49
|
+
* RCBC-57 Expose timers API from libcouchbase
|
50
|
+
* RCBC-50 Allow to read keys from replica
|
51
|
+
* RCBC-6 Implement OBSERVE command
|
52
|
+
* Expose number of replicas to the user
|
53
|
+
* Notify about observe batch finish in async mode
|
54
|
+
* Separate memory errors for client and server
|
55
|
+
* Prefix error message from views with "SERVER: "
|
56
|
+
* Remove timeout hack
|
57
|
+
* RCBC-49 Bucket#observe_and_wait primitive
|
58
|
+
* RCBC-47 Allow to skip username for protected buckets
|
59
|
+
* Use allocators instead of singleton methods
|
60
|
+
* Check RDATA()->dfree to ensure object type
|
61
|
+
* Fix observe_and_wait in async mode
|
62
|
+
* Fill 'operation' in observe_and_wait Result object
|
63
|
+
* Fix extraction Hash with keys in observe_and_wait
|
64
|
+
* RCBC-49 :observe option for storage functions
|
65
|
+
* Fix timeout test
|
66
|
+
* Mention couchbase.com in install errors
|
67
|
+
* Make Bucket#observe_and_wait more 1.8.7 friendly
|
68
|
+
|
69
|
+
## 1.2.0.dp5 / 2012-06-15
|
70
|
+
|
71
|
+
* Allow to force assembling result Hash for multi-get
|
72
|
+
* Fix documentation for :ttl option in Bucket#cas
|
73
|
+
* Implement key prefix (simple namespacing)
|
74
|
+
* Implement cache store adapter for Rails
|
75
|
+
* Integrate with Rack and Rails session store
|
76
|
+
|
77
|
+
## 1.2.0.dp4 / 2012-06-07
|
78
|
+
|
79
|
+
* RCBC-36 Fix segfault
|
80
|
+
* Comment out unpredictable test
|
81
|
+
* Update replace documentation: it accepts :cas option
|
82
|
+
|
83
|
+
## 1.2.0.dp3 / 2012-06-06
|
84
|
+
|
85
|
+
* Fix for multi_json < 1.3.3
|
86
|
+
* Break out from event loop for non-chunked responses (fix creating
|
87
|
+
design create)
|
88
|
+
|
89
|
+
## 1.2.0.dp2 / 2012-06-05
|
90
|
+
|
91
|
+
* RCBC-31 Make Bucket#get more consistent
|
92
|
+
* Use monotonic high resolution clock
|
93
|
+
* Implement threshold for outgoing commands
|
94
|
+
* Allow to stop event loop from ruby
|
95
|
+
* RCBC-35 Fix the params escaping
|
96
|
+
* RCBC-34 Use multi_json gem
|
97
|
+
* Allow to block and wait for part of the requests
|
98
|
+
* Fix view iterator. It doesn't lock event loop anymore
|
99
|
+
* Specify HTTP method when body is set for View request
|
100
|
+
* Define views only if "views" key presented
|
101
|
+
* Use plain structs instead of typedefs
|
102
|
+
* Use debugger gem for 1.9.x rubies
|
103
|
+
* Use latest stable build of libcouchbase for travis-ci
|
104
|
+
* Require yajl as development dependency
|
105
|
+
* Implement get with lock operation
|
106
|
+
* Update docs
|
107
|
+
|
108
|
+
## 1.2.0.dp / 2012-04-06
|
109
|
+
|
110
|
+
* Properly handle hashes as Couchbase.connection_options
|
111
|
+
* Implement views
|
112
|
+
* Use verbose mode by default throwing exceptions on NOT_FOUND errors.
|
113
|
+
This means that quiet attribute is false now on new connections.
|
114
|
+
* Doc fixes
|
4
115
|
|
5
116
|
## 1.1.4 / 2012-08-30
|
6
117
|
|
data/README.markdown
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Couchbase Ruby Client [](http://travis-ci.org/couchbase/couchbase-ruby-client)
|
2
2
|
|
3
3
|
This is the official client library for use with Couchbase Server.
|
4
4
|
|
@@ -18,14 +18,15 @@ libcouchbase doesn't take much effort.
|
|
18
18
|
|
19
19
|
$ brew install libcouchbase
|
20
20
|
|
21
|
-
|
21
|
+
The official homebrew repository contains only stable versions of
|
22
|
+
libvbucket and libcouchbase, if you need preview, take a look at
|
23
|
+
Couchbase's fork: https://github.com/couchbase/homebrew
|
22
24
|
|
23
|
-
$ brew install https://github.com/
|
24
|
-
$ brew install https://github.com/avsej/homebrew/raw/libcouchbase/Library/Formula/libcouchbase.rb
|
25
|
+
$ brew install https://raw.github.com/couchbase/homebrew/preview/Library/Formula/libcouchbase.rb
|
25
26
|
|
26
27
|
### Debian (Ubuntu)
|
27
28
|
|
28
|
-
Add the appropriate line to
|
29
|
+
Add the appropriate line to `/etc/apt/sources.list.d/couchbase.list` for
|
29
30
|
your OS release:
|
30
31
|
|
31
32
|
# Ubuntu 11.10 Oneiric Ocelot (Debian unstable)
|
@@ -42,6 +43,15 @@ Then install them
|
|
42
43
|
|
43
44
|
$ sudo apt-get update && sudo apt-get install libcouchbase-dev
|
44
45
|
|
46
|
+
Again, if you need preview versions, just use another repositories in
|
47
|
+
your `couchbase.list`
|
48
|
+
|
49
|
+
# Ubuntu 11.10 Oneiric Ocelot (Debian unstable)
|
50
|
+
deb http://packages.couchbase.com/preview/ubuntu oneiric oneiric/main
|
51
|
+
|
52
|
+
# Ubuntu 10.04 Lucid Lynx (Debian stable or testing)
|
53
|
+
deb http://packages.couchbase.com/preview/ubuntu lucid lucid/main
|
54
|
+
|
45
55
|
### Centos (Redhat and rpm-based systems)
|
46
56
|
|
47
57
|
Add these lines to /etc/yum.repos.d/couchbase.repo using the correct architecture
|
@@ -52,12 +62,23 @@ Add these lines to /etc/yum.repos.d/couchbase.repo using the correct architectur
|
|
52
62
|
|
53
63
|
[couchbase]
|
54
64
|
name = Couchbase package repository
|
55
|
-
baseurl = http
|
65
|
+
baseurl = http://packages.couchbase.com/rpm/5.5/x86_64
|
56
66
|
|
57
67
|
Then to install libcouchbase itself, run:
|
58
68
|
|
59
69
|
$ sudo yum update && sudo yum install libcouchbase-devel
|
60
70
|
|
71
|
+
We have preview repositories for RPMs too, use them if you need to try
|
72
|
+
fresh version of couchbase gem:
|
73
|
+
|
74
|
+
[couchbase]
|
75
|
+
name = Couchbase package repository
|
76
|
+
baseurl = http://packages.couchbase.com/preview/rpm/5.5/i386
|
77
|
+
|
78
|
+
[couchbase]
|
79
|
+
name = Couchbase package repository
|
80
|
+
baseurl = http://packages.couchbase.com/preview/rpm/5.5/x86_64
|
81
|
+
|
61
82
|
### Windows
|
62
83
|
|
63
84
|
There no additional dependencies for Windows systems. The gem carry
|
@@ -94,6 +115,14 @@ This is equivalent to following forms:
|
|
94
115
|
|
95
116
|
The hash parameters take precedence on string URL.
|
96
117
|
|
118
|
+
If you worry about state of your nodes or not sure what node is alive,
|
119
|
+
you can pass the list of nodes and the library will iterate over it
|
120
|
+
until finds the working one. From that moment it won't use **your**
|
121
|
+
list, because node list from cluster config is more actual.
|
122
|
+
|
123
|
+
c = Couchbase.connect(:bucket => "mybucket",
|
124
|
+
:node_list => ['example.com:8091', example.net'])
|
125
|
+
|
97
126
|
There is also handy method `Couchbase.bucket` which uses thread local
|
98
127
|
storage to keep the reference to default connection. You can set the
|
99
128
|
connection options via `Couchbase.connection_options`:
|
@@ -371,6 +400,120 @@ the key and stats as key-value pairs.
|
|
371
400
|
# ...
|
372
401
|
}
|
373
402
|
|
403
|
+
### Timers
|
404
|
+
|
405
|
+
It is possible to create timers to implement general purpose timeouts.
|
406
|
+
Note that timers are using microseconds for time intervals. For example,
|
407
|
+
following examples increment the keys value five times with 0.5 second
|
408
|
+
interval:
|
409
|
+
|
410
|
+
c.set("foo", 100)
|
411
|
+
n = 1
|
412
|
+
c.run do
|
413
|
+
c.create_periodic_timer(500000) do |tm|
|
414
|
+
c.incr("foo") do
|
415
|
+
if n == 5
|
416
|
+
tm.cancel
|
417
|
+
else
|
418
|
+
n += 1
|
419
|
+
end
|
420
|
+
end
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
### Views (Map/Reduce queries)
|
425
|
+
|
426
|
+
If you store structured data, they will be treated as documents and you
|
427
|
+
can handle them in map/reduce function from Couchbase Views. For example,
|
428
|
+
store a couple of posts using memcached API:
|
429
|
+
|
430
|
+
c['biking'] = {:title => 'Biking',
|
431
|
+
:body => 'My biggest hobby is mountainbiking. The other day...',
|
432
|
+
:date => '2009/01/30 18:04:11'}
|
433
|
+
c['bought-a-cat'] = {:title => 'Bought a Cat',
|
434
|
+
:body => 'I went to the the pet store earlier and brought home a little kitty...',
|
435
|
+
:date => '2009/01/30 20:04:11'}
|
436
|
+
c['hello-world'] = {:title => 'Hello World',
|
437
|
+
:body => 'Well hello and welcome to my new blog...',
|
438
|
+
:date => '2009/01/15 15:52:20'}
|
439
|
+
c.all_docs.count #=> 3
|
440
|
+
|
441
|
+
Now let's create design doc with sample view and save it in file
|
442
|
+
'blog.json':
|
443
|
+
|
444
|
+
{
|
445
|
+
"_id": "_design/blog",
|
446
|
+
"language": "javascript",
|
447
|
+
"views": {
|
448
|
+
"recent_posts": {
|
449
|
+
"map": "function(doc){if(doc.date && doc.title){emit(doc.date, doc.title);}}"
|
450
|
+
}
|
451
|
+
}
|
452
|
+
}
|
453
|
+
|
454
|
+
This design document could be loaded into the database like this (also you can
|
455
|
+
pass the ruby Hash or String with JSON encoded document):
|
456
|
+
|
457
|
+
c.save_design_doc(File.open('blog.json'))
|
458
|
+
|
459
|
+
To execute view you need to fetch it from design document `_design/blog`:
|
460
|
+
|
461
|
+
blog = c.design_docs['blog']
|
462
|
+
blog.views #=> ["recent_posts"]
|
463
|
+
blog.recent_posts #=> [#<Couchbase::ViewRow:9855800 @id="hello-world" @key="2009/01/15 15:52:20" @value="Hello World" @doc=nil @meta={} @views=[]>, ...]
|
464
|
+
|
465
|
+
Gem uses streaming parser to access view results so you can iterate them
|
466
|
+
easily and if your code won't keep links to the documents GC might free
|
467
|
+
them as soon as it decide they are unreachable, because parser doesn't
|
468
|
+
store global JSON tree.
|
469
|
+
|
470
|
+
blog.recent_posts.each do |doc|
|
471
|
+
# do something
|
472
|
+
# with doc object
|
473
|
+
doc.key # gives the key argument of the emit()
|
474
|
+
doc.value # gives the value argument of the emit()
|
475
|
+
end
|
476
|
+
|
477
|
+
Load with documents
|
478
|
+
|
479
|
+
blog.recent_posts(:include_docs => true).each do |doc|
|
480
|
+
doc.doc # gives the document which emitted the item
|
481
|
+
doc['date'] # gives the argument of the underlying document
|
482
|
+
end
|
483
|
+
|
484
|
+
|
485
|
+
You can also use Enumerator to iterate view results
|
486
|
+
|
487
|
+
require 'date'
|
488
|
+
posts_by_date = Hash.new{|h,k| h[k] = []}
|
489
|
+
enum = c.all_docs(:include_docs => true).each # request hasn't issued yet
|
490
|
+
enum.inject(posts_by_date) do |acc, doc|
|
491
|
+
acc[date] = Date.strptime(doc['date'], '%Y/%m/%d')
|
492
|
+
acc
|
493
|
+
end
|
494
|
+
|
495
|
+
The Couchbase server could generate errors during view execution with
|
496
|
+
`200 OK` and partial results. By default the library raises exception as
|
497
|
+
soon as errors detected in the result stream, but you can define the
|
498
|
+
callback `on_error` to intercept these errors and do something more
|
499
|
+
useful.
|
500
|
+
|
501
|
+
view = blog.recent_posts(:include_docs => true)
|
502
|
+
logger = Logger.new(STDOUT)
|
503
|
+
|
504
|
+
view.on_error do |from, reason|
|
505
|
+
logger.warn("#{view.inspect} received the error '#{reason}' from #{from}")
|
506
|
+
end
|
507
|
+
|
508
|
+
posts = view.each do |doc|
|
509
|
+
# do something
|
510
|
+
# with doc object
|
511
|
+
end
|
512
|
+
|
513
|
+
Note that errors object in view results usually goes *after* the rows,
|
514
|
+
so you will likely receive a number of view results successfully before
|
515
|
+
the error is detected.
|
516
|
+
|
374
517
|
[1]: http://couchbase.com/issues/browse/RCBC
|
375
518
|
[2]: http://freenode.net/irc_servers.shtml
|
376
519
|
[3]: http://www.couchbase.com/develop/c/current
|
data/couchbase.gemspec
CHANGED
@@ -35,13 +35,17 @@ Gem::Specification.new do |s|
|
|
35
35
|
s.extensions = `git ls-files -- ext/**/extconf.rb`.split("\n")
|
36
36
|
s.require_paths = ['lib']
|
37
37
|
|
38
|
-
s.add_runtime_dependency '
|
38
|
+
s.add_runtime_dependency 'yaji', '~> 0.3.2'
|
39
|
+
s.add_runtime_dependency 'multi_json', '~> 1.0'
|
39
40
|
|
40
41
|
s.add_development_dependency 'rake', '~> 0.8.7'
|
41
42
|
s.add_development_dependency 'minitest'
|
42
43
|
s.add_development_dependency 'rake-compiler', '>= 0.7.5'
|
43
44
|
s.add_development_dependency 'rdiscount'
|
44
45
|
s.add_development_dependency 'yard'
|
46
|
+
s.add_development_dependency 'yard-xml'
|
45
47
|
s.add_development_dependency 'mini_portile'
|
48
|
+
s.add_development_dependency 'yajl-ruby', '~> 1.1.0'
|
46
49
|
s.add_development_dependency RUBY_VERSION =~ /^1\.9/ ? 'debugger' : 'ruby-debug'
|
50
|
+
s.add_development_dependency 'active_support'
|
47
51
|
end
|
@@ -0,0 +1,973 @@
|
|
1
|
+
/* vim: ft=c et ts=8 sts=4 sw=4 cino=
|
2
|
+
*
|
3
|
+
* Copyright 2011, 2012 Couchbase, Inc.
|
4
|
+
*
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
* you may not use this file except in compliance with the License.
|
7
|
+
* You may obtain a copy of the License at
|
8
|
+
*
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
*
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
* See the License for the specific language governing permissions and
|
15
|
+
* limitations under the License.
|
16
|
+
*/
|
17
|
+
|
18
|
+
#include "couchbase_ext.h"
|
19
|
+
|
20
|
+
|
21
|
+
/* TOUCH */
|
22
|
+
|
23
|
+
static void
|
24
|
+
cb_params_touch_alloc(struct params_st *params, lcb_size_t size)
|
25
|
+
{
|
26
|
+
lcb_size_t ii;
|
27
|
+
|
28
|
+
params->cmd.touch.num = size;
|
29
|
+
params->cmd.touch.items = xcalloc(size, sizeof(lcb_touch_cmd_t));
|
30
|
+
if (params->cmd.touch.items == NULL) {
|
31
|
+
rb_raise(eClientNoMemoryError, "failed to allocate memory for arguments");
|
32
|
+
}
|
33
|
+
params->cmd.touch.ptr = xcalloc(size, sizeof(lcb_touch_cmd_t *));
|
34
|
+
if (params->cmd.touch.ptr == NULL) {
|
35
|
+
rb_raise(eClientNoMemoryError, "failed to allocate memory for arguments");
|
36
|
+
}
|
37
|
+
for (ii = 0; ii < size; ++ii) {
|
38
|
+
params->cmd.touch.ptr[ii] = params->cmd.touch.items + ii;
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
static void
|
43
|
+
cb_params_touch_init_item(struct params_st *params, lcb_size_t idx, VALUE key_obj, lcb_time_t exptime)
|
44
|
+
{
|
45
|
+
key_obj = unify_key(params->bucket, key_obj, 1);
|
46
|
+
params->cmd.touch.items[idx].v.v0.key = RSTRING_PTR(key_obj);
|
47
|
+
params->cmd.touch.items[idx].v.v0.nkey = RSTRING_LEN(key_obj);
|
48
|
+
params->cmd.touch.items[idx].v.v0.exptime = exptime;
|
49
|
+
params->npayload += RSTRING_LEN(key_obj) + sizeof(exptime);
|
50
|
+
}
|
51
|
+
|
52
|
+
static int
|
53
|
+
cb_params_touch_extract_keys_i(VALUE key, VALUE value, VALUE arg)
|
54
|
+
{
|
55
|
+
struct params_st *params = (struct params_st *)arg;
|
56
|
+
cb_params_touch_init_item(params, params->idx++, key, NUM2ULONG(value));
|
57
|
+
return ST_CONTINUE;
|
58
|
+
}
|
59
|
+
|
60
|
+
static void
|
61
|
+
cb_params_touch_parse_options(struct params_st *params, VALUE options)
|
62
|
+
{
|
63
|
+
VALUE tmp;
|
64
|
+
|
65
|
+
if (NIL_P(options)) {
|
66
|
+
return;
|
67
|
+
}
|
68
|
+
tmp = rb_hash_aref(options, sym_ttl);
|
69
|
+
if (tmp != Qnil) {
|
70
|
+
params->cmd.touch.ttl = NUM2ULONG(tmp);
|
71
|
+
}
|
72
|
+
if (RTEST(rb_funcall(options, id_has_key_p, 1, sym_quiet))) {
|
73
|
+
params->cmd.touch.quiet = RTEST(rb_hash_aref(options, sym_quiet));
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
static void
|
78
|
+
cb_params_touch_parse_arguments(struct params_st *params, int argc, VALUE argv)
|
79
|
+
{
|
80
|
+
lcb_size_t ii;
|
81
|
+
|
82
|
+
if (argc < 1) {
|
83
|
+
rb_raise(rb_eArgError, "must be at least one key");
|
84
|
+
}
|
85
|
+
if (argc == 1) {
|
86
|
+
VALUE keys = RARRAY_PTR(argv)[0];
|
87
|
+
switch(TYPE(keys)) {
|
88
|
+
case T_ARRAY:
|
89
|
+
/* array of keys as a first argument */
|
90
|
+
params->cmd.touch.array = 1;
|
91
|
+
cb_params_touch_alloc(params, RARRAY_LEN(keys));
|
92
|
+
for (ii = 0; ii < params->cmd.touch.num; ++ii) {
|
93
|
+
cb_params_touch_init_item(params, ii, RARRAY_PTR(keys)[ii], params->cmd.touch.ttl);
|
94
|
+
}
|
95
|
+
break;
|
96
|
+
case T_HASH:
|
97
|
+
/* key-ttl pairs */
|
98
|
+
cb_params_touch_alloc(params, RHASH_SIZE(keys));
|
99
|
+
rb_hash_foreach(keys, cb_params_touch_extract_keys_i,
|
100
|
+
(VALUE)params);
|
101
|
+
break;
|
102
|
+
default:
|
103
|
+
/* single key */
|
104
|
+
cb_params_touch_alloc(params, 1);
|
105
|
+
cb_params_touch_init_item(params, 0, keys, params->cmd.touch.ttl);
|
106
|
+
}
|
107
|
+
} else {
|
108
|
+
/* just list of arguments */
|
109
|
+
cb_params_touch_alloc(params, argc);
|
110
|
+
for (ii = 0; ii < params->cmd.touch.num; ++ii) {
|
111
|
+
cb_params_touch_init_item(params, ii, RARRAY_PTR(argv)[ii], params->cmd.touch.ttl);
|
112
|
+
}
|
113
|
+
}
|
114
|
+
}
|
115
|
+
|
116
|
+
|
117
|
+
/* REMOVE */
|
118
|
+
|
119
|
+
static void
|
120
|
+
cb_params_remove_alloc(struct params_st *params, lcb_size_t size)
|
121
|
+
{
|
122
|
+
lcb_size_t ii;
|
123
|
+
|
124
|
+
params->cmd.remove.num = size;
|
125
|
+
params->cmd.remove.items = xcalloc(size, sizeof(lcb_remove_cmd_t));
|
126
|
+
if (params->cmd.remove.items == NULL) {
|
127
|
+
rb_raise(eClientNoMemoryError, "failed to allocate memory for arguments");
|
128
|
+
}
|
129
|
+
params->cmd.remove.ptr = xcalloc(size, sizeof(lcb_remove_cmd_t *));
|
130
|
+
if (params->cmd.remove.ptr == NULL) {
|
131
|
+
rb_raise(eClientNoMemoryError, "failed to allocate memory for arguments");
|
132
|
+
}
|
133
|
+
for (ii = 0; ii < size; ++ii) {
|
134
|
+
params->cmd.remove.ptr[ii] = params->cmd.remove.items + ii;
|
135
|
+
}
|
136
|
+
}
|
137
|
+
|
138
|
+
static void
|
139
|
+
cb_params_remove_init_item(struct params_st *params, lcb_size_t idx, VALUE key_obj, lcb_cas_t cas)
|
140
|
+
{
|
141
|
+
key_obj = unify_key(params->bucket, key_obj, 1);
|
142
|
+
params->cmd.remove.items[idx].v.v0.key = RSTRING_PTR(key_obj);
|
143
|
+
params->cmd.remove.items[idx].v.v0.nkey = RSTRING_LEN(key_obj);
|
144
|
+
params->cmd.remove.items[idx].v.v0.cas = cas;
|
145
|
+
params->npayload += RSTRING_LEN(key_obj);
|
146
|
+
}
|
147
|
+
|
148
|
+
static int
|
149
|
+
cb_params_remove_extract_keys_i(VALUE key, VALUE value, VALUE arg)
|
150
|
+
{
|
151
|
+
struct params_st *params = (struct params_st *)arg;
|
152
|
+
cb_params_remove_init_item(params, params->idx++, key, NUM2ULL(value));
|
153
|
+
return ST_CONTINUE;
|
154
|
+
}
|
155
|
+
|
156
|
+
static void
|
157
|
+
cb_params_remove_parse_options(struct params_st *params, VALUE options)
|
158
|
+
{
|
159
|
+
VALUE tmp;
|
160
|
+
|
161
|
+
if (NIL_P(options)) {
|
162
|
+
return;
|
163
|
+
}
|
164
|
+
if (RTEST(rb_funcall(options, id_has_key_p, 1, sym_quiet))) {
|
165
|
+
params->cmd.remove.quiet = RTEST(rb_hash_aref(options, sym_quiet));
|
166
|
+
}
|
167
|
+
tmp = rb_hash_aref(options, sym_cas);
|
168
|
+
if (tmp != Qnil) {
|
169
|
+
params->cmd.remove.cas = NUM2ULL(tmp);
|
170
|
+
}
|
171
|
+
}
|
172
|
+
|
173
|
+
static void
|
174
|
+
cb_params_remove_parse_arguments(struct params_st *params, int argc, VALUE argv)
|
175
|
+
{
|
176
|
+
lcb_size_t ii;
|
177
|
+
|
178
|
+
if (argc < 1) {
|
179
|
+
rb_raise(rb_eArgError, "must be at least one key");
|
180
|
+
}
|
181
|
+
if (argc == 1) {
|
182
|
+
VALUE keys = RARRAY_PTR(argv)[0];
|
183
|
+
switch(TYPE(keys)) {
|
184
|
+
case T_ARRAY:
|
185
|
+
/* array of keys as a first argument */
|
186
|
+
params->cmd.remove.array = 1;
|
187
|
+
cb_params_remove_alloc(params, RARRAY_LEN(keys));
|
188
|
+
for (ii = 0; ii < params->cmd.remove.num; ++ii) {
|
189
|
+
cb_params_remove_init_item(params, ii, RARRAY_PTR(keys)[ii], params->cmd.remove.cas);
|
190
|
+
}
|
191
|
+
break;
|
192
|
+
case T_HASH:
|
193
|
+
/* key-cas pairs */
|
194
|
+
cb_params_remove_alloc(params, RHASH_SIZE(keys));
|
195
|
+
rb_hash_foreach(keys, cb_params_remove_extract_keys_i,
|
196
|
+
(VALUE)params);
|
197
|
+
break;
|
198
|
+
default:
|
199
|
+
/* single key */
|
200
|
+
cb_params_remove_alloc(params, 1);
|
201
|
+
cb_params_remove_init_item(params, 0, keys, params->cmd.remove.cas);
|
202
|
+
}
|
203
|
+
} else {
|
204
|
+
/* just list of arguments */
|
205
|
+
cb_params_remove_alloc(params, argc);
|
206
|
+
for (ii = 0; ii < params->cmd.remove.num; ++ii) {
|
207
|
+
cb_params_remove_init_item(params, ii, RARRAY_PTR(argv)[ii], params->cmd.remove.cas);
|
208
|
+
}
|
209
|
+
}
|
210
|
+
}
|
211
|
+
|
212
|
+
|
213
|
+
/* STORE */
|
214
|
+
static void
|
215
|
+
cb_params_store_alloc(struct params_st *params, lcb_size_t size)
|
216
|
+
{
|
217
|
+
lcb_size_t ii;
|
218
|
+
|
219
|
+
params->cmd.store.num = size;
|
220
|
+
params->cmd.store.items = xcalloc(size, sizeof(lcb_store_cmd_t));
|
221
|
+
if (params->cmd.store.items == NULL) {
|
222
|
+
rb_raise(eClientNoMemoryError, "failed to allocate memory for arguments");
|
223
|
+
}
|
224
|
+
params->cmd.store.ptr = xcalloc(size, sizeof(lcb_store_cmd_t *));
|
225
|
+
if (params->cmd.store.ptr == NULL) {
|
226
|
+
rb_raise(eClientNoMemoryError, "failed to allocate memory for arguments");
|
227
|
+
}
|
228
|
+
for (ii = 0; ii < size; ++ii) {
|
229
|
+
params->cmd.store.ptr[ii] = params->cmd.store.items + ii;
|
230
|
+
}
|
231
|
+
}
|
232
|
+
|
233
|
+
static void
|
234
|
+
cb_params_store_init_item(struct params_st *params, lcb_size_t idx,
|
235
|
+
VALUE key_obj, VALUE value_obj, lcb_uint32_t flags, lcb_cas_t cas,
|
236
|
+
lcb_time_t exptime)
|
237
|
+
{
|
238
|
+
key_obj = unify_key(params->bucket, key_obj, 1);
|
239
|
+
value_obj = encode_value(value_obj, params->cmd.store.flags);
|
240
|
+
if (value_obj == Qundef) {
|
241
|
+
rb_raise(eValueFormatError, "unable to convert value for key '%s'", RSTRING_PTR(key_obj));
|
242
|
+
}
|
243
|
+
params->cmd.store.items[idx].v.v0.datatype = params->cmd.store.datatype;
|
244
|
+
params->cmd.store.items[idx].v.v0.operation = params->cmd.store.operation;
|
245
|
+
params->cmd.store.items[idx].v.v0.key = RSTRING_PTR(key_obj);
|
246
|
+
params->cmd.store.items[idx].v.v0.nkey = RSTRING_LEN(key_obj);
|
247
|
+
params->cmd.store.items[idx].v.v0.bytes = RSTRING_PTR(value_obj);
|
248
|
+
params->cmd.store.items[idx].v.v0.nbytes = RSTRING_LEN(value_obj);
|
249
|
+
params->cmd.store.items[idx].v.v0.flags = flags;
|
250
|
+
params->cmd.store.items[idx].v.v0.cas = cas;
|
251
|
+
params->cmd.store.items[idx].v.v0.exptime = exptime;
|
252
|
+
params->npayload += RSTRING_LEN(key_obj) + RSTRING_LEN(value_obj) + sizeof(flags) + sizeof(exptime);
|
253
|
+
}
|
254
|
+
|
255
|
+
static int
|
256
|
+
cb_params_store_extract_keys_i(VALUE key, VALUE value, VALUE arg)
|
257
|
+
{
|
258
|
+
struct params_st *params = (struct params_st *)arg;
|
259
|
+
cb_params_store_init_item(params, params->idx++, key, value,
|
260
|
+
params->cmd.store.flags, 0, params->cmd.store.ttl);
|
261
|
+
return ST_CONTINUE;
|
262
|
+
}
|
263
|
+
|
264
|
+
static void
|
265
|
+
cb_params_store_parse_options(struct params_st *params, VALUE options)
|
266
|
+
{
|
267
|
+
VALUE tmp;
|
268
|
+
|
269
|
+
if (NIL_P(options)) {
|
270
|
+
return;
|
271
|
+
}
|
272
|
+
tmp = rb_hash_aref(options, sym_flags);
|
273
|
+
if (tmp != Qnil) {
|
274
|
+
params->cmd.store.flags = (lcb_uint32_t)NUM2ULONG(tmp);
|
275
|
+
}
|
276
|
+
tmp = rb_hash_aref(options, sym_format);
|
277
|
+
if (tmp != Qnil) { /* rewrite format bits */
|
278
|
+
params->cmd.store.flags = flags_set_format(params->cmd.store.flags, tmp);
|
279
|
+
}
|
280
|
+
tmp = rb_hash_aref(options, sym_ttl);
|
281
|
+
if (tmp != Qnil) {
|
282
|
+
params->cmd.store.ttl = NUM2ULONG(tmp);
|
283
|
+
}
|
284
|
+
tmp = rb_hash_aref(options, sym_cas);
|
285
|
+
if (tmp != Qnil) {
|
286
|
+
params->cmd.store.cas = NUM2ULL(tmp);
|
287
|
+
}
|
288
|
+
tmp = rb_hash_aref(options, sym_observe);
|
289
|
+
if (tmp != Qnil) {
|
290
|
+
Check_Type(tmp, T_HASH);
|
291
|
+
rb_funcall(params->bucket->self, id_verify_observe_options, 1, tmp);
|
292
|
+
params->cmd.store.observe = tmp;
|
293
|
+
}
|
294
|
+
if (flags_get_format(params->cmd.store.flags) == sym_document) {
|
295
|
+
/* just amend datatype for now */
|
296
|
+
params->cmd.store.datatype = 0x01;
|
297
|
+
}
|
298
|
+
}
|
299
|
+
|
300
|
+
static void
|
301
|
+
cb_params_store_parse_arguments(struct params_st *params, int argc, VALUE argv)
|
302
|
+
{
|
303
|
+
VALUE keys;
|
304
|
+
|
305
|
+
if (argc < 1) {
|
306
|
+
rb_raise(rb_eArgError, "the key and value must be specified");
|
307
|
+
}
|
308
|
+
switch (argc) {
|
309
|
+
case 1:
|
310
|
+
keys = RARRAY_PTR(argv)[0];
|
311
|
+
switch(TYPE(keys)) {
|
312
|
+
case T_HASH:
|
313
|
+
/* key-value pairs */
|
314
|
+
cb_params_store_alloc(params, RHASH_SIZE(keys));
|
315
|
+
rb_hash_foreach(keys, cb_params_store_extract_keys_i,
|
316
|
+
(VALUE)params);
|
317
|
+
break;
|
318
|
+
default:
|
319
|
+
rb_raise(rb_eArgError, "there must be either Hash with key-value pairs"
|
320
|
+
" or two separate arguments: key and value");
|
321
|
+
}
|
322
|
+
break;
|
323
|
+
case 2:
|
324
|
+
/* just key and value */
|
325
|
+
cb_params_store_alloc(params, 1);
|
326
|
+
cb_params_store_init_item(params, 0, RARRAY_PTR(argv)[0], RARRAY_PTR(argv)[1],
|
327
|
+
params->cmd.store.flags, params->cmd.store.cas, params->cmd.store.ttl);
|
328
|
+
break;
|
329
|
+
default:
|
330
|
+
rb_raise(rb_eArgError, "too many arguments");
|
331
|
+
}
|
332
|
+
}
|
333
|
+
|
334
|
+
|
335
|
+
/* GET */
|
336
|
+
static void
|
337
|
+
cb_params_get_alloc(struct params_st *params, lcb_size_t size)
|
338
|
+
{
|
339
|
+
lcb_size_t ii;
|
340
|
+
|
341
|
+
params->cmd.get.num = size;
|
342
|
+
if (params->cmd.get.replica) {
|
343
|
+
params->cmd.get.items = xcalloc(size, sizeof(lcb_get_replica_cmd_t));
|
344
|
+
if (params->cmd.get.items_gr == NULL) {
|
345
|
+
rb_raise(eClientNoMemoryError, "failed to allocate memory for arguments");
|
346
|
+
}
|
347
|
+
params->cmd.get.ptr = xcalloc(size, sizeof(lcb_get_replica_cmd_t *));
|
348
|
+
if (params->cmd.get.ptr_gr == NULL) {
|
349
|
+
rb_raise(eClientNoMemoryError, "failed to allocate memory for arguments");
|
350
|
+
}
|
351
|
+
for (ii = 0; ii < size; ++ii) {
|
352
|
+
params->cmd.get.ptr_gr[ii] = params->cmd.get.items_gr + ii;
|
353
|
+
}
|
354
|
+
} else {
|
355
|
+
params->cmd.get.items = xcalloc(size, sizeof(lcb_get_cmd_t));
|
356
|
+
if (params->cmd.get.items == NULL) {
|
357
|
+
rb_raise(eClientNoMemoryError, "failed to allocate memory for arguments");
|
358
|
+
}
|
359
|
+
params->cmd.get.ptr = xcalloc(size, sizeof(lcb_get_cmd_t *));
|
360
|
+
if (params->cmd.get.ptr == NULL) {
|
361
|
+
rb_raise(eClientNoMemoryError, "failed to allocate memory for arguments");
|
362
|
+
}
|
363
|
+
for (ii = 0; ii < size; ++ii) {
|
364
|
+
params->cmd.get.ptr[ii] = params->cmd.get.items + ii;
|
365
|
+
}
|
366
|
+
}
|
367
|
+
}
|
368
|
+
|
369
|
+
static void
|
370
|
+
cb_params_get_init_item(struct params_st *params, lcb_size_t idx,
|
371
|
+
VALUE key_obj, lcb_time_t exptime)
|
372
|
+
{
|
373
|
+
key_obj = unify_key(params->bucket, key_obj, 1);
|
374
|
+
if (params->cmd.get.replica) {
|
375
|
+
params->cmd.get.items_gr[idx].v.v0.key = RSTRING_PTR(key_obj);
|
376
|
+
params->cmd.get.items_gr[idx].v.v0.nkey = RSTRING_LEN(key_obj);
|
377
|
+
} else {
|
378
|
+
params->cmd.get.items[idx].v.v0.key = RSTRING_PTR(key_obj);
|
379
|
+
params->cmd.get.items[idx].v.v0.nkey = RSTRING_LEN(key_obj);
|
380
|
+
params->cmd.get.items[idx].v.v0.exptime = exptime;
|
381
|
+
params->cmd.get.items[idx].v.v0.lock = params->cmd.get.lock;
|
382
|
+
params->npayload += sizeof(exptime);
|
383
|
+
}
|
384
|
+
params->npayload += RSTRING_LEN(key_obj);
|
385
|
+
}
|
386
|
+
|
387
|
+
static int
|
388
|
+
cb_params_get_extract_keys_i(VALUE key, VALUE value, VALUE arg)
|
389
|
+
{
|
390
|
+
struct params_st *params = (struct params_st *)arg;
|
391
|
+
rb_ary_push(params->cmd.get.keys_ary, key);
|
392
|
+
cb_params_get_init_item(params, params->idx++, key, NUM2ULONG(value));
|
393
|
+
return ST_CONTINUE;
|
394
|
+
}
|
395
|
+
|
396
|
+
static void
|
397
|
+
cb_params_get_parse_options(struct params_st *params, VALUE options)
|
398
|
+
{
|
399
|
+
VALUE tmp;
|
400
|
+
|
401
|
+
if (NIL_P(options)) {
|
402
|
+
return;
|
403
|
+
}
|
404
|
+
params->cmd.get.replica = RTEST(rb_hash_aref(options, sym_replica));
|
405
|
+
params->cmd.get.extended = RTEST(rb_hash_aref(options, sym_extended));
|
406
|
+
params->cmd.get.assemble_hash = RTEST(rb_hash_aref(options, sym_assemble_hash));
|
407
|
+
if (RTEST(rb_funcall(options, id_has_key_p, 1, sym_quiet))) {
|
408
|
+
params->cmd.get.quiet = RTEST(rb_hash_aref(options, sym_quiet));
|
409
|
+
}
|
410
|
+
tmp = rb_hash_aref(options, sym_format);
|
411
|
+
if (tmp != Qnil) {
|
412
|
+
Check_Type(tmp, T_SYMBOL);
|
413
|
+
params->cmd.get.forced_format = tmp;
|
414
|
+
}
|
415
|
+
tmp = rb_hash_aref(options, sym_ttl);
|
416
|
+
if (tmp != Qnil) {
|
417
|
+
params->cmd.get.ttl = NUM2ULONG(tmp);
|
418
|
+
}
|
419
|
+
/* boolean or number of seconds to lock */
|
420
|
+
tmp = rb_hash_aref(options, sym_lock);
|
421
|
+
if (tmp != Qnil) {
|
422
|
+
params->cmd.get.lock = RTEST(tmp);
|
423
|
+
if (TYPE(tmp) == T_FIXNUM) {
|
424
|
+
params->cmd.get.ttl = NUM2ULONG(tmp);
|
425
|
+
}
|
426
|
+
}
|
427
|
+
}
|
428
|
+
|
429
|
+
static void
|
430
|
+
cb_params_get_parse_arguments(struct params_st *params, int argc, VALUE argv)
|
431
|
+
{
|
432
|
+
lcb_size_t ii;
|
433
|
+
|
434
|
+
if (argc < 1) {
|
435
|
+
rb_raise(rb_eArgError, "must be at least one key");
|
436
|
+
}
|
437
|
+
if (argc == 1) {
|
438
|
+
VALUE keys = RARRAY_PTR(argv)[0];
|
439
|
+
switch(TYPE(keys)) {
|
440
|
+
case T_ARRAY:
|
441
|
+
/* array of keys as a first argument */
|
442
|
+
params->cmd.get.array = 1;
|
443
|
+
cb_params_get_alloc(params, RARRAY_LEN(keys));
|
444
|
+
for (ii = 0; ii < params->cmd.get.num; ++ii) {
|
445
|
+
rb_ary_push(params->cmd.get.keys_ary, RARRAY_PTR(keys)[ii]);
|
446
|
+
cb_params_get_init_item(params, ii, RARRAY_PTR(keys)[ii], params->cmd.get.ttl);
|
447
|
+
}
|
448
|
+
break;
|
449
|
+
case T_HASH:
|
450
|
+
/* key-ttl pairs */
|
451
|
+
if (params->cmd.get.replica) {
|
452
|
+
rb_raise(rb_eArgError, "must be either list of key or single key");
|
453
|
+
}
|
454
|
+
params->cmd.get.gat = 1;
|
455
|
+
cb_params_get_alloc(params, RHASH_SIZE(keys));
|
456
|
+
rb_hash_foreach(keys, cb_params_get_extract_keys_i, (VALUE)params);
|
457
|
+
break;
|
458
|
+
default:
|
459
|
+
/* single key */
|
460
|
+
cb_params_get_alloc(params, 1);
|
461
|
+
rb_ary_push(params->cmd.get.keys_ary, keys);
|
462
|
+
cb_params_get_init_item(params, 0, keys, params->cmd.get.ttl);
|
463
|
+
}
|
464
|
+
} else {
|
465
|
+
/* just list of arguments */
|
466
|
+
cb_params_get_alloc(params, argc);
|
467
|
+
for (ii = 0; ii < params->cmd.get.num; ++ii) {
|
468
|
+
rb_ary_push(params->cmd.get.keys_ary, RARRAY_PTR(argv)[ii]);
|
469
|
+
cb_params_get_init_item(params, ii, RARRAY_PTR(argv)[ii], params->cmd.get.ttl);
|
470
|
+
}
|
471
|
+
}
|
472
|
+
}
|
473
|
+
|
474
|
+
|
475
|
+
/* ARITH */
|
476
|
+
static void
|
477
|
+
cb_params_arith_alloc(struct params_st *params, lcb_size_t size)
|
478
|
+
{
|
479
|
+
lcb_size_t ii;
|
480
|
+
|
481
|
+
params->cmd.arith.num = size;
|
482
|
+
params->cmd.arith.items = xcalloc(size, sizeof(lcb_arithmetic_cmd_t));
|
483
|
+
if (params->cmd.arith.items == NULL) {
|
484
|
+
rb_raise(eClientNoMemoryError, "failed to allocate memory for arguments");
|
485
|
+
}
|
486
|
+
params->cmd.arith.ptr = xcalloc(size, sizeof(lcb_arithmetic_cmd_t *));
|
487
|
+
if (params->cmd.arith.ptr == NULL) {
|
488
|
+
rb_raise(eClientNoMemoryError, "failed to allocate memory for arguments");
|
489
|
+
}
|
490
|
+
for (ii = 0; ii < size; ++ii) {
|
491
|
+
params->cmd.arith.ptr[ii] = params->cmd.arith.items + ii;
|
492
|
+
}
|
493
|
+
}
|
494
|
+
|
495
|
+
static void
|
496
|
+
cb_params_arith_init_item(struct params_st *params, lcb_size_t idx,
|
497
|
+
VALUE key_obj, lcb_int64_t delta)
|
498
|
+
{
|
499
|
+
key_obj = unify_key(params->bucket, key_obj, 1);
|
500
|
+
params->cmd.arith.items[idx].v.v0.key = RSTRING_PTR(key_obj);
|
501
|
+
params->cmd.arith.items[idx].v.v0.nkey = RSTRING_LEN(key_obj);
|
502
|
+
params->cmd.arith.items[idx].v.v0.delta = delta * params->cmd.arith.sign;
|
503
|
+
params->cmd.arith.items[idx].v.v0.exptime = params->cmd.arith.ttl;
|
504
|
+
params->cmd.arith.items[idx].v.v0.create = params->cmd.arith.create;
|
505
|
+
params->cmd.arith.items[idx].v.v0.initial = params->cmd.arith.initial;
|
506
|
+
params->npayload += RSTRING_LEN(key_obj);
|
507
|
+
}
|
508
|
+
|
509
|
+
static int
|
510
|
+
cb_params_arith_extract_keys_i(VALUE key, VALUE value, VALUE arg)
|
511
|
+
{
|
512
|
+
struct params_st *params = (struct params_st *)arg;
|
513
|
+
cb_params_arith_init_item(params, params->idx++, key, NUM2ULONG(value) & INT64_MAX);
|
514
|
+
return ST_CONTINUE;
|
515
|
+
}
|
516
|
+
|
517
|
+
static void
|
518
|
+
cb_params_arith_parse_options(struct params_st *params, VALUE options)
|
519
|
+
{
|
520
|
+
VALUE tmp;
|
521
|
+
|
522
|
+
if (NIL_P(options)) {
|
523
|
+
return;
|
524
|
+
}
|
525
|
+
params->cmd.arith.create = RTEST(rb_hash_aref(options, sym_create));
|
526
|
+
params->cmd.arith.extended = RTEST(rb_hash_aref(options, sym_extended));
|
527
|
+
tmp = rb_hash_aref(options, sym_ttl);
|
528
|
+
if (tmp != Qnil) {
|
529
|
+
params->cmd.arith.ttl = NUM2ULONG(tmp);
|
530
|
+
}
|
531
|
+
tmp = rb_hash_aref(options, sym_initial);
|
532
|
+
if (tmp != Qnil) {
|
533
|
+
params->cmd.arith.initial = NUM2ULL(tmp);
|
534
|
+
params->cmd.arith.create = 1;
|
535
|
+
}
|
536
|
+
tmp = rb_hash_aref(options, sym_delta);
|
537
|
+
if (tmp != Qnil) {
|
538
|
+
params->cmd.arith.delta = NUM2ULL(tmp) & INT64_MAX;
|
539
|
+
}
|
540
|
+
tmp = rb_hash_aref(options, sym_format);
|
541
|
+
if (tmp != Qnil) { /* rewrite format bits */
|
542
|
+
params->cmd.arith.format = tmp;
|
543
|
+
}
|
544
|
+
if (params->cmd.arith.format == sym_document) {
|
545
|
+
/* just amend datatype for now */
|
546
|
+
params->cmd.arith.datatype = 0x01;
|
547
|
+
}
|
548
|
+
}
|
549
|
+
|
550
|
+
static void
|
551
|
+
cb_params_arith_parse_arguments(struct params_st *params, int argc, VALUE argv)
|
552
|
+
{
|
553
|
+
lcb_size_t ii;
|
554
|
+
|
555
|
+
if (argc < 1) {
|
556
|
+
rb_raise(rb_eArgError, "must be at least one key");
|
557
|
+
}
|
558
|
+
if (argc == 1) {
|
559
|
+
VALUE keys = RARRAY_PTR(argv)[0];
|
560
|
+
switch(TYPE(keys)) {
|
561
|
+
case T_ARRAY:
|
562
|
+
/* array of keys as a first argument */
|
563
|
+
params->cmd.arith.array = 1;
|
564
|
+
cb_params_arith_alloc(params, RARRAY_LEN(keys));
|
565
|
+
for (ii = 0; ii < params->cmd.arith.num; ++ii) {
|
566
|
+
cb_params_arith_init_item(params, ii, RARRAY_PTR(keys)[ii], params->cmd.arith.delta);
|
567
|
+
}
|
568
|
+
break;
|
569
|
+
case T_HASH:
|
570
|
+
/* key-delta pairs */
|
571
|
+
cb_params_arith_alloc(params, RHASH_SIZE(keys));
|
572
|
+
rb_hash_foreach(keys, cb_params_arith_extract_keys_i, (VALUE)params);
|
573
|
+
break;
|
574
|
+
default:
|
575
|
+
/* single key */
|
576
|
+
cb_params_arith_alloc(params, 1);
|
577
|
+
cb_params_arith_init_item(params, 0, keys, params->cmd.arith.delta);
|
578
|
+
}
|
579
|
+
} else {
|
580
|
+
/* just list of arguments */
|
581
|
+
cb_params_arith_alloc(params, argc);
|
582
|
+
for (ii = 0; ii < params->cmd.arith.num; ++ii) {
|
583
|
+
cb_params_arith_init_item(params, ii, RARRAY_PTR(argv)[ii], params->cmd.arith.delta);
|
584
|
+
}
|
585
|
+
}
|
586
|
+
}
|
587
|
+
|
588
|
+
|
589
|
+
/* STATS */
|
590
|
+
static void
|
591
|
+
cb_params_stats_alloc(struct params_st *params, lcb_size_t size)
|
592
|
+
{
|
593
|
+
lcb_size_t ii;
|
594
|
+
|
595
|
+
params->cmd.stats.num = size;
|
596
|
+
params->cmd.stats.items = xcalloc(size, sizeof(lcb_server_stats_cmd_t));
|
597
|
+
if (params->cmd.stats.items == NULL) {
|
598
|
+
rb_raise(eClientNoMemoryError, "failed to allocate memory for arguments");
|
599
|
+
}
|
600
|
+
params->cmd.stats.ptr = xcalloc(size, sizeof(lcb_server_stats_cmd_t *));
|
601
|
+
if (params->cmd.stats.ptr == NULL) {
|
602
|
+
rb_raise(eClientNoMemoryError, "failed to allocate memory for arguments");
|
603
|
+
}
|
604
|
+
for (ii = 0; ii < size; ++ii) {
|
605
|
+
params->cmd.stats.ptr[ii] = params->cmd.stats.items + ii;
|
606
|
+
}
|
607
|
+
}
|
608
|
+
|
609
|
+
static void
|
610
|
+
cb_params_stats_init_item(struct params_st *params, lcb_size_t idx,
|
611
|
+
VALUE key_obj)
|
612
|
+
{
|
613
|
+
key_obj = unify_key(params->bucket, key_obj, 1);
|
614
|
+
params->cmd.stats.items[idx].v.v0.name = RSTRING_PTR(key_obj);
|
615
|
+
params->cmd.stats.items[idx].v.v0.nname = RSTRING_LEN(key_obj);
|
616
|
+
params->npayload += RSTRING_LEN(key_obj);
|
617
|
+
}
|
618
|
+
|
619
|
+
static void
|
620
|
+
cb_params_stats_parse_arguments(struct params_st *params, int argc, VALUE argv)
|
621
|
+
{
|
622
|
+
lcb_size_t ii;
|
623
|
+
|
624
|
+
if (argc == 1) {
|
625
|
+
VALUE keys = RARRAY_PTR(argv)[0];
|
626
|
+
switch(TYPE(keys)) {
|
627
|
+
case T_ARRAY:
|
628
|
+
/* array of keys as a first argument */
|
629
|
+
params->cmd.stats.array = 1;
|
630
|
+
cb_params_stats_alloc(params, RARRAY_LEN(keys));
|
631
|
+
for (ii = 0; ii < params->cmd.stats.num; ++ii) {
|
632
|
+
cb_params_stats_init_item(params, ii, RARRAY_PTR(keys)[ii]);
|
633
|
+
}
|
634
|
+
break;
|
635
|
+
default:
|
636
|
+
/* single key */
|
637
|
+
cb_params_stats_alloc(params, 1);
|
638
|
+
cb_params_stats_init_item(params, 0, keys);
|
639
|
+
}
|
640
|
+
} else if (argc == 0) {
|
641
|
+
/* stat without argument (single empty struct) */
|
642
|
+
cb_params_stats_alloc(params, 1);
|
643
|
+
} else {
|
644
|
+
/* just list of arguments */
|
645
|
+
cb_params_stats_alloc(params, argc);
|
646
|
+
for (ii = 0; ii < params->cmd.stats.num; ++ii) {
|
647
|
+
cb_params_stats_init_item(params, ii, RARRAY_PTR(argv)[ii]);
|
648
|
+
}
|
649
|
+
}
|
650
|
+
}
|
651
|
+
|
652
|
+
|
653
|
+
/* REMOVE */
|
654
|
+
|
655
|
+
static void
|
656
|
+
cb_params_observe_alloc(struct params_st *params, lcb_size_t size)
|
657
|
+
{
|
658
|
+
lcb_size_t ii;
|
659
|
+
|
660
|
+
params->cmd.observe.num = size;
|
661
|
+
params->cmd.observe.items = xcalloc(size, sizeof(lcb_observe_cmd_t));
|
662
|
+
if (params->cmd.observe.items == NULL) {
|
663
|
+
rb_raise(eClientNoMemoryError, "failed to allocate memory for arguments");
|
664
|
+
}
|
665
|
+
params->cmd.observe.ptr = xcalloc(size, sizeof(lcb_observe_cmd_t *));
|
666
|
+
if (params->cmd.observe.ptr == NULL) {
|
667
|
+
rb_raise(eClientNoMemoryError, "failed to allocate memory for arguments");
|
668
|
+
}
|
669
|
+
for (ii = 0; ii < size; ++ii) {
|
670
|
+
params->cmd.observe.ptr[ii] = params->cmd.observe.items + ii;
|
671
|
+
}
|
672
|
+
}
|
673
|
+
|
674
|
+
static void
|
675
|
+
cb_params_observe_init_item(struct params_st *params, lcb_size_t idx, VALUE key_obj)
|
676
|
+
{
|
677
|
+
key_obj = unify_key(params->bucket, key_obj, 1);
|
678
|
+
params->cmd.observe.items[idx].v.v0.key = RSTRING_PTR(key_obj);
|
679
|
+
params->cmd.observe.items[idx].v.v0.nkey = RSTRING_LEN(key_obj);
|
680
|
+
params->npayload += RSTRING_LEN(key_obj);
|
681
|
+
}
|
682
|
+
|
683
|
+
static void
|
684
|
+
cb_params_observe_parse_arguments(struct params_st *params, int argc, VALUE argv)
|
685
|
+
{
|
686
|
+
lcb_size_t ii;
|
687
|
+
|
688
|
+
if (argc < 1) {
|
689
|
+
rb_raise(rb_eArgError, "must be at least one key");
|
690
|
+
}
|
691
|
+
if (argc == 1) {
|
692
|
+
VALUE keys = RARRAY_PTR(argv)[0];
|
693
|
+
switch(TYPE(keys)) {
|
694
|
+
case T_ARRAY:
|
695
|
+
/* array of keys as a first argument */
|
696
|
+
params->cmd.observe.array = 1;
|
697
|
+
cb_params_observe_alloc(params, RARRAY_LEN(keys));
|
698
|
+
for (ii = 0; ii < params->cmd.observe.num; ++ii) {
|
699
|
+
cb_params_observe_init_item(params, ii, RARRAY_PTR(keys)[ii]);
|
700
|
+
}
|
701
|
+
break;
|
702
|
+
default:
|
703
|
+
/* single key */
|
704
|
+
cb_params_observe_alloc(params, 1);
|
705
|
+
cb_params_observe_init_item(params, 0, keys);
|
706
|
+
}
|
707
|
+
} else {
|
708
|
+
/* just list of arguments */
|
709
|
+
cb_params_observe_alloc(params, argc);
|
710
|
+
for (ii = 0; ii < params->cmd.observe.num; ++ii) {
|
711
|
+
cb_params_observe_init_item(params, ii, RARRAY_PTR(argv)[ii]);
|
712
|
+
}
|
713
|
+
}
|
714
|
+
}
|
715
|
+
|
716
|
+
|
717
|
+
/* UNLOCK */
|
718
|
+
static void
|
719
|
+
cb_params_unlock_alloc(struct params_st *params, lcb_size_t size)
|
720
|
+
{
|
721
|
+
lcb_size_t ii;
|
722
|
+
|
723
|
+
params->cmd.unlock.num = size;
|
724
|
+
params->cmd.unlock.items = xcalloc(size, sizeof(lcb_unlock_cmd_t));
|
725
|
+
if (params->cmd.unlock.items == NULL) {
|
726
|
+
rb_raise(eClientNoMemoryError, "failed to allocate memory for arguments");
|
727
|
+
}
|
728
|
+
params->cmd.unlock.ptr = xcalloc(size, sizeof(lcb_unlock_cmd_t *));
|
729
|
+
if (params->cmd.unlock.ptr == NULL) {
|
730
|
+
rb_raise(eClientNoMemoryError, "failed to allocate memory for arguments");
|
731
|
+
}
|
732
|
+
for (ii = 0; ii < size; ++ii) {
|
733
|
+
params->cmd.unlock.ptr[ii] = params->cmd.unlock.items + ii;
|
734
|
+
}
|
735
|
+
}
|
736
|
+
|
737
|
+
static void
|
738
|
+
cb_params_unlock_init_item(struct params_st *params, lcb_size_t idx, VALUE key_obj, lcb_cas_t cas)
|
739
|
+
{
|
740
|
+
key_obj = unify_key(params->bucket, key_obj, 1);
|
741
|
+
params->cmd.unlock.items[idx].v.v0.key = RSTRING_PTR(key_obj);
|
742
|
+
params->cmd.unlock.items[idx].v.v0.nkey = RSTRING_LEN(key_obj);
|
743
|
+
params->cmd.unlock.items[idx].v.v0.cas = cas;
|
744
|
+
params->npayload += RSTRING_LEN(key_obj);
|
745
|
+
}
|
746
|
+
|
747
|
+
static int
|
748
|
+
cb_params_unlock_extract_keys_i(VALUE key, VALUE value, VALUE arg)
|
749
|
+
{
|
750
|
+
struct params_st *params = (struct params_st *)arg;
|
751
|
+
cb_params_unlock_init_item(params, params->idx++, key, NUM2ULL(value));
|
752
|
+
return ST_CONTINUE;
|
753
|
+
}
|
754
|
+
|
755
|
+
static void
|
756
|
+
cb_params_unlock_parse_options(struct params_st *params, VALUE options)
|
757
|
+
{
|
758
|
+
VALUE tmp;
|
759
|
+
|
760
|
+
if (NIL_P(options)) {
|
761
|
+
return;
|
762
|
+
}
|
763
|
+
tmp = rb_hash_aref(options, sym_cas);
|
764
|
+
if (tmp != Qnil) {
|
765
|
+
params->cmd.unlock.cas = NUM2ULL(tmp);
|
766
|
+
}
|
767
|
+
if (RTEST(rb_funcall(options, id_has_key_p, 1, sym_quiet))) {
|
768
|
+
params->cmd.unlock.quiet = RTEST(rb_hash_aref(options, sym_quiet));
|
769
|
+
}
|
770
|
+
}
|
771
|
+
|
772
|
+
static void
|
773
|
+
cb_params_unlock_parse_arguments(struct params_st *params, int argc, VALUE argv)
|
774
|
+
{
|
775
|
+
if (argc == 1) {
|
776
|
+
VALUE keys = RARRAY_PTR(argv)[0];
|
777
|
+
switch(TYPE(keys)) {
|
778
|
+
case T_HASH:
|
779
|
+
/* key-cas pairs */
|
780
|
+
cb_params_unlock_alloc(params, RHASH_SIZE(keys));
|
781
|
+
rb_hash_foreach(keys, cb_params_unlock_extract_keys_i, (VALUE)params);
|
782
|
+
break;
|
783
|
+
default:
|
784
|
+
/* single key */
|
785
|
+
cb_params_unlock_alloc(params, 1);
|
786
|
+
cb_params_unlock_init_item(params, 0, keys, params->cmd.unlock.cas);
|
787
|
+
}
|
788
|
+
} else {
|
789
|
+
rb_raise(rb_eArgError, "must be either Hash or single key with cas option");
|
790
|
+
}
|
791
|
+
}
|
792
|
+
|
793
|
+
|
794
|
+
/* VERSION */
|
795
|
+
static void
|
796
|
+
cb_params_version_alloc(struct params_st *params)
|
797
|
+
{
|
798
|
+
params->cmd.version.num = 1;
|
799
|
+
params->cmd.version.items = xcalloc(1, sizeof(lcb_server_version_cmd_t));
|
800
|
+
if (params->cmd.version.items == NULL) {
|
801
|
+
rb_raise(eClientNoMemoryError, "failed to allocate memory for arguments");
|
802
|
+
}
|
803
|
+
params->cmd.version.ptr = xcalloc(1, sizeof(lcb_server_version_cmd_t *));
|
804
|
+
if (params->cmd.version.ptr == NULL) {
|
805
|
+
rb_raise(eClientNoMemoryError, "failed to allocate memory for arguments");
|
806
|
+
}
|
807
|
+
params->cmd.version.ptr[0] = params->cmd.version.items;
|
808
|
+
}
|
809
|
+
|
810
|
+
|
811
|
+
/* common stuff */
|
812
|
+
void
|
813
|
+
cb_params_destroy(struct params_st *params)
|
814
|
+
{
|
815
|
+
#define _release_data_for(type) \
|
816
|
+
xfree(params->cmd.type.items); \
|
817
|
+
xfree(params->cmd.type.ptr);
|
818
|
+
|
819
|
+
switch (params->type) {
|
820
|
+
case cmd_get:
|
821
|
+
_release_data_for(get);
|
822
|
+
xfree(params->cmd.get.items_gr);
|
823
|
+
xfree(params->cmd.get.ptr_gr);
|
824
|
+
break;
|
825
|
+
case cmd_touch:
|
826
|
+
_release_data_for(touch);
|
827
|
+
break;
|
828
|
+
case cmd_arith:
|
829
|
+
_release_data_for(arith);
|
830
|
+
break;
|
831
|
+
case cmd_remove:
|
832
|
+
_release_data_for(remove);
|
833
|
+
break;
|
834
|
+
case cmd_store:
|
835
|
+
_release_data_for(store);
|
836
|
+
break;
|
837
|
+
case cmd_stats:
|
838
|
+
_release_data_for(stats);
|
839
|
+
break;
|
840
|
+
case cmd_version:
|
841
|
+
_release_data_for(version);
|
842
|
+
break;
|
843
|
+
case cmd_observe:
|
844
|
+
_release_data_for(observe);
|
845
|
+
break;
|
846
|
+
case cmd_unlock:
|
847
|
+
_release_data_for(unlock);
|
848
|
+
break;
|
849
|
+
}
|
850
|
+
#undef _release_data_for
|
851
|
+
}
|
852
|
+
|
853
|
+
struct build_params_st
|
854
|
+
{
|
855
|
+
struct params_st *params;
|
856
|
+
int argc;
|
857
|
+
VALUE argv;
|
858
|
+
};
|
859
|
+
|
860
|
+
static VALUE
|
861
|
+
do_params_build(VALUE ptr)
|
862
|
+
{
|
863
|
+
VALUE opts;
|
864
|
+
/* unpack arguments */
|
865
|
+
struct build_params_st *p = (struct build_params_st *)ptr;
|
866
|
+
struct params_st *params = p->params;
|
867
|
+
int argc = p->argc;
|
868
|
+
VALUE argv = p->argv;
|
869
|
+
|
870
|
+
/* extract options */
|
871
|
+
if (argc > 1 && TYPE(RARRAY_PTR(argv)[argc-1]) == T_HASH) {
|
872
|
+
opts = rb_ary_pop(argv);
|
873
|
+
--argc;
|
874
|
+
} else {
|
875
|
+
opts = Qnil;
|
876
|
+
}
|
877
|
+
|
878
|
+
params->npayload = PACKET_HEADER_SIZE; /* size of packet header */
|
879
|
+
switch (params->type) {
|
880
|
+
case cmd_touch:
|
881
|
+
params->cmd.touch.quiet = params->bucket->quiet;
|
882
|
+
params->cmd.touch.ttl = params->bucket->default_ttl;
|
883
|
+
cb_params_touch_parse_options(params, opts);
|
884
|
+
cb_params_touch_parse_arguments(params, argc, argv);
|
885
|
+
break;
|
886
|
+
case cmd_remove:
|
887
|
+
params->cmd.remove.quiet = params->bucket->quiet;
|
888
|
+
if (argc == 2) {
|
889
|
+
int type = TYPE(RARRAY_PTR(argv)[1]);
|
890
|
+
if (type == T_FIXNUM || type == T_BIGNUM) {
|
891
|
+
/* allow form delete("foo", 0xdeadbeef) */
|
892
|
+
--argc;
|
893
|
+
params->cmd.remove.cas = NUM2ULL(rb_ary_pop(argv));
|
894
|
+
}
|
895
|
+
}
|
896
|
+
cb_params_remove_parse_options(params, opts);
|
897
|
+
cb_params_remove_parse_arguments(params, argc, argv);
|
898
|
+
break;
|
899
|
+
case cmd_store:
|
900
|
+
if (argc == 1 && opts != Qnil) {
|
901
|
+
/* put last hash back because it is the value */
|
902
|
+
rb_ary_push(argv, opts);
|
903
|
+
opts = Qnil;
|
904
|
+
++argc;
|
905
|
+
}
|
906
|
+
params->cmd.store.datatype = 0x00;
|
907
|
+
params->cmd.store.ttl = params->bucket->default_ttl;
|
908
|
+
params->cmd.store.flags = flags_set_format(params->bucket->default_flags,
|
909
|
+
params->bucket->default_format);
|
910
|
+
params->cmd.store.observe = Qnil;
|
911
|
+
cb_params_store_parse_options(params, opts);
|
912
|
+
cb_params_store_parse_arguments(params, argc, argv);
|
913
|
+
break;
|
914
|
+
case cmd_get:
|
915
|
+
params->cmd.get.quiet = params->bucket->quiet;
|
916
|
+
cb_params_get_parse_options(params, opts);
|
917
|
+
cb_params_get_parse_arguments(params, argc, argv);
|
918
|
+
break;
|
919
|
+
case cmd_arith:
|
920
|
+
params->cmd.arith.delta = 1;
|
921
|
+
params->cmd.arith.format = params->bucket->default_format;
|
922
|
+
params->cmd.arith.ttl = params->bucket->default_ttl;
|
923
|
+
if (argc == 2 && TYPE(RARRAY_PTR(argv)[1]) == T_FIXNUM) {
|
924
|
+
/* allow form incr("foo", 1) */
|
925
|
+
--argc;
|
926
|
+
params->cmd.arith.delta = NUM2ULL(rb_ary_pop(argv)) & INT64_MAX;
|
927
|
+
}
|
928
|
+
cb_params_arith_parse_options(params, opts);
|
929
|
+
cb_params_arith_parse_arguments(params, argc, argv);
|
930
|
+
break;
|
931
|
+
case cmd_stats:
|
932
|
+
cb_params_stats_parse_arguments(params, argc, argv);
|
933
|
+
break;
|
934
|
+
case cmd_version:
|
935
|
+
cb_params_version_alloc(params);
|
936
|
+
break;
|
937
|
+
case cmd_observe:
|
938
|
+
cb_params_observe_parse_arguments(params, argc, argv);
|
939
|
+
break;
|
940
|
+
case cmd_unlock:
|
941
|
+
params->cmd.unlock.quiet = params->bucket->quiet;
|
942
|
+
if (argc == 2) {
|
943
|
+
int type = TYPE(RARRAY_PTR(argv)[1]);
|
944
|
+
if (type == T_FIXNUM || type == T_BIGNUM) {
|
945
|
+
/* allow form unlock("foo", 0xdeadbeef) */
|
946
|
+
--argc;
|
947
|
+
params->cmd.unlock.cas = NUM2ULL(rb_ary_pop(argv));
|
948
|
+
}
|
949
|
+
}
|
950
|
+
cb_params_unlock_parse_options(params, opts);
|
951
|
+
cb_params_unlock_parse_arguments(params, argc, argv);
|
952
|
+
break;
|
953
|
+
}
|
954
|
+
|
955
|
+
return Qnil;
|
956
|
+
}
|
957
|
+
|
958
|
+
void
|
959
|
+
cb_params_build(struct params_st *params, int argc, VALUE argv)
|
960
|
+
{
|
961
|
+
int fail = 0;
|
962
|
+
struct build_params_st args;
|
963
|
+
|
964
|
+
args.params = params;
|
965
|
+
args.argc = argc;
|
966
|
+
args.argv = argv;
|
967
|
+
rb_protect(do_params_build, (VALUE)&args, &fail);
|
968
|
+
if (fail) {
|
969
|
+
cb_params_destroy(params);
|
970
|
+
/* raise exception from protected block */
|
971
|
+
rb_jump_tag(fail);
|
972
|
+
}
|
973
|
+
}
|