libcouchbase 0.3.3 → 1.0.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 (167) hide show
  1. checksums.yaml +4 -4
  2. data/ext/libcouchbase/CMakeLists.txt +6 -8
  3. data/ext/libcouchbase/README.markdown +2 -2
  4. data/ext/libcouchbase/RELEASE_NOTES.markdown +229 -2
  5. data/ext/libcouchbase/cmake/Modules/ConfigureDtrace.cmake +11 -0
  6. data/ext/libcouchbase/cmake/Modules/GenerateConfigDotH.cmake +18 -0
  7. data/ext/libcouchbase/cmake/Modules/GetLibcouchbaseFlags.cmake +3 -2
  8. data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +3 -3
  9. data/ext/libcouchbase/cmake/config-cmake.h.in +4 -0
  10. data/ext/libcouchbase/cmake/defs.mk.in +0 -2
  11. data/ext/libcouchbase/cmake/source_files.cmake +21 -5
  12. data/ext/libcouchbase/contrib/cJSON/cJSON.c +1 -1
  13. data/ext/libcouchbase/contrib/cbsasl/src/client.c +2 -0
  14. data/ext/libcouchbase/example/users/README +48 -0
  15. data/ext/libcouchbase/example/users/users.c +147 -0
  16. data/ext/libcouchbase/include/libcouchbase/auth.h +175 -31
  17. data/ext/libcouchbase/include/libcouchbase/cntl.h +82 -1
  18. data/ext/libcouchbase/include/libcouchbase/couchbase.h +45 -3
  19. data/ext/libcouchbase/include/libcouchbase/error.h +19 -1
  20. data/ext/libcouchbase/include/libcouchbase/iops.h +3 -0
  21. data/ext/libcouchbase/include/libcouchbase/n1ql.h +31 -1
  22. data/ext/libcouchbase/include/libcouchbase/plugins/io/bsdio-inl.c +4 -1
  23. data/ext/libcouchbase/include/libcouchbase/subdoc.h +36 -2
  24. data/ext/libcouchbase/include/libcouchbase/views.h +7 -1
  25. data/ext/libcouchbase/include/libcouchbase/visibility.h +1 -0
  26. data/ext/libcouchbase/include/memcached/protocol_binary.h +24 -1146
  27. data/ext/libcouchbase/packaging/parse-git-describe.pl +1 -1
  28. data/ext/libcouchbase/plugins/io/libev/libev_io_opts.h +3 -2
  29. data/ext/libcouchbase/src/README.md +0 -2
  30. data/ext/libcouchbase/src/auth-priv.h +23 -4
  31. data/ext/libcouchbase/src/auth.cc +51 -43
  32. data/ext/libcouchbase/src/bootstrap.cc +244 -0
  33. data/ext/libcouchbase/src/bootstrap.h +58 -38
  34. data/ext/libcouchbase/src/bucketconfig/bc_cccp.cc +120 -158
  35. data/ext/libcouchbase/src/bucketconfig/bc_file.cc +281 -0
  36. data/ext/libcouchbase/src/bucketconfig/bc_http.cc +526 -0
  37. data/ext/libcouchbase/src/bucketconfig/bc_http.h +50 -25
  38. data/ext/libcouchbase/src/bucketconfig/bc_static.cc +150 -0
  39. data/ext/libcouchbase/src/bucketconfig/clconfig.h +410 -386
  40. data/ext/libcouchbase/src/bucketconfig/confmon.cc +393 -0
  41. data/ext/libcouchbase/src/cbft.cc +22 -27
  42. data/ext/libcouchbase/src/cntl.cc +56 -22
  43. data/ext/libcouchbase/src/connspec.cc +47 -6
  44. data/ext/libcouchbase/src/connspec.h +27 -0
  45. data/ext/libcouchbase/src/dns-srv.cc +147 -0
  46. data/ext/libcouchbase/src/dump.cc +3 -3
  47. data/ext/libcouchbase/src/errmap.cc +173 -0
  48. data/ext/libcouchbase/src/errmap.h +198 -0
  49. data/ext/libcouchbase/src/getconfig.cc +7 -33
  50. data/ext/libcouchbase/src/handler.cc +118 -7
  51. data/ext/libcouchbase/src/hostlist.cc +0 -36
  52. data/ext/libcouchbase/src/hostlist.h +44 -62
  53. data/ext/libcouchbase/src/http/http-priv.h +125 -112
  54. data/ext/libcouchbase/src/http/http.cc +27 -35
  55. data/ext/libcouchbase/src/http/http.h +1 -34
  56. data/ext/libcouchbase/src/http/http_io.cc +28 -36
  57. data/ext/libcouchbase/src/instance.cc +131 -34
  58. data/ext/libcouchbase/src/internal.h +58 -26
  59. data/ext/libcouchbase/src/jsparse/parser.cc +136 -210
  60. data/ext/libcouchbase/src/jsparse/parser.h +84 -98
  61. data/ext/libcouchbase/src/lcbht/lcbht.cc +177 -0
  62. data/ext/libcouchbase/src/lcbht/lcbht.h +174 -163
  63. data/ext/libcouchbase/src/lcbio/connect.cc +569 -0
  64. data/ext/libcouchbase/src/lcbio/connect.h +16 -7
  65. data/ext/libcouchbase/src/lcbio/ctx.c +1 -1
  66. data/ext/libcouchbase/src/lcbio/iotable.h +101 -16
  67. data/ext/libcouchbase/src/lcbio/{ioutils.c → ioutils.cc} +30 -51
  68. data/ext/libcouchbase/src/lcbio/ioutils.h +29 -90
  69. data/ext/libcouchbase/src/lcbio/manager.cc +543 -0
  70. data/ext/libcouchbase/src/lcbio/manager.h +133 -96
  71. data/ext/libcouchbase/src/lcbio/protoctx.c +2 -2
  72. data/ext/libcouchbase/src/lcbio/timer-cxx.h +87 -0
  73. data/ext/libcouchbase/src/mc/mcreq.c +11 -2
  74. data/ext/libcouchbase/src/mc/mcreq.h +9 -2
  75. data/ext/libcouchbase/src/mcserver/mcserver.cc +175 -43
  76. data/ext/libcouchbase/src/mcserver/mcserver.h +9 -13
  77. data/ext/libcouchbase/src/mcserver/negotiate.cc +181 -62
  78. data/ext/libcouchbase/src/mcserver/negotiate.h +1 -3
  79. data/ext/libcouchbase/src/mctx-helper.h +51 -0
  80. data/ext/libcouchbase/src/n1ql/ixmgmt.cc +1 -2
  81. data/ext/libcouchbase/src/n1ql/n1ql.cc +74 -42
  82. data/ext/libcouchbase/src/netbuf/netbuf.c +4 -4
  83. data/ext/libcouchbase/src/newconfig.cc +6 -6
  84. data/ext/libcouchbase/src/nodeinfo.cc +2 -2
  85. data/ext/libcouchbase/src/operations/{cbflush.c → cbflush.cc} +7 -15
  86. data/ext/libcouchbase/src/operations/{counter.c → counter.cc} +0 -0
  87. data/ext/libcouchbase/src/operations/durability.cc +6 -26
  88. data/ext/libcouchbase/src/operations/durability_internal.h +6 -3
  89. data/ext/libcouchbase/src/operations/{get.c → get.cc} +24 -26
  90. data/ext/libcouchbase/src/operations/{observe.c → observe.cc} +68 -93
  91. data/ext/libcouchbase/src/operations/{pktfwd.c → pktfwd.cc} +0 -0
  92. data/ext/libcouchbase/src/operations/{remove.c → remove.cc} +0 -0
  93. data/ext/libcouchbase/src/operations/stats.cc +3 -8
  94. data/ext/libcouchbase/src/operations/{store.c → store.cc} +27 -32
  95. data/ext/libcouchbase/src/operations/subdoc.cc +129 -42
  96. data/ext/libcouchbase/src/operations/{touch.c → touch.cc} +0 -0
  97. data/ext/libcouchbase/src/packetutils.h +30 -2
  98. data/ext/libcouchbase/src/probes.d +1 -1
  99. data/ext/libcouchbase/src/rdb/rope.c +1 -1
  100. data/ext/libcouchbase/src/{retrychk.c → retrychk.cc} +2 -3
  101. data/ext/libcouchbase/src/retryq.cc +52 -14
  102. data/ext/libcouchbase/src/retryq.h +3 -3
  103. data/ext/libcouchbase/src/settings.c +5 -0
  104. data/ext/libcouchbase/src/settings.h +11 -0
  105. data/ext/libcouchbase/src/ssl/ssl_c.c +1 -0
  106. data/ext/libcouchbase/src/ssl/ssl_common.c +2 -0
  107. data/ext/libcouchbase/src/ssl/ssl_e.c +0 -1
  108. data/ext/libcouchbase/src/strcodecs/strcodecs.h +1 -1
  109. data/ext/libcouchbase/src/trace.h +4 -4
  110. data/ext/libcouchbase/src/vbucket/vbucket.c +6 -10
  111. data/ext/libcouchbase/src/views/{docreq.c → docreq.cc} +48 -54
  112. data/ext/libcouchbase/src/views/docreq.h +24 -30
  113. data/ext/libcouchbase/src/views/viewreq.cc +318 -0
  114. data/ext/libcouchbase/src/views/viewreq.h +43 -13
  115. data/ext/libcouchbase/tests/basic/t_connstr.cc +88 -50
  116. data/ext/libcouchbase/tests/basic/t_creds.cc +47 -5
  117. data/ext/libcouchbase/tests/basic/t_host.cc +67 -75
  118. data/ext/libcouchbase/tests/basic/t_jsparse.cc +27 -82
  119. data/ext/libcouchbase/tests/basic/t_misc.cc +1 -1
  120. data/ext/libcouchbase/tests/basic/t_n1qlstrings.cc +0 -1
  121. data/ext/libcouchbase/tests/htparse/t_basic.cc +58 -78
  122. data/ext/libcouchbase/tests/ioserver/connection.cc +1 -1
  123. data/ext/libcouchbase/tests/ioserver/ioserver.cc +19 -6
  124. data/ext/libcouchbase/tests/iotests/mock-environment.cc +28 -2
  125. data/ext/libcouchbase/tests/iotests/mock-environment.h +51 -1
  126. data/ext/libcouchbase/tests/iotests/t_behavior.cc +1 -7
  127. data/ext/libcouchbase/tests/iotests/t_confmon.cc +97 -115
  128. data/ext/libcouchbase/tests/iotests/t_durability.cc +0 -1
  129. data/ext/libcouchbase/tests/iotests/t_eerrs.cc +119 -0
  130. data/ext/libcouchbase/tests/iotests/t_errmap.cc +178 -0
  131. data/ext/libcouchbase/tests/iotests/t_misc.cc +3 -3
  132. data/ext/libcouchbase/tests/iotests/t_netfail.cc +1 -1
  133. data/ext/libcouchbase/tests/iotests/t_obseqno.cc +0 -1
  134. data/ext/libcouchbase/tests/iotests/t_subdoc.cc +18 -11
  135. data/ext/libcouchbase/tests/mc/t_alloc.cc +9 -9
  136. data/ext/libcouchbase/tests/socktests/socktest.cc +7 -10
  137. data/ext/libcouchbase/tests/socktests/socktest.h +2 -3
  138. data/ext/libcouchbase/tests/socktests/t_basic.cc +6 -6
  139. data/ext/libcouchbase/tests/socktests/t_manager.cc +5 -6
  140. data/ext/libcouchbase/tests/socktests/t_ssl.cc +1 -1
  141. data/ext/libcouchbase/tests/vbucket/confdata/ketama_expected.json +2562 -0
  142. data/ext/libcouchbase/tests/vbucket/confdata/memd_ketama_config.json +31 -0
  143. data/ext/libcouchbase/tests/vbucket/t_config.cc +35 -5
  144. data/ext/libcouchbase/tools/CMakeLists.txt +2 -2
  145. data/ext/libcouchbase/tools/cbc-handlers.h +128 -0
  146. data/ext/libcouchbase/tools/cbc-n1qlback.cc +64 -10
  147. data/ext/libcouchbase/tools/cbc-pillowfight.cc +2 -2
  148. data/ext/libcouchbase/tools/cbc.cc +143 -10
  149. data/ext/libcouchbase/tools/docgen/loc.h +1 -1
  150. data/lib/libcouchbase/connection.rb +4 -3
  151. data/lib/libcouchbase/version.rb +1 -1
  152. metadata +37 -28
  153. data/ext/libcouchbase/include/memcached/vbucket.h +0 -42
  154. data/ext/libcouchbase/src/bootstrap.c +0 -269
  155. data/ext/libcouchbase/src/bucketconfig/bc_file.c +0 -347
  156. data/ext/libcouchbase/src/bucketconfig/bc_http.c +0 -630
  157. data/ext/libcouchbase/src/bucketconfig/bc_mcraw.c +0 -150
  158. data/ext/libcouchbase/src/bucketconfig/confmon.c +0 -474
  159. data/ext/libcouchbase/src/lcbht/lcbht.c +0 -282
  160. data/ext/libcouchbase/src/lcbio/connect.c +0 -557
  161. data/ext/libcouchbase/src/lcbio/manager.c +0 -584
  162. data/ext/libcouchbase/src/packetutils.c +0 -37
  163. data/ext/libcouchbase/src/simplestring.c +0 -211
  164. data/ext/libcouchbase/src/simplestring.h +0 -228
  165. data/ext/libcouchbase/src/ssobuf.h +0 -82
  166. data/ext/libcouchbase/src/views/viewreq.c +0 -358
  167. data/ext/libcouchbase/tests/basic/t_string.cc +0 -112
@@ -2,14 +2,6 @@
2
2
  #include "connspec.h"
3
3
  using namespace lcb;
4
4
 
5
- static lcb_error_t lcb_connspec_parse(const char *connstr, Connspec *spec, const char **errmsg)
6
- {
7
- return spec->parse(connstr, errmsg);
8
- }
9
- static lcb_error_t lcb_connspec_convert(Connspec *spec, const lcb_create_st *cropts)
10
- {
11
- return spec->load(*cropts);
12
- }
13
5
  static size_t countHosts(const Connspec *spec) {
14
6
  return spec->hosts().size();
15
7
  }
@@ -110,7 +102,7 @@ TEST_F(ConnstrTest, testParseBasic)
110
102
  ASSERT_EQ(LCB_CONFIG_HTTP_PORT, params.default_port());
111
103
 
112
104
  reinit();
113
- err = lcb_connspec_parse("1.2.3.4:999", &params, &errmsg);
105
+ err = params.parse("1.2.3.4:999", &errmsg);
114
106
  ASSERT_EQ(1, countHosts(&params));
115
107
  tmphost = findHost(&params, "1.2.3.4");
116
108
  ASSERT_FALSE(tmphost == NULL);
@@ -122,7 +114,7 @@ TEST_F(ConnstrTest, testParseBasic)
122
114
  TEST_F(ConnstrTest, testParseHosts)
123
115
  {
124
116
  lcb_error_t err;
125
- err = lcb_connspec_parse("couchbase://foo.com,bar.com,baz.com", &params, &errmsg);
117
+ err = params.parse("couchbase://foo.com,bar.com,baz.com", &errmsg);
126
118
  ASSERT_EQ(3, countHosts(&params));
127
119
  ASSERT_FALSE(NULL == findHost(&params, "foo.com"));
128
120
  ASSERT_FALSE(NULL == findHost(&params, "bar.com"));
@@ -130,7 +122,7 @@ TEST_F(ConnstrTest, testParseHosts)
130
122
 
131
123
  // Parse with 'legacy' format
132
124
  reinit();
133
- err = lcb_connspec_parse("couchbase://foo.com:8091", &params, &errmsg);
125
+ err = params.parse("couchbase://foo.com:8091", &errmsg);
134
126
  ASSERT_EQ(LCB_SUCCESS, err);
135
127
  const Spechost *dh = findHost(&params, "foo.com");
136
128
  ASSERT_FALSE(NULL == dh);
@@ -141,14 +133,14 @@ TEST_F(ConnstrTest, testParseHosts)
141
133
 
142
134
  // parse with invalid port, without specifying protocol
143
135
  reinit();
144
- err = lcb_connspec_parse("couchbase://foo.com:4444", &params, &errmsg);
136
+ err = params.parse("couchbase://foo.com:4444", &errmsg);
145
137
  ASSERT_EQ(LCB_SUCCESS, err);
146
138
  dh = findHost(&params, "foo.com");
147
139
  ASSERT_EQ(4444, dh->port);
148
140
  ASSERT_TRUE(dh->isMCD());
149
141
 
150
142
  reinit();
151
- err = lcb_connspec_parse("couchbases://foo.com:4444", &params, &errmsg);
143
+ err = params.parse("couchbases://foo.com:4444", &errmsg);
152
144
  ASSERT_EQ(LCB_SUCCESS, err);
153
145
  dh = findHost(&params, "foo.com");
154
146
  ASSERT_EQ(LCB_SSL_ENABLED, params.sslopts());
@@ -157,7 +149,7 @@ TEST_F(ConnstrTest, testParseHosts)
157
149
 
158
150
  // Parse with recognized format
159
151
  reinit();
160
- err = lcb_connspec_parse("couchbase://foo.com:4444=mcd", &params, &errmsg);
152
+ err = params.parse("couchbase://foo.com:4444=mcd", &errmsg);
161
153
  ASSERT_EQ(LCB_SUCCESS, err);
162
154
  dh = findHost(&params, "foo.com");
163
155
  ASSERT_EQ("foo.com", dh->hostname);
@@ -166,8 +158,7 @@ TEST_F(ConnstrTest, testParseHosts)
166
158
 
167
159
  //Parse multiple hosts with ports
168
160
  reinit();
169
- err = lcb_connspec_parse("couchbase://foo.com:4444=mcd,bar.com:5555=mcd",
170
- &params, &errmsg);
161
+ err = params.parse("couchbase://foo.com:4444=mcd,bar.com:5555=mcd", &errmsg);
171
162
  ASSERT_EQ(LCB_SUCCESS, err);
172
163
 
173
164
  dh = findHost(&params, "foo.com");
@@ -183,7 +174,7 @@ TEST_F(ConnstrTest, testParseHosts)
183
174
  ASSERT_TRUE(dh->isMCD());
184
175
 
185
176
  reinit();
186
- err = lcb_connspec_parse("couchbase://foo.com,bar.com:4444", &params, &errmsg);
177
+ err = params.parse("couchbase://foo.com,bar.com:4444", &errmsg);
187
178
  ASSERT_EQ(LCB_SUCCESS, err);
188
179
  dh = findHost(&params, "bar.com");
189
180
  ASSERT_EQ(4444, dh->port);
@@ -192,7 +183,7 @@ TEST_F(ConnstrTest, testParseHosts)
192
183
  ASSERT_TRUE(dh->isTypeless());
193
184
 
194
185
  reinit();
195
- err = lcb_connspec_parse("couchbase://foo.com;bar.com;baz.com", &params, &errmsg);
186
+ err = params.parse("couchbase://foo.com;bar.com;baz.com", &errmsg);
196
187
  ASSERT_EQ(LCB_SUCCESS, err) << "Can parse old-style semicolons";
197
188
  ASSERT_EQ(3, countHosts(&params));
198
189
  ASSERT_FALSE(NULL == findHost(&params, "foo.com"));
@@ -203,27 +194,27 @@ TEST_F(ConnstrTest, testParseHosts)
203
194
  TEST_F(ConnstrTest, testParseBucket)
204
195
  {
205
196
  lcb_error_t err;
206
- err = lcb_connspec_parse("couchbase://foo.com/user", &params, &errmsg);
197
+ err = params.parse("couchbase://foo.com/user", &errmsg);
207
198
  ASSERT_EQ(LCB_SUCCESS, err);
208
199
  ASSERT_EQ("user", params.bucket()) << "Basic bucket parse";
209
200
 
210
201
  reinit();
211
- err = lcb_connspec_parse("couchbase://foo.com/user/", &params, &errmsg);
202
+ err = params.parse("couchbase://foo.com/user/", &errmsg);
212
203
  ASSERT_EQ(LCB_SUCCESS, err) << "Bucket can have a slash";
213
204
  // We can have a bucket using a slash
214
205
 
215
206
  reinit();
216
- err = lcb_connspec_parse("couchbase:///default", &params, &errmsg);
207
+ err = params.parse("couchbase:///default", &errmsg);
217
208
  ASSERT_EQ(LCB_SUCCESS, err) << "Bucket without host OK";
218
209
  ASSERT_EQ("default", params.bucket());
219
210
 
220
211
  reinit();
221
- err = lcb_connspec_parse("couchbase:///default?", &params, &errmsg);
212
+ err = params.parse("couchbase:///default?", &errmsg);
222
213
  ASSERT_EQ(LCB_SUCCESS, err);
223
214
  ASSERT_EQ("default", params.bucket());
224
215
 
225
216
  reinit();
226
- err = lcb_connspec_parse("couchbase:///%2FUsers%2F?", &params, &errmsg);
217
+ err = params.parse("couchbase:///%2FUsers%2F?", &errmsg);
227
218
  ASSERT_EQ(LCB_SUCCESS, err);
228
219
  ASSERT_EQ("/Users/", params.bucket());
229
220
  }
@@ -231,7 +222,7 @@ TEST_F(ConnstrTest, testParseBucket)
231
222
  TEST_F(ConnstrTest, testOptionsPassthrough)
232
223
  {
233
224
  lcb_error_t err;
234
- err = lcb_connspec_parse("couchbase://?foo=bar", &params, &errmsg);
225
+ err = params.parse("couchbase://?foo=bar", &errmsg);
235
226
  ASSERT_EQ(LCB_SUCCESS, err) << "Options only";
236
227
  ASSERT_FALSE(params.options().empty());
237
228
  ASSERT_NE(0, params.options().size());
@@ -241,19 +232,19 @@ TEST_F(ConnstrTest, testOptionsPassthrough)
241
232
  ASSERT_EQ("bar", op.value);
242
233
 
243
234
  reinit();
244
- err = lcb_connspec_parse("couchbase://?foo=bar", &params, &errmsg);
235
+ err = params.parse("couchbase://?foo=bar", &errmsg);
245
236
  ASSERT_EQ(LCB_SUCCESS, err);
246
237
  ASSERT_TRUE(findOption(&params, "foo", op));
247
238
  ASSERT_EQ("bar", op.value);
248
239
 
249
240
  reinit();
250
- err = lcb_connspec_parse("couchbase://?foo", &params, &errmsg);
241
+ err = params.parse("couchbase://?foo", &errmsg);
251
242
  ASSERT_NE(LCB_SUCCESS, err) << "Option without value";
252
243
 
253
244
 
254
245
  // Multiple options
255
246
  reinit();
256
- err = lcb_connspec_parse("couchbase://?foo=fooval&bar=barval", &params, &errmsg);
247
+ err = params.parse("couchbase://?foo=fooval&bar=barval", &errmsg);
257
248
  ASSERT_EQ(LCB_SUCCESS, err);
258
249
  ASSERT_TRUE(findOption(&params, "foo", op));
259
250
  ASSERT_EQ("fooval", op.value);
@@ -262,20 +253,18 @@ TEST_F(ConnstrTest, testOptionsPassthrough)
262
253
  ASSERT_EQ("barval", op.value);
263
254
 
264
255
  reinit();
265
- err = lcb_connspec_parse("couchbase:///protected?ssl=on&compression=off",
266
- &params, &errmsg);
256
+ err = params.parse("couchbase:///protected?ssl=on&compression=off", &errmsg);
267
257
  ASSERT_EQ(LCB_SUCCESS, err) << "Ok with bucket and no hosts";
268
258
  ASSERT_EQ(1, countHosts(&params));
269
259
  ASSERT_FALSE(NULL == findHost(&params, "localhost"));
270
260
  ASSERT_TRUE(findOption(&params, "compression", op));
271
261
 
272
262
  reinit();
273
- err = lcb_connspec_parse("couchbase://?foo=foo&bar=bar&", &params, &errmsg);
263
+ err = params.parse("couchbase://?foo=foo&bar=bar&", &errmsg);
274
264
  ASSERT_EQ(LCB_SUCCESS, err) << "Ok with trailing '&'";
275
265
 
276
266
  reinit();
277
- err = lcb_connspec_parse("couchbase://?foo=foo&bootstrap_on=all&bar=bar",
278
- &params, &errmsg);
267
+ err = params.parse("couchbase://?foo=foo&bootstrap_on=all&bar=bar", &errmsg);
279
268
  ASSERT_EQ(LCB_SUCCESS, err) << "Ok with non-passthrough option";
280
269
  ASSERT_TRUE(findOption(&params, "foo", op));
281
270
  ASSERT_TRUE(findOption(&params, "bar", op));
@@ -285,32 +274,32 @@ TEST_F(ConnstrTest, testOptionsPassthrough)
285
274
  TEST_F(ConnstrTest, testRecognizedOptions)
286
275
  {
287
276
  lcb_error_t err;
288
- err = lcb_connspec_parse("couchbases://", &params, &errmsg);
277
+ err = params.parse("couchbases://", &errmsg);
289
278
  ASSERT_EQ(LCB_SUCCESS, err);
290
279
  ASSERT_EQ(LCB_SSL_ENABLED, params.sslopts());
291
280
 
292
281
  reinit();
293
- err = lcb_connspec_parse("couchbase://?ssl=on", &params, &errmsg);
282
+ err = params.parse("couchbase://?ssl=on", &errmsg);
294
283
  ASSERT_EQ(LCB_SUCCESS, err);
295
284
  ASSERT_EQ(LCB_SSL_ENABLED, params.sslopts());
296
285
 
297
286
  reinit();
298
- err = lcb_connspec_parse("couchbases://?ssl=no_verify", &params, &errmsg);
287
+ err = params.parse("couchbases://?ssl=no_verify", &errmsg);
299
288
  ASSERT_EQ(LCB_SUCCESS, err);
300
289
  ASSERT_EQ(LCB_SSL_ENABLED|LCB_SSL_NOVERIFY, params.sslopts());
301
290
 
302
291
  reinit();
303
- err = lcb_connspec_parse("couchbases://?ssl=off", &params, &errmsg);
292
+ err = params.parse("couchbases://?ssl=off", &errmsg);
304
293
  ASSERT_NE(LCB_SUCCESS, err);
305
294
 
306
295
  // Loglevel
307
296
  reinit();
308
- err = lcb_connspec_parse("couchbase://?console_log_level=5", &params, &errmsg);
297
+ err = params.parse("couchbase://?console_log_level=5", &errmsg);
309
298
  ASSERT_EQ(LCB_SUCCESS, err);
310
299
  ASSERT_EQ(5, params.loglevel());
311
300
 
312
301
  reinit();
313
- err = lcb_connspec_parse("couchbase://?console_log_level=gah", &params, &errmsg);
302
+ err = params.parse("couchbase://?console_log_level=gah", &errmsg);
314
303
  ASSERT_NE(LCB_SUCCESS, err);
315
304
 
316
305
  }
@@ -318,30 +307,30 @@ TEST_F(ConnstrTest, testRecognizedOptions)
318
307
  TEST_F(ConnstrTest, testTransportOptions)
319
308
  {
320
309
  lcb_error_t err;
321
- err = lcb_connspec_parse("couchbase://", &params, &errmsg);
310
+ err = params.parse("couchbase://", &errmsg);
322
311
  ASSERT_EQ(LCB_SUCCESS, err);
323
312
  ASSERT_FALSE(params.is_bs_udef());
324
313
 
325
314
  reinit();
326
- err = lcb_connspec_parse("couchbase://?bootstrap_on=cccp", &params, &errmsg);
315
+ err = params.parse("couchbase://?bootstrap_on=cccp", &errmsg);
327
316
  ASSERT_EQ(LCB_SUCCESS, err) << "bootstrap_on=cccp";
328
317
  ASSERT_TRUE(params.has_bsmode(LCB_CONFIG_TRANSPORT_CCCP));
329
318
  ASSERT_FALSE(params.has_bsmode(LCB_CONFIG_TRANSPORT_HTTP));
330
319
 
331
320
  reinit();
332
- err = lcb_connspec_parse("couchbase://?bootstrap_on=http", &params, &errmsg);
321
+ err = params.parse("couchbase://?bootstrap_on=http", &errmsg);
333
322
  ASSERT_EQ(LCB_SUCCESS, err) << "bootstrap_on=http";
334
323
  ASSERT_TRUE(params.has_bsmode(LCB_CONFIG_TRANSPORT_HTTP));
335
324
  ASSERT_FALSE(params.has_bsmode(LCB_CONFIG_TRANSPORT_CCCP));
336
325
 
337
326
  reinit();
338
- err = lcb_connspec_parse("couchbase://?bootstrap_on=all", &params, &errmsg);
327
+ err = params.parse("couchbase://?bootstrap_on=all", &errmsg);
339
328
  ASSERT_EQ(LCB_SUCCESS, err) << "bootstrap_on=all";
340
329
  ASSERT_TRUE(params.has_bsmode(LCB_CONFIG_TRANSPORT_CCCP));
341
330
  ASSERT_TRUE(params.has_bsmode(LCB_CONFIG_TRANSPORT_HTTP));
342
331
 
343
332
  reinit();
344
- err = lcb_connspec_parse("couchbase://?bootstrap_on=bleh", &params, &errmsg);
333
+ err = params.parse("couchbase://?bootstrap_on=bleh", &errmsg);
345
334
  ASSERT_NE(LCB_SUCCESS, err) << "Error on bad bootstrap_on value";
346
335
  }
347
336
 
@@ -355,7 +344,7 @@ TEST_F(ConnstrTest, testCompatConversion)
355
344
  cropts.v.v0.host = "foo.com;bar.com;baz.com";
356
345
  cropts.v.v0.passwd = "secret";
357
346
 
358
- err = lcb_connspec_convert(&params, &cropts);
347
+ err = params.load(cropts);
359
348
  ASSERT_EQ(LCB_SUCCESS, err);
360
349
  ASSERT_FALSE(NULL == findHost(&params, "foo.com"));
361
350
  ASSERT_FALSE(NULL == findHost(&params, "bar.com"));
@@ -372,7 +361,7 @@ TEST_F(ConnstrTest, testCompatConversion)
372
361
  cropts.version = 2;
373
362
  cropts.v.v2.host = "foo.com:9030;bar.com:9040;baz.com:9050";
374
363
  cropts.v.v2.mchosts = "foo.com:7030;bar.com:7040;baz.com:7050";
375
- err = lcb_connspec_convert(&params, &cropts);
364
+ err = params.load(cropts);
376
365
  ASSERT_EQ(LCB_SUCCESS, err);
377
366
  ASSERT_EQ(6, countHosts(&params));
378
367
 
@@ -382,7 +371,7 @@ TEST_F(ConnstrTest, testCompatConversion)
382
371
  cropts.version = 3;
383
372
  cropts.v.v3.passwd = "secret";
384
373
  cropts.v.v3.connstr = "couchbase:///fluffle?password=bleh";
385
- err = lcb_connspec_convert(&params, &cropts);
374
+ err = params.load(cropts);
386
375
  ASSERT_EQ(LCB_SUCCESS, err);
387
376
  ASSERT_EQ("fluffle", params.bucket());
388
377
  ASSERT_EQ(cropts.v.v3.passwd, params.password());
@@ -393,12 +382,61 @@ TEST_F(ConnstrTest, testCertificateWithoutSSL)
393
382
  // Ensure we get an invalid input error for certificate paths without
394
383
  // couchbases://
395
384
  lcb_error_t err;
396
- err = lcb_connspec_parse(
397
- "couchbase://1.2.3.4/default?certpath=/foo/bar/baz", &params, &errmsg);
385
+ err = params.parse(
386
+ "couchbase://1.2.3.4/default?certpath=/foo/bar/baz", &errmsg);
398
387
  ASSERT_NE(LCB_SUCCESS, err);
399
388
 
400
389
  reinit();
401
- err = lcb_connspec_parse(
402
- "couchbases://1.2.3.4/default?certpath=/foo/bar/baz", &params, &errmsg);
390
+ err = params.parse(
391
+ "couchbases://1.2.3.4/default?certpath=/foo/bar/baz", &errmsg);
403
392
  ASSERT_EQ(LCB_SUCCESS, err);
404
393
  }
394
+
395
+ TEST_F(ConnstrTest, testDnsSrvExplicit)
396
+ {
397
+ // Test various things relating to DNS SRV
398
+ lcb_error_t err;
399
+ err = params.parse("couchbase+dnssrv://1.1.1.1", &errmsg);
400
+ EXPECT_EQ(LCB_SUCCESS, err);
401
+ EXPECT_TRUE(params.can_dnssrv());
402
+ EXPECT_TRUE(params.is_explicit_dnssrv());
403
+
404
+ reinit();
405
+ err = params.parse("couchbase+dnssrv://1.1.1.1,2.2.2.2", &errmsg);
406
+ EXPECT_NE(LCB_SUCCESS, err);
407
+
408
+ reinit();
409
+ err = params.parse("couchbases+dnssrv://1.1.1.1", &errmsg);
410
+ EXPECT_EQ(LCB_SUCCESS, err);
411
+ EXPECT_NE(0, params.sslopts());
412
+ EXPECT_TRUE(params.can_dnssrv());
413
+ EXPECT_TRUE(params.is_explicit_dnssrv());
414
+ }
415
+
416
+ TEST_F(ConnstrTest, testDnsSrvImplicit)
417
+ {
418
+ EXPECT_EQ(LCB_SUCCESS, params.parse("couchbase://"));
419
+ EXPECT_FALSE(params.can_dnssrv());
420
+ EXPECT_FALSE(params.is_explicit_dnssrv());
421
+
422
+ reinit();
423
+ EXPECT_EQ(LCB_SUCCESS, params.parse("couchbase://1.1.1.1"));
424
+ EXPECT_TRUE(params.can_dnssrv());
425
+ EXPECT_FALSE(params.is_explicit_dnssrv());
426
+
427
+ reinit();
428
+ EXPECT_EQ(LCB_SUCCESS, params.parse("couchbase://1.1.1.1,2.2.2.2"));
429
+ EXPECT_FALSE(params.can_dnssrv()) << "No implicit SRV on multiple hosts";
430
+
431
+ reinit();
432
+ EXPECT_EQ(LCB_SUCCESS, params.parse("couchbase://1.1.1.1:666"));
433
+ EXPECT_FALSE(params.can_dnssrv());
434
+
435
+ reinit();
436
+ EXPECT_EQ(LCB_SUCCESS, params.parse("couchbase://1.1.1.1:11210"));
437
+ EXPECT_TRUE(params.can_dnssrv());
438
+
439
+ reinit();
440
+ EXPECT_EQ(LCB_SUCCESS, params.parse("couchbases://1.1.1.1"));
441
+ EXPECT_TRUE(params.can_dnssrv());
442
+ }
@@ -9,25 +9,67 @@ class CredsTest : public ::testing::Test
9
9
  {
10
10
  };
11
11
 
12
- TEST_F(CredsTest, testCreds)
12
+ static lcb_t create(const char *connstr = NULL) {
13
+ lcb_create_st crst;
14
+ memset(&crst, 0, sizeof crst);
15
+ crst.version = 3;
16
+ crst.v.v3.connstr = connstr;
17
+ lcb_t ret;
18
+ lcb_error_t rc = lcb_create(&ret, &crst);
19
+ EXPECT_EQ(LCB_SUCCESS, rc);
20
+ return ret;
21
+ }
22
+
23
+ TEST_F(CredsTest, testLegacyCreds)
13
24
  {
14
25
  lcb_t instance;
15
- lcb_BUCKETCRED cred;
16
26
  ASSERT_EQ(LCB_SUCCESS, lcb_create(&instance, NULL));
17
27
  lcb::Authenticator& auth = *instance->settings->auth;
18
- ASSERT_FALSE(auth.username().empty());
19
- ASSERT_EQ("default", auth.username());
28
+ ASSERT_TRUE(auth.username().empty());
29
+ ASSERT_EQ(LCBAUTH_MODE_CLASSIC, auth.mode());
20
30
 
21
31
  ASSERT_EQ(1, auth.buckets().size());
22
32
  ASSERT_TRUE(auth.buckets().find("default")->second.empty());
33
+ ASSERT_EQ("", auth.password_for("default"));
34
+ ASSERT_EQ("default", auth.username_for("default"));
23
35
 
24
36
  // Try to add another user/password:
25
37
  lcb_BUCKETCRED creds = { "user2", "pass2" };
26
38
  ASSERT_EQ(LCB_SUCCESS, lcb_cntl(instance, LCB_CNTL_SET, LCB_CNTL_BUCKET_CRED, creds));
27
39
  ASSERT_EQ(2, auth.buckets().size());
28
40
  ASSERT_EQ("pass2", auth.buckets().find("user2")->second);
29
- ASSERT_EQ("default", auth.username());
41
+ ASSERT_EQ("user2", auth.username_for("user2"));
42
+ ASSERT_EQ("pass2", auth.password_for("user2"));
43
+
44
+ ASSERT_TRUE(auth.username().empty());
45
+ ASSERT_TRUE(auth.password().empty());
46
+ lcb_destroy(instance);
47
+ }
48
+
49
+ TEST_F(CredsTest, testRbacCreds) {
50
+ lcb_t instance = create("couchbase://localhost/default?username=mark");
51
+ lcb::Authenticator& auth = *instance->settings->auth;
52
+ ASSERT_EQ("mark", auth.username());
53
+ ASSERT_EQ(LCBAUTH_MODE_RBAC, auth.mode());
54
+ ASSERT_TRUE(auth.buckets().empty());
55
+ ASSERT_EQ("mark", auth.username_for("default"));
56
+ ASSERT_EQ("", auth.password_for("default"));
57
+ ASSERT_EQ("mark", auth.username_for("jane"));
58
+ ASSERT_EQ("", auth.password_for("jane"));
59
+
60
+ // Try adding a new bucket, it should fail
61
+ ASSERT_EQ(LCB_OPTIONS_CONFLICT, auth.add("users", "secret", LCBAUTH_F_BUCKET));
62
+
63
+ // Try using "old-style" auth. It should fail:
64
+ ASSERT_EQ(LCB_OPTIONS_CONFLICT, auth.add("users", "secret", LCBAUTH_F_BUCKET|LCBAUTH_F_CLUSTER));
65
+ // Username/password should remain unchanged:
66
+ ASSERT_EQ("mark", auth.username());
30
67
  ASSERT_EQ("", auth.password());
68
+
69
+ // Try *changing* the credentials
70
+ ASSERT_EQ(LCB_SUCCESS, auth.add("jane", "seekrit", LCBAUTH_F_CLUSTER));
71
+ ASSERT_EQ("jane", auth.username_for("default"));
72
+ ASSERT_EQ("seekrit", auth.password_for("default"));
31
73
  lcb_destroy(instance);
32
74
  }
33
75
 
@@ -82,117 +82,109 @@ TEST_F(Hostlist, testEquals)
82
82
 
83
83
  TEST_F(Hostlist, testParseList)
84
84
  {
85
- hostlist_t hosts = hostlist_create();
86
- ASSERT_FALSE(NULL == hosts);
85
+ lcb::Hostlist hosts;
87
86
 
88
87
  lcb_error_t err;
89
- err = hostlist_add_stringz(hosts, "1.1.1.1", 8091);
88
+ err = hosts.add("1.1.1.1", 8091);
90
89
  ASSERT_EQ(LCB_SUCCESS, err);
91
- ASSERT_EQ(1, hosts->size());
92
- ASSERT_TRUE(hosts->exists("1.1.1.1:8091"));
90
+ ASSERT_EQ(1, hosts.size());
91
+ ASSERT_TRUE(hosts.exists("1.1.1.1:8091"));
93
92
 
94
-
95
- hostlist_clear(hosts);
96
- err = hostlist_add_stringz(hosts, "1.1.1.1;", 8091);
93
+ hosts.clear();
94
+ err = hosts.add("1.1.1.1;", 8091);
97
95
  ASSERT_EQ(LCB_SUCCESS, err);
98
- ASSERT_EQ(1, hosts->size());
99
- ASSERT_TRUE(hosts->exists("1.1.1.1:8091"));
96
+ ASSERT_EQ(1, hosts.size());
97
+ ASSERT_TRUE(hosts.exists("1.1.1.1:8091"));
100
98
 
101
- hostlist_clear(hosts);
102
- err = hostlist_add_stringz(hosts, ";", 8091);
99
+ hosts.clear();
100
+ err = hosts.add(";", 8091);
103
101
  ASSERT_EQ(LCB_SUCCESS, err);
104
- ASSERT_EQ(0, hosts->size());
102
+ ASSERT_EQ(0, hosts.size());
105
103
 
106
- hostlist_clear(hosts);
107
- err = hostlist_add_stringz(hosts, ";;;;", 8091);
104
+ hosts.clear();
105
+ err = hosts.add(";;;;", 8091);
108
106
  ASSERT_EQ(LCB_SUCCESS, err);
109
- ASSERT_EQ(0, hosts->size());
107
+ ASSERT_EQ(0, hosts.size());
110
108
 
111
- hostlist_clear(hosts);
112
- err = hostlist_add_stringz(hosts, "1.1.1.1;2.2.2.2", 8091);
109
+ hosts.clear();
110
+ err = hosts.add("1.1.1.1;2.2.2.2", 8091);
113
111
  ASSERT_EQ(LCB_SUCCESS, err);
114
- ASSERT_EQ(2, hosts->size());
115
- ASSERT_TRUE(hosts->exists("1.1.1.1:8091"));
116
- ASSERT_TRUE(hosts->exists("2.2.2.2:8091"));
117
-
112
+ ASSERT_EQ(2, hosts.size());
113
+ ASSERT_TRUE(hosts.exists("1.1.1.1:8091"));
114
+ ASSERT_TRUE(hosts.exists("2.2.2.2:8091"));
118
115
 
119
- hostlist_clear(hosts);
120
- err = hostlist_add_stringz(hosts, "1.1.1.1:1000;2.2.2.2:2000;3.3.3.3", 8091);
116
+ hosts.clear();
117
+ err = hosts.add("1.1.1.1:1000;2.2.2.2:2000;3.3.3.3", 8091);
121
118
  ASSERT_EQ(LCB_SUCCESS, err);
122
- ASSERT_EQ(3, hosts->size());
123
- ASSERT_TRUE(hosts->exists("1.1.1.1:1000"));
124
- ASSERT_TRUE(hosts->exists("2.2.2.2:2000"));
125
- ASSERT_TRUE(hosts->exists("3.3.3.3:8091"));
119
+ ASSERT_EQ(3, hosts.size());
120
+ ASSERT_TRUE(hosts.exists("1.1.1.1:1000"));
121
+ ASSERT_TRUE(hosts.exists("2.2.2.2:2000"));
122
+ ASSERT_TRUE(hosts.exists("3.3.3.3:8091"));
126
123
 
127
- hostlist_clear(hosts);
128
- err = hostlist_add_stringz(hosts, "1.1.1.1;1.1.1.1;1.1.1.1", 8091);
124
+ hosts.clear();
125
+ err = hosts.add("1.1.1.1;1.1.1.1;1.1.1.1", 8091);
129
126
  ASSERT_EQ(LCB_SUCCESS, err);
130
- ASSERT_EQ(1, hosts->size());
131
- ASSERT_TRUE(hosts->exists("1.1.1.1:8091"));
127
+ ASSERT_EQ(1, hosts.size());
128
+ ASSERT_TRUE(hosts.exists("1.1.1.1:8091"));
132
129
 
133
130
 
134
- hostlist_clear(hosts);
135
- err = hostlist_add_stringz(hosts, "1.1.1.1:9000;1.1.1.1:9001;1.1.1.1:9002", 8091);
131
+ hosts.clear();
132
+ err = hosts.add("1.1.1.1:9000;1.1.1.1:9001;1.1.1.1:9002", 8091);
136
133
  ASSERT_EQ(LCB_SUCCESS, err);
137
- ASSERT_EQ(3, hosts->size());
138
- ASSERT_TRUE(hosts->exists("1.1.1.1:9000"));
139
- ASSERT_TRUE(hosts->exists("1.1.1.1:9001"));
140
- ASSERT_TRUE(hosts->exists("1.1.1.1:9002"));
141
-
142
- hostlist_clear(hosts);
143
- ASSERT_EQ(LCB_SUCCESS, hostlist_add_stringz(hosts, "1.1.1.1", 8091));
144
- ASSERT_EQ(LCB_SUCCESS, hostlist_add_stringz(hosts, "2.2.2.2", 8091));
145
- ASSERT_EQ(LCB_SUCCESS, hostlist_add_stringz(hosts, "3.3.3.3", 8091));
146
- ASSERT_EQ(3, hosts->size());
147
-
148
- ASSERT_TRUE(hosts->exists("1.1.1.1:8091"));
149
- ASSERT_TRUE(hosts->exists("2.2.2.2:8091"));
150
- ASSERT_TRUE(hosts->exists("3.3.3.3:8091"));
151
-
152
- hostlist_randomize(hosts);
153
- hostlist_clear(hosts);
154
- hostlist_randomize(hosts);
155
-
156
- hostlist_destroy(hosts);
134
+ ASSERT_EQ(3, hosts.size());
135
+ ASSERT_TRUE(hosts.exists("1.1.1.1:9000"));
136
+ ASSERT_TRUE(hosts.exists("1.1.1.1:9001"));
137
+ ASSERT_TRUE(hosts.exists("1.1.1.1:9002"));
138
+
139
+ hosts.clear();
140
+ ASSERT_EQ(LCB_SUCCESS, hosts.add("1.1.1.1", 8091));
141
+ ASSERT_EQ(LCB_SUCCESS, hosts.add("2.2.2.2", 8091));
142
+ ASSERT_EQ(LCB_SUCCESS, hosts.add("3.3.3.3", 8091));
143
+ ASSERT_EQ(3, hosts.size());
144
+
145
+ ASSERT_TRUE(hosts.exists("1.1.1.1:8091"));
146
+ ASSERT_TRUE(hosts.exists("2.2.2.2:8091"));
147
+ ASSERT_TRUE(hosts.exists("3.3.3.3:8091"));
148
+
149
+ hosts.randomize();
150
+ hosts.clear();
151
+ hosts.randomize();
157
152
  }
158
153
 
159
154
  TEST_F(Hostlist, testCycle)
160
155
  {
161
- hostlist_t hosts = hostlist_create();
156
+ lcb::Hostlist hosts;
162
157
  lcb_host_t *curhost;
163
158
 
164
-
165
159
  // Empty list
166
- ASSERT_EQ(NULL, hostlist_shift_next(hosts, 0));
167
- ASSERT_EQ(NULL, hostlist_shift_next(hosts, 1));
168
- hostlist_destroy(hosts);
169
- hosts = hostlist_create();
160
+ ASSERT_EQ(NULL, hosts.next(false));
161
+ ASSERT_EQ(NULL, hosts.next(true));
170
162
 
171
- hostlist_add_stringz(hosts, "1.1.1.1", 8091);
172
- curhost = hostlist_shift_next(hosts, 0);
163
+ hosts.clear();
164
+ hosts.add("1.1.1.1", 8091);
165
+ curhost = hosts.next(false);
173
166
  ASSERT_TRUE(curhost != NULL);
174
167
  ASSERT_TRUE(hostEquals(*curhost, "1.1.1.1", "8091"));
175
168
 
176
- curhost = hostlist_shift_next(hosts, 0);
177
- ASSERT_TRUE(hostlist_shift_next(hosts, 0) == NULL);
178
- ASSERT_TRUE(hostlist_shift_next(hosts, 0) == NULL);
179
- ASSERT_TRUE(hosts->ix == 1);
169
+ curhost = hosts.next(false);
170
+ ASSERT_TRUE(hosts.next(false) == NULL);
171
+ ASSERT_TRUE(hosts.next(false) == NULL);
172
+ ASSERT_TRUE(hosts.ix == 1);
180
173
 
181
- curhost = hostlist_shift_next(hosts, 1);
174
+ curhost = hosts.next(true);
182
175
  ASSERT_TRUE(curhost != NULL);
183
176
  ASSERT_TRUE(hostEquals(*curhost, "1.1.1.1", "8091"));
184
177
 
185
- hostlist_add_stringz(hosts, "2.2.2.2", 8091);
186
- curhost = hostlist_shift_next(hosts, 0);
178
+ hosts.add("2.2.2.2", 8091);
179
+ curhost = hosts.next(false);
187
180
  ASSERT_TRUE(hostEquals(*curhost, "2.2.2.2", "8091"));
188
- ASSERT_TRUE(hostlist_shift_next(hosts, 0) == NULL);
181
+ ASSERT_TRUE(hosts.next(false) == NULL);
189
182
 
190
- curhost = hostlist_shift_next(hosts, 1);
183
+ curhost = hosts.next(true);
191
184
  ASSERT_TRUE(hostEquals(*curhost, "1.1.1.1", "8091"));
192
- curhost = hostlist_shift_next(hosts, 0);
185
+ curhost = hosts.next(false);
193
186
  ASSERT_TRUE(hostEquals(*curhost, "2.2.2.2", "8091"));
194
187
 
195
- hostlist_clear(hosts);
196
- ASSERT_TRUE(hostlist_shift_next(hosts, 1) == NULL);
197
- hostlist_destroy(hosts);
188
+ hosts.clear();
189
+ ASSERT_TRUE(hosts.next(true) == NULL);
198
190
  }