libcouchbase 0.0.9 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +4 -4
- data/README.md +4 -0
- data/ext/libcouchbase/CMakeLists.txt +1 -1
- data/ext/libcouchbase/RELEASE_NOTES.markdown +42 -0
- data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +3 -3
- data/ext/libcouchbase/cmake/source_files.cmake +1 -0
- data/ext/libcouchbase/include/libcouchbase/cntl.h +27 -1
- data/ext/libcouchbase/include/libcouchbase/couchbase.h +0 -10
- data/ext/libcouchbase/include/libcouchbase/error.h +8 -1
- data/ext/libcouchbase/include/memcached/protocol_binary.h +12 -3
- data/ext/libcouchbase/src/auth.cc +0 -4
- data/ext/libcouchbase/src/cntl.cc +11 -1
- data/ext/libcouchbase/src/connspec.cc +18 -0
- data/ext/libcouchbase/src/connspec.h +10 -0
- data/ext/libcouchbase/src/dns-srv.cc +13 -14
- data/ext/libcouchbase/src/errmap.cc +107 -0
- data/ext/libcouchbase/src/errmap.h +113 -0
- data/ext/libcouchbase/src/hostlist.cc +0 -35
- data/ext/libcouchbase/src/hostlist.h +38 -64
- data/ext/libcouchbase/src/http/http.cc +6 -1
- data/ext/libcouchbase/src/instance.cc +1 -1
- data/ext/libcouchbase/src/internal.h +10 -0
- data/ext/libcouchbase/src/mcserver/mcserver.cc +119 -3
- data/ext/libcouchbase/src/mcserver/mcserver.h +3 -1
- data/ext/libcouchbase/src/mcserver/negotiate.cc +130 -37
- data/ext/libcouchbase/src/nodeinfo.cc +1 -1
- data/ext/libcouchbase/src/settings.c +3 -0
- data/ext/libcouchbase/src/settings.h +5 -0
- data/ext/libcouchbase/src/ssl/ssl_common.c +2 -0
- data/ext/libcouchbase/tests/basic/t_host.cc +67 -75
- data/ext/libcouchbase/tests/iotests/mock-environment.h +2 -1
- data/ext/libcouchbase/tests/iotests/t_confmon.cc +3 -4
- data/ext/libcouchbase/tests/iotests/t_errmap.cc +97 -0
- data/lib/libcouchbase/bucket.rb +27 -12
- data/lib/libcouchbase/callbacks.rb +1 -1
- data/lib/libcouchbase/connection.rb +18 -5
- data/lib/libcouchbase/version.rb +1 -1
- data/spec/connection_spec.rb +1 -1
- metadata +5 -2
@@ -141,14 +141,13 @@ TEST_F(ConfmonTest, testCycle)
|
|
141
141
|
Provider *cccp = mon->get_provider(CLCONFIG_CCCP);
|
142
142
|
Provider *http = mon->get_provider(CLCONFIG_HTTP);
|
143
143
|
|
144
|
-
|
145
|
-
|
144
|
+
lcb::Hostlist hl;
|
145
|
+
hl.add(cropts.v.v2.mchosts, 11210);
|
146
146
|
cccp->enable(instance);
|
147
|
-
cccp->configure_nodes(
|
147
|
+
cccp->configure_nodes(hl);
|
148
148
|
|
149
149
|
http->enable();
|
150
150
|
http->configure_nodes(*instance->ht_nodes);
|
151
|
-
hostlist_destroy(hl);
|
152
151
|
|
153
152
|
mon->prepare();
|
154
153
|
mon->start();
|
@@ -0,0 +1,97 @@
|
|
1
|
+
#include "config.h"
|
2
|
+
#include "iotests.h"
|
3
|
+
#include "internal.h"
|
4
|
+
#include <map>
|
5
|
+
|
6
|
+
class ErrmapUnitTest : public MockUnitTest {
|
7
|
+
protected:
|
8
|
+
virtual void createErrmapConnection(HandleWrap& hw, lcb_t& instance) {
|
9
|
+
MockEnvironment::getInstance()->createConnection(hw, instance);
|
10
|
+
ASSERT_EQ(LCB_SUCCESS, lcb_cntl_string(instance, "enable_errmap", "true"));
|
11
|
+
ASSERT_EQ(LCB_SUCCESS, lcb_connect(instance));
|
12
|
+
lcb_wait(instance);
|
13
|
+
ASSERT_EQ(LCB_SUCCESS, lcb_get_bootstrap_status(instance));
|
14
|
+
}
|
15
|
+
};
|
16
|
+
|
17
|
+
struct ResultCookie {
|
18
|
+
lcb_error_t rc;
|
19
|
+
bool called;
|
20
|
+
|
21
|
+
void reset() {
|
22
|
+
rc = LCB_SUCCESS;
|
23
|
+
called = false;
|
24
|
+
}
|
25
|
+
ResultCookie() : rc(LCB_SUCCESS), called(false) {
|
26
|
+
}
|
27
|
+
};
|
28
|
+
|
29
|
+
extern "C" {
|
30
|
+
static void opcb(lcb_t,int,const lcb_RESPBASE* rb) {
|
31
|
+
ResultCookie *cookie = reinterpret_cast<ResultCookie*>(rb->cookie);
|
32
|
+
cookie->called = true;
|
33
|
+
cookie->rc = rb->rc;
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
37
|
+
TEST_F(ErrmapUnitTest, hasRecognizedErrors) {
|
38
|
+
SKIP_UNLESS_MOCK();
|
39
|
+
HandleWrap hw;
|
40
|
+
lcb_t instance;
|
41
|
+
|
42
|
+
createErrmapConnection(hw, instance);
|
43
|
+
|
44
|
+
// Test the actual error map..
|
45
|
+
using namespace lcb;
|
46
|
+
const errmap::ErrorMap& em = *instance->settings->errmap;
|
47
|
+
const errmap::Error& err = em.getError(PROTOCOL_BINARY_RESPONSE_KEY_ENOENT);
|
48
|
+
ASSERT_TRUE(err.isValid());
|
49
|
+
ASSERT_TRUE(err.hasAttribute(errmap::CONSTRAINT_FAILURE));
|
50
|
+
}
|
51
|
+
|
52
|
+
TEST_F(ErrmapUnitTest, closesOnUnrecognizedError) {
|
53
|
+
// For now, EINTERNAL is an error code we don't know!
|
54
|
+
SKIP_UNLESS_MOCK();
|
55
|
+
HandleWrap hw;
|
56
|
+
lcb_t instance;
|
57
|
+
createErrmapConnection(hw, instance);
|
58
|
+
|
59
|
+
const char *key = "key";
|
60
|
+
lcb_CMDSTORE scmd = { 0 };
|
61
|
+
LCB_CMD_SET_KEY(&scmd, key, strlen(key));
|
62
|
+
LCB_CMD_SET_VALUE(&scmd, "val", 3);
|
63
|
+
|
64
|
+
ResultCookie cookie;
|
65
|
+
lcb_install_callback3(instance, LCB_CALLBACK_STORE, opcb);
|
66
|
+
ASSERT_EQ(LCB_SUCCESS, lcb_store3(instance, &cookie, &scmd));
|
67
|
+
lcb_wait(instance);
|
68
|
+
ASSERT_EQ(LCB_SUCCESS, cookie.rc);
|
69
|
+
|
70
|
+
MockCommand cmd(MockCommand::OPFAIL);
|
71
|
+
|
72
|
+
// Determine the server
|
73
|
+
int srvix = instance->map_key(key);
|
74
|
+
|
75
|
+
cmd.set("server", srvix);
|
76
|
+
cmd.set("code", PROTOCOL_BINARY_RESPONSE_EINTERNAL); // Invalidate the connection!
|
77
|
+
cmd.set("count", 1);
|
78
|
+
doMockTxn(cmd);
|
79
|
+
|
80
|
+
cookie.reset();
|
81
|
+
ASSERT_EQ(LCB_SUCCESS, lcb_store3(instance, &cookie, &scmd));
|
82
|
+
lcb_wait(instance);
|
83
|
+
|
84
|
+
ASSERT_TRUE(cookie.called);
|
85
|
+
ASSERT_NE(LCB_SUCCESS, cookie.rc);
|
86
|
+
|
87
|
+
cookie.reset();
|
88
|
+
ASSERT_EQ(LCB_SUCCESS, lcb_store3(instance, &cookie, &scmd));
|
89
|
+
lcb_wait(instance);
|
90
|
+
ASSERT_TRUE(cookie.called);
|
91
|
+
|
92
|
+
// Note, we can't determine what the actual error here is. It would be nice
|
93
|
+
// if we were able to reconnect and retry the other commands, but right now
|
94
|
+
// detecting a failed connection is better than having no detection at all:
|
95
|
+
//
|
96
|
+
// ASSERT_EQ(LCB_SUCCESS, cookie.rc);
|
97
|
+
}
|
data/lib/libcouchbase/bucket.rb
CHANGED
@@ -24,7 +24,7 @@ module Libcouchbase
|
|
24
24
|
|
25
25
|
# This obtains the connections reactor
|
26
26
|
@reactor = reactor
|
27
|
-
@quiet =
|
27
|
+
@quiet = false
|
28
28
|
|
29
29
|
# clean up the connection once this object is garbage collected
|
30
30
|
ObjectSpace.define_finalizer( self, self.class.finalize(@connection) )
|
@@ -157,7 +157,11 @@ module Libcouchbase
|
|
157
157
|
}), async)
|
158
158
|
end
|
159
159
|
end
|
160
|
-
|
160
|
+
|
161
|
+
# Quietly obtain an object stored in Couchbase by given key.
|
162
|
+
def [](key)
|
163
|
+
get(key, quiet: true)
|
164
|
+
end
|
161
165
|
|
162
166
|
# Add the item to the database, but fail if the object exists already
|
163
167
|
#
|
@@ -495,7 +499,7 @@ module Libcouchbase
|
|
495
499
|
# res = c.set("foo", "bar") #=> #<struct Libcouchbase::Response callback=:callback_set, key="foo", cas=1975457268957184, value="bar", metadata={:format=>:document, :flags=>0}>
|
496
500
|
# c.delete("foo", cas: 123456) #=> will raise Libcouchbase::Error::KeyExists
|
497
501
|
# c.delete("foo", cas: res.cas) #=> true
|
498
|
-
def delete(key, async: false, quiet:
|
502
|
+
def delete(key, async: false, quiet: true, **opts)
|
499
503
|
promise = @connection.remove(key, **opts).then { true }
|
500
504
|
if quiet
|
501
505
|
promise = promise.catch { |error|
|
@@ -654,7 +658,7 @@ module Libcouchbase
|
|
654
658
|
# @param [String, Symbol] key
|
655
659
|
#
|
656
660
|
# @param [Hash] options the options for "swap" part
|
657
|
-
# @option options [
|
661
|
+
# @option options [Integer] :retry (0) maximum number of times to autmatically retry upon update collision
|
658
662
|
#
|
659
663
|
# @yieldparam [Object] value existing value
|
660
664
|
# @yieldreturn [Object] new value.
|
@@ -727,7 +731,7 @@ module Libcouchbase
|
|
727
731
|
@connection.reactor.next_tick do
|
728
732
|
begin
|
729
733
|
response = co(promise)
|
730
|
-
rescue => e
|
734
|
+
rescue Exception => e
|
731
735
|
error = e
|
732
736
|
end
|
733
737
|
|
@@ -738,7 +742,7 @@ module Libcouchbase
|
|
738
742
|
|
739
743
|
Fiber.yield
|
740
744
|
|
741
|
-
|
745
|
+
update_backtrace(error) if error
|
742
746
|
response
|
743
747
|
else
|
744
748
|
request = Mutex.new
|
@@ -750,7 +754,7 @@ module Libcouchbase
|
|
750
754
|
@connection.reactor.next_tick do
|
751
755
|
begin
|
752
756
|
response = co(promise)
|
753
|
-
rescue => e
|
757
|
+
rescue Exception => e
|
754
758
|
error = e
|
755
759
|
end
|
756
760
|
|
@@ -762,7 +766,7 @@ module Libcouchbase
|
|
762
766
|
result.wait(request)
|
763
767
|
}
|
764
768
|
|
765
|
-
|
769
|
+
update_backtrace(error) if error
|
766
770
|
response
|
767
771
|
end
|
768
772
|
end
|
@@ -801,7 +805,7 @@ module Libcouchbase
|
|
801
805
|
retry
|
802
806
|
end
|
803
807
|
error = e
|
804
|
-
rescue => e
|
808
|
+
rescue Exception => e
|
805
809
|
error = e
|
806
810
|
end
|
807
811
|
|
@@ -814,7 +818,7 @@ module Libcouchbase
|
|
814
818
|
result.wait(connecting)
|
815
819
|
}
|
816
820
|
|
817
|
-
|
821
|
+
update_backtrace(error) if error
|
818
822
|
end
|
819
823
|
|
820
824
|
# Assume this is being run in em-synchrony
|
@@ -838,7 +842,7 @@ module Libcouchbase
|
|
838
842
|
retry
|
839
843
|
end
|
840
844
|
error = e
|
841
|
-
rescue => e
|
845
|
+
rescue Exception => e
|
842
846
|
error = e
|
843
847
|
end
|
844
848
|
|
@@ -850,7 +854,18 @@ module Libcouchbase
|
|
850
854
|
|
851
855
|
Fiber.yield
|
852
856
|
|
853
|
-
|
857
|
+
update_backtrace(error) if error
|
858
|
+
end
|
859
|
+
|
860
|
+
def update_backtrace(error)
|
861
|
+
backtrace = caller
|
862
|
+
backtrace.shift(2)
|
863
|
+
if error.respond_to?(:backtrace) && error.backtrace
|
864
|
+
backtrace << '---- continuation ----'
|
865
|
+
backtrace.concat(error.backtrace)
|
866
|
+
end
|
867
|
+
error.set_backtrace(backtrace)
|
868
|
+
raise error
|
854
869
|
end
|
855
870
|
end
|
856
871
|
end
|
@@ -47,7 +47,7 @@ module Libcouchbase
|
|
47
47
|
|
48
48
|
def self.included(base)
|
49
49
|
base.instance_variable_set(:@callback_funcs, {})
|
50
|
-
base.instance_variable_set(:@callback_lookup, ::Concurrent::
|
50
|
+
base.instance_variable_set(:@callback_lookup, ::Concurrent::Hash.new)
|
51
51
|
base.instance_variable_set(:@callback_lock, ::Mutex.new)
|
52
52
|
base.extend(ClassMethods)
|
53
53
|
end
|
@@ -3,6 +3,15 @@
|
|
3
3
|
require 'json'
|
4
4
|
|
5
5
|
|
6
|
+
at_exit do
|
7
|
+
ObjectSpace.each_object(::Libcouchbase::Connection).each do |connection|
|
8
|
+
connection.destroy.finally do
|
9
|
+
connection.reactor.stop
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
|
6
15
|
module Libcouchbase
|
7
16
|
Response = Struct.new(:callback, :key, :cas, :value, :metadata)
|
8
17
|
HttpResponse = Struct.new(:callback, :status, :headers, :body, :request)
|
@@ -176,12 +185,16 @@ module Libcouchbase
|
|
176
185
|
# Ensure it is thread safe
|
177
186
|
@reactor.schedule {
|
178
187
|
if @handle
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
188
|
+
nodes = Ext.get_num_nodes(@handle)
|
189
|
+
list = []
|
190
|
+
count = 0
|
191
|
+
|
192
|
+
while count <= nodes
|
193
|
+
list << Ext.get_node(@handle, :node_data, count)
|
194
|
+
count += 1
|
184
195
|
end
|
196
|
+
|
197
|
+
defer.resolve(list.uniq)
|
185
198
|
else
|
186
199
|
defer.reject(RuntimeError.new('not connected'))
|
187
200
|
end
|
data/lib/libcouchbase/version.rb
CHANGED
data/spec/connection_spec.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: libcouchbase
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stephen von Takach
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-03-
|
11
|
+
date: 2017-03-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi
|
@@ -404,6 +404,8 @@ files:
|
|
404
404
|
- ext/libcouchbase/src/ctx-log-inl.h
|
405
405
|
- ext/libcouchbase/src/dns-srv.cc
|
406
406
|
- ext/libcouchbase/src/dump.cc
|
407
|
+
- ext/libcouchbase/src/errmap.cc
|
408
|
+
- ext/libcouchbase/src/errmap.h
|
407
409
|
- ext/libcouchbase/src/getconfig.cc
|
408
410
|
- ext/libcouchbase/src/gethrtime.c
|
409
411
|
- ext/libcouchbase/src/handler.cc
|
@@ -566,6 +568,7 @@ files:
|
|
566
568
|
- ext/libcouchbase/tests/iotests/t_configcache.cc
|
567
569
|
- ext/libcouchbase/tests/iotests/t_confmon.cc
|
568
570
|
- ext/libcouchbase/tests/iotests/t_durability.cc
|
571
|
+
- ext/libcouchbase/tests/iotests/t_errmap.cc
|
569
572
|
- ext/libcouchbase/tests/iotests/t_forward.cc
|
570
573
|
- ext/libcouchbase/tests/iotests/t_get.cc
|
571
574
|
- ext/libcouchbase/tests/iotests/t_http.cc
|