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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -4
  3. data/README.md +4 -0
  4. data/ext/libcouchbase/CMakeLists.txt +1 -1
  5. data/ext/libcouchbase/RELEASE_NOTES.markdown +42 -0
  6. data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +3 -3
  7. data/ext/libcouchbase/cmake/source_files.cmake +1 -0
  8. data/ext/libcouchbase/include/libcouchbase/cntl.h +27 -1
  9. data/ext/libcouchbase/include/libcouchbase/couchbase.h +0 -10
  10. data/ext/libcouchbase/include/libcouchbase/error.h +8 -1
  11. data/ext/libcouchbase/include/memcached/protocol_binary.h +12 -3
  12. data/ext/libcouchbase/src/auth.cc +0 -4
  13. data/ext/libcouchbase/src/cntl.cc +11 -1
  14. data/ext/libcouchbase/src/connspec.cc +18 -0
  15. data/ext/libcouchbase/src/connspec.h +10 -0
  16. data/ext/libcouchbase/src/dns-srv.cc +13 -14
  17. data/ext/libcouchbase/src/errmap.cc +107 -0
  18. data/ext/libcouchbase/src/errmap.h +113 -0
  19. data/ext/libcouchbase/src/hostlist.cc +0 -35
  20. data/ext/libcouchbase/src/hostlist.h +38 -64
  21. data/ext/libcouchbase/src/http/http.cc +6 -1
  22. data/ext/libcouchbase/src/instance.cc +1 -1
  23. data/ext/libcouchbase/src/internal.h +10 -0
  24. data/ext/libcouchbase/src/mcserver/mcserver.cc +119 -3
  25. data/ext/libcouchbase/src/mcserver/mcserver.h +3 -1
  26. data/ext/libcouchbase/src/mcserver/negotiate.cc +130 -37
  27. data/ext/libcouchbase/src/nodeinfo.cc +1 -1
  28. data/ext/libcouchbase/src/settings.c +3 -0
  29. data/ext/libcouchbase/src/settings.h +5 -0
  30. data/ext/libcouchbase/src/ssl/ssl_common.c +2 -0
  31. data/ext/libcouchbase/tests/basic/t_host.cc +67 -75
  32. data/ext/libcouchbase/tests/iotests/mock-environment.h +2 -1
  33. data/ext/libcouchbase/tests/iotests/t_confmon.cc +3 -4
  34. data/ext/libcouchbase/tests/iotests/t_errmap.cc +97 -0
  35. data/lib/libcouchbase/bucket.rb +27 -12
  36. data/lib/libcouchbase/callbacks.rb +1 -1
  37. data/lib/libcouchbase/connection.rb +18 -5
  38. data/lib/libcouchbase/version.rb +1 -1
  39. data/spec/connection_spec.rb +1 -1
  40. metadata +5 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b7528bfbb566a80d2229384ddb803404ddd397fb
4
- data.tar.gz: 4f88409cda5903afc7e2ee5904dc6a03707e225a
3
+ metadata.gz: a694a8d99cf0101482777db2e8c4f81c9a2e3575
4
+ data.tar.gz: 3b484eb067a3ba40c9bf9b852cac90f48616db62
5
5
  SHA512:
6
- metadata.gz: 2052657011535ae443555d9724776a0a62d7fae10b589404baacd8a28d8cd70fe66a8715581eb1f19fef7d4da52807c2a77941cd95e6fb9f87b612774ee2b7fc
7
- data.tar.gz: caed84a246ae8747a5e777f6f7c4dbb7da623e1b53aa4557445dcba2e0041fe2724b67977ece54bed5f0313eef1619fb77acdcb1a4267bac059295dbd79e69cc
6
+ metadata.gz: 3cf8f41d050d5bbb1ff2337de189c8893f36bae402c687d9543e1f996a327610e6f8d6ca7f84cc2cec0e27e8e958d3bb0e5ee05acee4101f70082a7ffaa12e83
7
+ data.tar.gz: bfeadf7d0eca8959258c9dccb64f03c6b5a9f4391da856d2ddcdc7aa60631421cb0f37f332809a93e69c6516b364c4b6e553d1f5a8eb76281ebe1c383a45f6d6
data/.travis.yml CHANGED
@@ -3,10 +3,10 @@ rvm:
3
3
  - ruby-2.3.1
4
4
  - ruby-2.2.5
5
5
  - ruby-head
6
- - rubinius-3.62
7
- - rubinius
8
6
  - jruby-9.1.5.0
9
7
  - jruby-head
8
+ - rubinius
9
+ # - rubinius-3.62 # blocked by https://github.com/rubinius/rubinius/issues/3706
10
10
  branches:
11
11
  only:
12
12
  - master
@@ -14,8 +14,8 @@ before_install:
14
14
  - git submodule update --init --recursive
15
15
  - gem install ffi
16
16
  - sudo apt-get install libev-dev
17
- - sudo wget http://packages.couchbase.com/releases/4.5.1/couchbase-server-enterprise_4.5.1-ubuntu14.04_amd64.deb
18
- - sudo dpkg -i couchbase-server-enterprise_4.5.1-ubuntu14.04_amd64.deb
17
+ - sudo wget https://packages.couchbase.com/releases/4.6.1/couchbase-server-enterprise_4.6.1-ubuntu14.04_amd64.deb
18
+ - sudo dpkg -i couchbase-server-enterprise_4.6.1-ubuntu14.04_amd64.deb
19
19
  - sleep 4
20
20
  - sudo service couchbase-server status
21
21
  - /opt/couchbase/bin/couchbase-cli cluster-init -c 127.0.0.1:8091 --cluster-username=admin --cluster-password=password --cluster-ramsize=320 --cluster-index-ramsize=256 --cluster-fts-ramsize=256 --services=data,index,query,fts
data/README.md CHANGED
@@ -1,10 +1,14 @@
1
1
  # libcouchbase FFI bindings for Ruby
2
2
 
3
+ [![Build Status](https://secure.travis-ci.org/cotag/libcouchbase.svg)](http://travis-ci.org/cotag/libcouchbase)
4
+
3
5
  An alternative to the official [couchbase-client](https://github.com/couchbase/couchbase-ruby-client)
4
6
 
5
7
  * This client is non-blocking where possible using Fibers, which makes it simple to write performant code in Frameworks like [Rails](http://rubyonrails.org/).
6
8
  * Client is threadsafe and reentrant
7
9
 
10
+ This is a low level wrapper around libcouchbase. For a more friendly ActiveModel interface see [couchbase-orm](https://github.com/acaprojects/couchbase-orm)
11
+
8
12
 
9
13
  ## Runtime Support:
10
14
 
@@ -21,7 +21,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8.9)
21
21
  # These variables can be modified as needed
22
22
 
23
23
  # Couchbase mock path to download
24
- SET(COUCHBASE_MOCK_VERSION CouchbaseMock-1.4.3.jar)
24
+ SET(COUCHBASE_MOCK_VERSION CouchbaseMock-1.4.7.jar)
25
25
  # Maven repository where ${COUCHBASE_MOCK_VERSION} is to be found
26
26
  SET(COUCHBASE_MOCK_DLSERVER http://packages.couchbase.com/clients/c/mock)
27
27
  project(libcouchbase)
@@ -1,5 +1,47 @@
1
1
  # Release Notes
2
2
 
3
+ ## 2.7.3 (March 21 2017)
4
+
5
+ * Provide the ability to send the `SELECT_BUCKET` when establishing a
6
+ to a server. This is a building block allowing us to use 'RBAC'/username
7
+ auth in the future.
8
+ Note that this requires the `select_bucket=true` option in the connection
9
+ string or equivalent, and that this feature as a whole is considered
10
+ experimental.
11
+ * Priority: Major
12
+ * Issues: [CCBC-758](https://issues.couchbase.com/browse/CCBC-758)
13
+
14
+ * Provide an option to disable DNS-SRV lookups. Because DNS SRV lookups often
15
+ result in no result (i.e. `NXDOMAIN`) - which takes longer, allowing to
16
+ disable such lookups may speed up startup time.
17
+ This option is available via the connection string, using `dnssrv=off`
18
+ * Priority: Minor
19
+ * Issues: [CCBC-756](https://issues.couchbase.com/browse/CCBC-756)
20
+
21
+ * Send client/user-specific identifier in `User-Agent` HTTP header.
22
+ The library already does this for data nodes (Memcached). Using it in HTTP
23
+ services allows better supportability when diagnosing issues by reading the
24
+ HTTP logs.
25
+ * Priority: Major
26
+ * Issues: [CCBC-755](https://issues.couchbase.com/browse/CCBC-755)
27
+
28
+ * Fix bug where DNS SRV hostnames would not be used.
29
+ While DNS SRV lookup was working, the library would not actually attempt
30
+ bootstrap off those received hostnames.
31
+ * Priority: Major
32
+ * Issues: [CCBC-753](https://issues.couchbase.com/browse/CCBC-753)
33
+
34
+ * Provide experimental Analytics support.
35
+ This allows access to the Couchbase Analytics Service, available in
36
+ some pre-release builds. API and syntax wise, Analytics is very similar
37
+ to N1QL.
38
+ To use the analytics service, set the `LCB_CMDN1QL_F_CBASQUERY` bit in
39
+ `lcb_CMDN1QL::cmdflags`, and provide the appropriate _host:port_ combination
40
+ in the `lcb_CMDN1QL::host` field. - Currently, analytics support is not
41
+ used in the cluster map/configuration.
42
+ * Priority: Major
43
+ * Issues: [CCBC-734](https://issues.couchbase.com/browse/CCBC-734)
44
+
3
45
  ## 2.7.2 (February 21 2017)
4
46
 
5
47
  This release consists of additional internal refactoring and some improved
@@ -42,13 +42,13 @@ ENDIF()
42
42
 
43
43
  IF (NOT LCB_VERSION)
44
44
  SET(LCB_NOGITVERSION ON)
45
- SET(LCB_VERSION "2.7.2")
45
+ SET(LCB_VERSION "2.7.3")
46
46
  ENDIF()
47
47
  IF (NOT LCB_VERSION_CHANGESET)
48
48
  SET(LCB_VERSION_CHANGESET "0xdeadbeef")
49
49
  ENDIF()
50
50
  IF (NOT LCB_VERSION_HEX)
51
- SET(LCB_VERSION_HEX 0x020702)
51
+ SET(LCB_VERSION_HEX 0x020703)
52
52
  ENDIF()
53
53
 
54
54
  # Now parse the version string
@@ -63,7 +63,7 @@ IF(APPLE)
63
63
  ELSE()
64
64
  SET(LCB_SONAME_MAJOR "2")
65
65
  ENDIF()
66
- SET(LCB_SONAME_FULL "${LCB_SONAME_MAJOR}.0.42")
66
+ SET(LCB_SONAME_FULL "${LCB_SONAME_MAJOR}.0.43")
67
67
 
68
68
  MESSAGE(STATUS
69
69
  "libcouchbase ${LCB_VERSION_MAJOR},${LCB_VERSION_MINOR},${LCB_VERSION_PATCH}")
@@ -57,6 +57,7 @@ SET(LCB_CORE_CXXSRC
57
57
  src/connspec.cc
58
58
  src/dns-srv.cc
59
59
  src/dump.cc
60
+ src/errmap.cc
60
61
  src/getconfig.cc
61
62
  src/nodeinfo.cc
62
63
  src/handler.cc
@@ -924,8 +924,34 @@ typedef const char *lcb_BUCKETCRED[2];
924
924
  */
925
925
  #define LCB_CNTL_READ_CHUNKSIZE 0x42
926
926
 
927
+ /**
928
+ * Enable/Disable the Error Map feature. This is disabled by default.
929
+ * Works only on servers which support error map
930
+ *
931
+ * Use `enable_errmap` in the connection string
932
+ *
933
+ * @volatile
934
+ * @cntl_arg_both{int* (as boolean)}
935
+ */
936
+ #define LCB_CNTL_ENABLE_ERRMAP 0x43
937
+
938
+ /**
939
+ * Enable/Disable sending the SELECT_BUCKET command after authentication.
940
+ * This is useful to test auth, and should not be set by end-users.
941
+ *
942
+ * Note that even if this feature is enabled (the default), the client will
943
+ * only send `SELECT_BUCKET` if the server indicates that it is supported
944
+ * during negotiation.
945
+ *
946
+ * Use `select_bucket` in the connection string
947
+ *
948
+ * @volatile
949
+ * @cntl_arg_both{int* (as boolean)}
950
+ */
951
+ #define LCB_CNTL_SELECT_BUCKET 0x44
952
+
927
953
  /** This is not a command, but rather an indicator of the last item */
928
- #define LCB_CNTL__MAX 0x43
954
+ #define LCB_CNTL__MAX 0x45
929
955
  /**@}*/
930
956
 
931
957
  #ifdef __cplusplus
@@ -3679,16 +3679,6 @@ lcb_histogram_read(const lcb_HISTOGRAM *hg, const void *cookie,
3679
3679
  LCB_INTERNAL_API
3680
3680
  void lcb_histogram_print(lcb_HISTOGRAM* hg, FILE* stream);
3681
3681
 
3682
- struct hostlist_st;
3683
-
3684
- LCB_INTERNAL_API
3685
- lcb_error_t
3686
- lcb_dnssrv_query(const char *, struct hostlist_st*);
3687
-
3688
- LCB_INTERNAL_API
3689
- struct hostlist_st*
3690
- lcb_dnssrv_getbslist(const char *, int, lcb_error_t*);
3691
-
3692
3682
  /* Post-include some other headers */
3693
3683
  #ifdef __cplusplus
3694
3684
  }
@@ -502,7 +502,14 @@ typedef enum {
502
502
  X(LCB_UNKNOWN_SDCMD, 0x4D, LCB_ERRTYPE_INPUT, "Unknown subdocument command") \
503
503
  X(LCB_ENO_COMMANDS, 0x4E, LCB_ERRTYPE_INPUT, "No commands specified") \
504
504
  X(LCB_QUERY_ERROR, 0x4F, LCB_ERRTYPE_SRVGEN, \
505
- "Query execution failed. Inspect raw response object for information")
505
+ "Query execution failed. Inspect raw response object for information") \
506
+ \
507
+ X(LCB_GENERIC_TMPERR, 0x50, LCB_ERRTYPE_TRANSIENT|LCB_ERRTYPE_SRVGEN, \
508
+ "Generic temporary error received from server") \
509
+ X(LCB_GENERIC_SUBDOCERR, 0x51, LCB_ERRTYPE_SUBDOC|LCB_ERRTYPE_SRVGEN, \
510
+ "Generic subdocument error received from server") \
511
+ X(LCB_GENERIC_CONSTRAINT_ERR, 0x52, LCB_ERRTYPE_INPUT|LCB_ERRTYPE_SRVGEN, \
512
+ "Generic constraint error received from server")
506
513
 
507
514
  /** Error codes returned by the library. */
508
515
  typedef enum {
@@ -224,6 +224,8 @@ extern "C"
224
224
 
225
225
  PROTOCOL_BINARY_CMD_GET_REPLICA = 0x83,
226
226
 
227
+ PROTOCOL_BINARY_CMD_SELECT_BUCKET = 0x89,
228
+
227
229
  PROTOCOL_BINARY_CMD_OBSERVE_SEQNO = 0x91,
228
230
  PROTOCOL_BINARY_CMD_OBSERVE = 0x92,
229
231
 
@@ -264,6 +266,9 @@ extern "C"
264
266
  /* Subdoc additions for Spock: */
265
267
  PROTOCOL_BINARY_CMD_SUBDOC_GET_COUNT = 0xd2,
266
268
 
269
+ /* get error code mappings */
270
+ PROTOCOL_BINARY_CMD_GET_ERROR_MAP = 0xfe,
271
+
267
272
  /* Reserved for being able to signal invalid opcode */
268
273
  PROTOCOL_BINARY_CMD_INVALID = 0xff
269
274
  } protocol_binary_command;
@@ -665,11 +670,13 @@ extern "C"
665
670
  PROTOCOL_BINARY_FEATURE_TCPNODELAY = 0x03,
666
671
  PROTOCOL_BINARY_FEATURE_MUTATION_SEQNO = 0x04,
667
672
  PROTOCOL_BINARY_FEATURE_TCPDELAY = 0x05,
668
- PROTOCOL_BINARY_FEATURE_XATTR = 0x06
673
+ PROTOCOL_BINARY_FEATURE_XATTR = 0x06,
674
+ PROTOCOL_BINARY_FEATURE_XERROR = 0x07,
675
+ PROTOCOL_BINARY_FEATURE_SELECT_BUCKET = 0x08
669
676
  } protocol_binary_hello_features;
670
677
 
671
678
  #define MEMCACHED_FIRST_HELLO_FEATURE 0x01
672
- #define MEMCACHED_TOTAL_HELLO_FEATURES 0x05
679
+ #define MEMCACHED_TOTAL_HELLO_FEATURES 10
673
680
 
674
681
  #define protocol_feature_2_text(a) \
675
682
  (a == PROTOCOL_BINARY_FEATURE_DATATYPE) ? "Datatype" : \
@@ -677,7 +684,9 @@ extern "C"
677
684
  (a == PROTOCOL_BINARY_FEATURE_TCPNODELAY) ? "TCP NODELAY" : \
678
685
  (a == PROTOCOL_BINARY_FEATURE_MUTATION_SEQNO) ? "Mutation seqno" : \
679
686
  (a == PROTOCOL_BINARY_FEATURE_TCPDELAY) ? "TCP DELAY" : \
680
- (a == PROTOCOL_BINARY_FEATURE_XATTR) ? "XATTR" : "Unknown"
687
+ (a == PROTOCOL_BINARY_FEATURE_XATTR) ? "XATTR" : \
688
+ (a == PROTOCOL_BINARY_FEATURE_XERROR) ? "Error Map": \
689
+ (a == PROTOCOL_BINARY_FEATURE_SELECT_BUCKET) ? "Select Bucket": "Unknown"
681
690
 
682
691
  /**
683
692
  * The HELLO command is used by the client and the server to agree
@@ -90,10 +90,6 @@ Authenticator::init(const std::string& username_, const std::string& bucket,
90
90
  m_username = (!username_.empty()) ? username_ : bucket;
91
91
  m_password = passwd;
92
92
 
93
- if (conntype == LCB_TYPE_BUCKET && m_username != bucket) {
94
- return LCB_INVALID_USERNAME;
95
- }
96
-
97
93
  m_buckets[bucket] = m_password;
98
94
  return LCB_SUCCESS;
99
95
  }
@@ -183,6 +183,12 @@ HANDLER(kv_hg_handler) {
183
183
  HANDLER(read_chunk_size_handler) {
184
184
  RETURN_GET_SET(lcb_U32, LCBT_SETTING(instance, read_chunk_size));
185
185
  }
186
+ HANDLER(enable_errmap_handler) {
187
+ RETURN_GET_SET(int, LCBT_SETTING(instance, use_errmap));
188
+ }
189
+ HANDLER(select_bucket_handler) {
190
+ RETURN_GET_SET(int, LCBT_SETTING(instance, select_bucket));
191
+ }
186
192
 
187
193
  HANDLER(get_kvb) {
188
194
  lcb_cntl_vbinfo_st *vbi = reinterpret_cast<lcb_cntl_vbinfo_st*>(arg);
@@ -586,7 +592,9 @@ static ctl_handler handlers[] = {
586
592
  client_string_handler, /* LCB_CNTL_CLIENT_STRING */
587
593
  bucket_auth_handler, /* LCB_CNTL_BUCKET_CRED */
588
594
  timeout_common, /* LCB_CNTL_RETRY_NMV_DELAY */
589
- read_chunk_size_handler /*LCB_CNTL_READ_CHUNKSIZE */
595
+ read_chunk_size_handler, /*LCB_CNTL_READ_CHUNKSIZE */
596
+ enable_errmap_handler, /* LCB_CNTL_ENABLE_ERRMAP */
597
+ select_bucket_handler /* LCB_CNTL_SELECT_BUCKET */
590
598
  };
591
599
 
592
600
  /* Union used for conversion to/from string functions */
@@ -738,6 +746,8 @@ static cntl_OPCODESTRS stropcode_map[] = {
738
746
  {"retry_nmv_delay", LCB_CNTL_RETRY_NMV_INTERVAL, convert_timeout},
739
747
  {"bucket_cred", LCB_CNTL_BUCKET_CRED, NULL},
740
748
  {"read_chunk_size", LCB_CNTL_READ_CHUNKSIZE, convert_u32},
749
+ {"enable_errmap", LCB_CNTL_ENABLE_ERRMAP, convert_intbool},
750
+ {"select_bucket", LCB_CNTL_SELECT_BUCKET, convert_intbool},
741
751
  {NULL, -1}
742
752
  };
743
753
 
@@ -244,6 +244,24 @@ Connspec::parse_options(
244
244
  if (sscanf(value, "%d", &m_loglevel) != 1) {
245
245
  SET_ERROR("console_log_level must be a numeric value");
246
246
  }
247
+ } else if (!strcmp(key, "dnssrv")) {
248
+ if ((m_flags & F_DNSSRV_EXPLICIT) == F_DNSSRV_EXPLICIT) {
249
+ SET_ERROR("Cannot use dnssrv scheme with dnssrv option");
250
+ }
251
+ int btmp = 0;
252
+ if (!strcmp(value, "on") || !strcmp(value, "true")) {
253
+ btmp = 1;
254
+ } else if (!strcmp(value, "off") || !strcmp(value, "false")) {
255
+ btmp = 0;
256
+ } else if (sscanf(value, "%d", &btmp) != 1) {
257
+ printf("Coldn't parse value!\n");
258
+ SET_ERROR("dnssrv must have numeric (boolean) value");
259
+ }
260
+ if (btmp) {
261
+ m_flags |= F_DNSSRV;
262
+ } else {
263
+ m_flags &= ~F_DNSSRV_EXPLICIT;
264
+ }
247
265
  } else {
248
266
  m_ctlopts.push_back(std::make_pair(key, value));
249
267
  }
@@ -20,9 +20,11 @@
20
20
 
21
21
  #include <libcouchbase/couchbase.h>
22
22
  #include "config.h"
23
+
23
24
  #include <string>
24
25
  #include <vector>
25
26
  #include <set>
27
+ #include "hostlist.h"
26
28
 
27
29
  #ifdef _MSC_VER
28
30
  /*
@@ -126,6 +128,14 @@ private:
126
128
  #define LCB_SPECSCHEME_MCCOMPAT "memcached://"
127
129
  #define LCB_SPECSCHEME_SRV "couchbase+dnssrv://"
128
130
  #define LCB_SPECSCHEME_SRV_SSL "couchbases+dnssrv://"
131
+
132
+ // Standalone functionality:
133
+ lcb_error_t
134
+ dnssrv_query(const char *name, Hostlist& hostlist);
135
+
136
+ Hostlist *
137
+ dnssrv_getbslist(const char *addr, bool is_ssl, lcb_error_t& errout);
138
+
129
139
  } // namespace
130
140
 
131
141
  #endif
@@ -2,6 +2,8 @@
2
2
 
3
3
  #include "config.h"
4
4
  #include "hostlist.h"
5
+ #include "connspec.h"
6
+ #include "hostlist.h"
5
7
 
6
8
  #ifndef _WIN32
7
9
  #include <string>
@@ -20,9 +22,8 @@
20
22
  #include <netinet/in.h>
21
23
  #include <resolv.h>
22
24
 
23
- LCB_INTERNAL_API
24
25
  lcb_error_t
25
- lcb_dnssrv_query(const char *name, hostlist_t hostlist)
26
+ lcb::dnssrv_query(const char* name, lcb::Hostlist& hostlist)
26
27
  {
27
28
  ns_msg msg;
28
29
 
@@ -82,7 +83,7 @@ lcb_dnssrv_query(const char *name, hostlist_t hostlist)
82
83
  ns_name_uncompress(
83
84
  ns_msg_base(msg), ns_msg_end(msg),
84
85
  rdata, &dname[0], NS_MAXDNAME);
85
- hostlist->add(&dname[0], srv_port);
86
+ hostlist.add(&dname[0], srv_port);
86
87
  }
87
88
  return LCB_SUCCESS;
88
89
  }
@@ -92,9 +93,8 @@ lcb_dnssrv_query(const char *name, hostlist_t hostlist)
92
93
  #include <windns.h>
93
94
  #define CAN_SRV_LOOKUP
94
95
  /* Implement via DnsQuery() */
95
- LCB_INTERNAL_API
96
96
  lcb_error_t
97
- lcb_dnssrv_query(const char *addr, hostlist_t hs)
97
+ lcb::dnssrv_query(const char *addr, Hostlist& hs)
98
98
  {
99
99
  DNS_STATUS status;
100
100
  PDNS_RECORDA root, cur;
@@ -108,7 +108,7 @@ lcb_dnssrv_query(const char *addr, hostlist_t hs)
108
108
  for (cur = root; cur; cur = cur->pNext) {
109
109
  // Use the ASCII version of the DNS lookup structure
110
110
  const DNS_SRV_DATAA *srv = &cur->Data.SRV;
111
- hostlist_add_stringz(hs, srv->pNameTarget, srv->wPort);
111
+ hs.add(srv->pNameTarget, srv->wPort);
112
112
  }
113
113
  DnsRecordListFree(root, DnsFreeRecordList);
114
114
  return LCB_SUCCESS;
@@ -118,7 +118,7 @@ lcb_dnssrv_query(const char *addr, hostlist_t hs)
118
118
 
119
119
 
120
120
  #ifndef CAN_SRV_LOOKUP
121
- LCB_INTERNAL_API lcb_error_t lcb_dnssrv_query(const char *, hostlist_t) {
121
+ lcb_error_t lcb::dnssrv_query(const char *, Hostlist&) {
122
122
  return LCB_CLIENT_FEATURE_UNAVAILABLE;
123
123
  }
124
124
  #endif
@@ -126,18 +126,17 @@ LCB_INTERNAL_API lcb_error_t lcb_dnssrv_query(const char *, hostlist_t) {
126
126
  #define SVCNAME_PLAIN "_couchbase._tcp."
127
127
  #define SVCNAME_SSL "_couchbases._tcp."
128
128
 
129
- LCB_INTERNAL_API
130
- hostlist_st*
131
- lcb_dnssrv_getbslist(const char *addr, int is_ssl, lcb_error_t *errp) {
129
+ lcb::Hostlist*
130
+ lcb::dnssrv_getbslist(const char *addr, bool is_ssl, lcb_error_t& errp) {
132
131
  std::string ss;
133
- lcb::Hostlist *ret = new lcb::Hostlist();
132
+ Hostlist *ret = new Hostlist();
134
133
  ss.append(is_ssl ? SVCNAME_SSL : SVCNAME_PLAIN);
135
134
  ss.append(addr);
136
135
 
137
- *errp = lcb_dnssrv_query(ss.c_str(), ret);
138
- if (*errp != LCB_SUCCESS) {
136
+ errp = dnssrv_query(ss.c_str(), *ret);
137
+ if (errp != LCB_SUCCESS) {
139
138
  delete ret;
140
139
  ret = NULL;
141
140
  }
142
- return static_cast<hostlist_st*>(ret);
141
+ return ret;
143
142
  }
@@ -0,0 +1,107 @@
1
+ #include "internal.h"
2
+ #include "errmap.h"
3
+ #include "contrib/lcb-jsoncpp/lcb-jsoncpp.h"
4
+
5
+ using namespace lcb::errmap;
6
+
7
+ ErrorMap::ErrorMap() : revision(0), version(0) {
8
+ }
9
+
10
+ static ErrorAttribute getAttribute(const std::string& s) {
11
+ #define X(c, s_) if (s == s_) { return c; }
12
+ LCB_XERRMAP_ATTRIBUTES(X)
13
+ #undef X
14
+ return INVALID_ATTRIBUTE;
15
+ }
16
+
17
+ const uint32_t ErrorMap::MAX_VERSION = 1;
18
+
19
+ ErrorMap::ParseStatus
20
+ ErrorMap::parse(const char *s, size_t n, std::string& errmsg) {
21
+ Json::Value root_nonconst;
22
+ Json::Reader reader;
23
+ if (!reader.parse(s, s + n, root_nonconst)) {
24
+ errmsg = "Invalid JSON";
25
+ return PARSE_ERROR;
26
+ }
27
+
28
+ const Json::Value& root = root_nonconst;
29
+ const Json::Value& verJson = root["version"];
30
+ if (!verJson.isNumeric()) {
31
+ errmsg = "'version' is not a number";
32
+ return PARSE_ERROR;
33
+ }
34
+
35
+ if (verJson.asUInt() > MAX_VERSION) {
36
+ errmsg = "'version' is unreasonably high";
37
+ return UNKNOWN_VERSION;
38
+ }
39
+
40
+ const Json::Value& revJson = root["revision"];
41
+ if (!revJson.isNumeric()) {
42
+ errmsg = "'revision' is not a number";
43
+ return PARSE_ERROR;
44
+ }
45
+
46
+ if (revJson.asUInt() <= revision) {
47
+ return NOT_UPDATED;
48
+ }
49
+
50
+ const Json::Value& errsJson = root["errors"];
51
+ if (!errsJson.isObject()) {
52
+ errmsg = "'errors' is not an object";
53
+ return PARSE_ERROR;
54
+ }
55
+
56
+ Json::Value::const_iterator ii = errsJson.begin();
57
+ for (; ii != errsJson.end(); ++ii) {
58
+ // Key is the version in hex
59
+ unsigned ec = 0;
60
+ if (sscanf(ii.key().asCString(), "%x", &ec) != 1) {
61
+ errmsg = "key " + ii.key().asString() + " is not a hex number";
62
+ return PARSE_ERROR;
63
+ }
64
+
65
+ const Json::Value& errorJson = *ii;
66
+
67
+ // Descend into the error attributes
68
+ Error error;
69
+ error.code = static_cast<uint16_t>(ec);
70
+
71
+ error.shortname = errorJson["name"].asString();
72
+ error.description = errorJson["desc"].asString();
73
+
74
+ const Json::Value& attrs = errorJson["attrs"];
75
+ if (!attrs.isArray()) {
76
+ errmsg = "'attrs' is not an array";
77
+ return PARSE_ERROR;
78
+ }
79
+
80
+ Json::Value::const_iterator jj = attrs.begin();
81
+ for (; jj != attrs.end(); ++jj) {
82
+ ErrorAttribute attr = getAttribute(jj->asString());
83
+ if (attr == INVALID_ATTRIBUTE) {
84
+ errmsg = "unknown attribute received";
85
+ return UNKNOWN_VERSION;
86
+ }
87
+ error.attributes.insert(attr);
88
+ }
89
+ errors.insert(MapType::value_type(ec, error));
90
+ }
91
+
92
+ return UPDATED;
93
+ }
94
+
95
+ const Error& ErrorMap::getError(uint16_t code) const {
96
+ static const Error invalid;
97
+ MapType::const_iterator it = errors.find(code);
98
+
99
+ if (it != errors.end()) {
100
+ return it->second;
101
+ } else {
102
+ return invalid;
103
+ }
104
+ }
105
+
106
+ ErrorMap *lcb_errmap_new() { return new ErrorMap(); }
107
+ void lcb_errmap_free(ErrorMap* m) { delete m; }