libcouchbase 0.0.9 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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; }