libcouchbase 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (561) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.gitmodules +3 -0
  4. data/.rspec +1 -0
  5. data/.travis.yml +35 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE +24 -0
  8. data/README.md +389 -0
  9. data/Rakefile +75 -0
  10. data/ext/README.md +6 -0
  11. data/ext/Rakefile +20 -0
  12. data/ext/libcouchbase/.gitignore +130 -0
  13. data/ext/libcouchbase/.travis.yml +19 -0
  14. data/ext/libcouchbase/CMakeLists.txt +429 -0
  15. data/ext/libcouchbase/CONTRIBUTING.md +124 -0
  16. data/ext/libcouchbase/LICENSE +202 -0
  17. data/ext/libcouchbase/README.markdown +163 -0
  18. data/ext/libcouchbase/RELEASE_NOTES.markdown +2691 -0
  19. data/ext/libcouchbase/cmake/Modules/ConfigureDtrace.cmake +27 -0
  20. data/ext/libcouchbase/cmake/Modules/CopyPDB.cmake +42 -0
  21. data/ext/libcouchbase/cmake/Modules/DistScript.cmake +17 -0
  22. data/ext/libcouchbase/cmake/Modules/DownloadLcbDep.cmake +20 -0
  23. data/ext/libcouchbase/cmake/Modules/FindCouchbaseHdrHistogram.cmake +15 -0
  24. data/ext/libcouchbase/cmake/Modules/FindCouchbaseLibev.cmake +73 -0
  25. data/ext/libcouchbase/cmake/Modules/FindCouchbaseLibevent.cmake +52 -0
  26. data/ext/libcouchbase/cmake/Modules/FindCouchbaseLibuv.cmake +56 -0
  27. data/ext/libcouchbase/cmake/Modules/FindCouchbaseSnappy.cmake +11 -0
  28. data/ext/libcouchbase/cmake/Modules/GenerateConfigDotH.cmake +29 -0
  29. data/ext/libcouchbase/cmake/Modules/GetLibcouchbaseFlags.cmake +133 -0
  30. data/ext/libcouchbase/cmake/Modules/GetPlatformCCInfo.cmake +45 -0
  31. data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +70 -0
  32. data/ext/libcouchbase/cmake/config-cmake.h.in +60 -0
  33. data/ext/libcouchbase/cmake/configure +357 -0
  34. data/ext/libcouchbase/cmake/defs.mk.in +8 -0
  35. data/ext/libcouchbase/cmake/dtrace-instr-link.pl +38 -0
  36. data/ext/libcouchbase/cmake/source_files.cmake +73 -0
  37. data/ext/libcouchbase/configure.pl +1 -0
  38. data/ext/libcouchbase/contrib/cJSON/cJSON.c +624 -0
  39. data/ext/libcouchbase/contrib/cJSON/cJSON.h +158 -0
  40. data/ext/libcouchbase/contrib/cbsasl/CMakeLists.txt +9 -0
  41. data/ext/libcouchbase/contrib/cbsasl/COPYING +202 -0
  42. data/ext/libcouchbase/contrib/cbsasl/include/cbsasl/cbsasl.h +217 -0
  43. data/ext/libcouchbase/contrib/cbsasl/src/client.c +205 -0
  44. data/ext/libcouchbase/contrib/cbsasl/src/common.c +46 -0
  45. data/ext/libcouchbase/contrib/cbsasl/src/cram-md5/hmac.c +67 -0
  46. data/ext/libcouchbase/contrib/cbsasl/src/cram-md5/hmac.h +33 -0
  47. data/ext/libcouchbase/contrib/cbsasl/src/cram-md5/md5.c +296 -0
  48. data/ext/libcouchbase/contrib/cbsasl/src/cram-md5/md5.h +45 -0
  49. data/ext/libcouchbase/contrib/cbsasl/src/hash.c +573 -0
  50. data/ext/libcouchbase/contrib/cbsasl/src/hash.h +15 -0
  51. data/ext/libcouchbase/contrib/cbsasl/src/util.h +31 -0
  52. data/ext/libcouchbase/contrib/cliopts/CMakeLists.txt +2 -0
  53. data/ext/libcouchbase/contrib/cliopts/cliopts.c +747 -0
  54. data/ext/libcouchbase/contrib/cliopts/cliopts.h +493 -0
  55. data/ext/libcouchbase/contrib/genhash/genhash.c +372 -0
  56. data/ext/libcouchbase/contrib/genhash/genhash.h +235 -0
  57. data/ext/libcouchbase/contrib/gtest-1.7.0/CHANGES +157 -0
  58. data/ext/libcouchbase/contrib/gtest-1.7.0/CMakeLists.txt +252 -0
  59. data/ext/libcouchbase/contrib/gtest-1.7.0/CONTRIBUTORS +37 -0
  60. data/ext/libcouchbase/contrib/gtest-1.7.0/LICENSE +28 -0
  61. data/ext/libcouchbase/contrib/gtest-1.7.0/MINIFY.sh +15 -0
  62. data/ext/libcouchbase/contrib/gtest-1.7.0/README +435 -0
  63. data/ext/libcouchbase/contrib/gtest-1.7.0/cmake/internal_utils.cmake +227 -0
  64. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest-death-test.h +294 -0
  65. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest-message.h +250 -0
  66. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest-param-test.h +1421 -0
  67. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest-param-test.h.pump +487 -0
  68. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest-printers.h +855 -0
  69. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest-spi.h +232 -0
  70. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest-test-part.h +179 -0
  71. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest-typed-test.h +259 -0
  72. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest.h +2291 -0
  73. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest_pred_impl.h +358 -0
  74. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest_prod.h +58 -0
  75. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-death-test-internal.h +319 -0
  76. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-filepath.h +206 -0
  77. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-internal.h +1158 -0
  78. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-linked_ptr.h +233 -0
  79. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h +5143 -0
  80. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h.pump +301 -0
  81. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-param-util.h +619 -0
  82. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-port.h +1947 -0
  83. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-string.h +167 -0
  84. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-tuple.h +1012 -0
  85. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-tuple.h.pump +339 -0
  86. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-type-util.h +3331 -0
  87. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-type-util.h.pump +297 -0
  88. data/ext/libcouchbase/contrib/gtest-1.7.0/src/gtest-all.cc +48 -0
  89. data/ext/libcouchbase/contrib/gtest-1.7.0/src/gtest-death-test.cc +1344 -0
  90. data/ext/libcouchbase/contrib/gtest-1.7.0/src/gtest-filepath.cc +382 -0
  91. data/ext/libcouchbase/contrib/gtest-1.7.0/src/gtest-internal-inl.h +1218 -0
  92. data/ext/libcouchbase/contrib/gtest-1.7.0/src/gtest-port.cc +805 -0
  93. data/ext/libcouchbase/contrib/gtest-1.7.0/src/gtest-printers.cc +363 -0
  94. data/ext/libcouchbase/contrib/gtest-1.7.0/src/gtest-test-part.cc +110 -0
  95. data/ext/libcouchbase/contrib/gtest-1.7.0/src/gtest-typed-test.cc +110 -0
  96. data/ext/libcouchbase/contrib/gtest-1.7.0/src/gtest.cc +5015 -0
  97. data/ext/libcouchbase/contrib/gtest-1.7.0/src/gtest_main.cc +38 -0
  98. data/ext/libcouchbase/contrib/http_parser/LICENSE-MIT +23 -0
  99. data/ext/libcouchbase/contrib/http_parser/README.md +178 -0
  100. data/ext/libcouchbase/contrib/http_parser/http_parser.c +2060 -0
  101. data/ext/libcouchbase/contrib/http_parser/http_parser.h +321 -0
  102. data/ext/libcouchbase/contrib/jsonsl/LICENSE +20 -0
  103. data/ext/libcouchbase/contrib/jsonsl/jsonsl.c +1452 -0
  104. data/ext/libcouchbase/contrib/jsonsl/jsonsl.h +971 -0
  105. data/ext/libcouchbase/contrib/lcb-jsoncpp/CMakeLists.txt +6 -0
  106. data/ext/libcouchbase/contrib/lcb-jsoncpp/LICENSE +55 -0
  107. data/ext/libcouchbase/contrib/lcb-jsoncpp/lcb-jsoncpp-forwards.h +255 -0
  108. data/ext/libcouchbase/contrib/lcb-jsoncpp/lcb-jsoncpp.cpp +4892 -0
  109. data/ext/libcouchbase/contrib/lcb-jsoncpp/lcb-jsoncpp.h +1961 -0
  110. data/ext/libcouchbase/contrib/snappy/CMakeLists.txt +8 -0
  111. data/ext/libcouchbase/contrib/snappy/COPYING +28 -0
  112. data/ext/libcouchbase/contrib/snappy/snappy-c.cc +90 -0
  113. data/ext/libcouchbase/contrib/snappy/snappy-c.h +138 -0
  114. data/ext/libcouchbase/contrib/snappy/snappy-internal.h +150 -0
  115. data/ext/libcouchbase/contrib/snappy/snappy-lcb-msvc.h +5 -0
  116. data/ext/libcouchbase/contrib/snappy/snappy-sinksource.cc +71 -0
  117. data/ext/libcouchbase/contrib/snappy/snappy-sinksource.h +137 -0
  118. data/ext/libcouchbase/contrib/snappy/snappy-stubs-internal.cc +42 -0
  119. data/ext/libcouchbase/contrib/snappy/snappy-stubs-internal.h +491 -0
  120. data/ext/libcouchbase/contrib/snappy/snappy-stubs-public.h +98 -0
  121. data/ext/libcouchbase/contrib/snappy/snappy.cc +1307 -0
  122. data/ext/libcouchbase/contrib/snappy/snappy.h +184 -0
  123. data/ext/libcouchbase/contrib/win32-defs/iocpdefs.h +133 -0
  124. data/ext/libcouchbase/contrib/win32-defs/mingwdefs.h +4396 -0
  125. data/ext/libcouchbase/contrib/win32-defs/win_stdint.h +258 -0
  126. data/ext/libcouchbase/example/CMakeLists.txt +37 -0
  127. data/ext/libcouchbase/example/README.markdown +47 -0
  128. data/ext/libcouchbase/example/db/db.c +167 -0
  129. data/ext/libcouchbase/example/db/vb.c +227 -0
  130. data/ext/libcouchbase/example/instancepool/main.cc +102 -0
  131. data/ext/libcouchbase/example/instancepool/pool.cc +102 -0
  132. data/ext/libcouchbase/example/instancepool/pool.h +69 -0
  133. data/ext/libcouchbase/example/libeventdirect/main.c +148 -0
  134. data/ext/libcouchbase/example/mcc/mcc.cc +246 -0
  135. data/ext/libcouchbase/example/minimal/minimal.c +130 -0
  136. data/ext/libcouchbase/example/observe/observe.c +146 -0
  137. data/ext/libcouchbase/example/subdoc/subdoc-multi.cc +132 -0
  138. data/ext/libcouchbase/example/subdoc/subdoc-simple.cc +191 -0
  139. data/ext/libcouchbase/example/tick/tick.c +119 -0
  140. data/ext/libcouchbase/example/views/views-example.cc +83 -0
  141. data/ext/libcouchbase/include/libcouchbase/_cxxwrap.h +150 -0
  142. data/ext/libcouchbase/include/libcouchbase/api-legacy.h +1689 -0
  143. data/ext/libcouchbase/include/libcouchbase/api3.h +2 -0
  144. data/ext/libcouchbase/include/libcouchbase/assert.h +44 -0
  145. data/ext/libcouchbase/include/libcouchbase/cbft.h +109 -0
  146. data/ext/libcouchbase/include/libcouchbase/cntl-private.h +356 -0
  147. data/ext/libcouchbase/include/libcouchbase/cntl.h +937 -0
  148. data/ext/libcouchbase/include/libcouchbase/configuration.h.in +23 -0
  149. data/ext/libcouchbase/include/libcouchbase/couchbase.h +3677 -0
  150. data/ext/libcouchbase/include/libcouchbase/deprecated.h +300 -0
  151. data/ext/libcouchbase/include/libcouchbase/error.h +595 -0
  152. data/ext/libcouchbase/include/libcouchbase/http.h +1 -0
  153. data/ext/libcouchbase/include/libcouchbase/iops.h +1050 -0
  154. data/ext/libcouchbase/include/libcouchbase/ixmgmt.h +263 -0
  155. data/ext/libcouchbase/include/libcouchbase/kvbuf.h +132 -0
  156. data/ext/libcouchbase/include/libcouchbase/n1ql.h +364 -0
  157. data/ext/libcouchbase/include/libcouchbase/pktfwd.h +270 -0
  158. data/ext/libcouchbase/include/libcouchbase/plugins/io/bsdio-inl.c +367 -0
  159. data/ext/libcouchbase/include/libcouchbase/plugins/io/wsaerr-inl.c +76 -0
  160. data/ext/libcouchbase/include/libcouchbase/plugins/io/wsaerr.h +199 -0
  161. data/ext/libcouchbase/include/libcouchbase/subdoc.h +312 -0
  162. data/ext/libcouchbase/include/libcouchbase/sysdefs.h +98 -0
  163. data/ext/libcouchbase/include/libcouchbase/vbucket.h +643 -0
  164. data/ext/libcouchbase/include/libcouchbase/views.h +298 -0
  165. data/ext/libcouchbase/include/libcouchbase/visibility.h +65 -0
  166. data/ext/libcouchbase/include/memcached/COPYING +30 -0
  167. data/ext/libcouchbase/include/memcached/README +10 -0
  168. data/ext/libcouchbase/include/memcached/protocol_binary.h +1916 -0
  169. data/ext/libcouchbase/include/memcached/vbucket.h +42 -0
  170. data/ext/libcouchbase/packaging/README +7 -0
  171. data/ext/libcouchbase/packaging/abicheck/.gitignore +4 -0
  172. data/ext/libcouchbase/packaging/abicheck/Makefile +17 -0
  173. data/ext/libcouchbase/packaging/abicheck/README.md +27 -0
  174. data/ext/libcouchbase/packaging/abicheck/template.xml +3 -0
  175. data/ext/libcouchbase/packaging/deb/compat +1 -0
  176. data/ext/libcouchbase/packaging/deb/control +73 -0
  177. data/ext/libcouchbase/packaging/deb/copyright +10 -0
  178. data/ext/libcouchbase/packaging/deb/libcouchbase-dev.docs +3 -0
  179. data/ext/libcouchbase/packaging/deb/package.mk +31 -0
  180. data/ext/libcouchbase/packaging/deb/rules +46 -0
  181. data/ext/libcouchbase/packaging/deb/source/format +1 -0
  182. data/ext/libcouchbase/packaging/distinfo/README +1 -0
  183. data/ext/libcouchbase/packaging/distinfo/distinfo.cmake.in +4 -0
  184. data/ext/libcouchbase/packaging/dllversion.rc.in +39 -0
  185. data/ext/libcouchbase/packaging/libcouchbase.pc.in +10 -0
  186. data/ext/libcouchbase/packaging/nuget/libcouchbase.autopkg +76 -0
  187. data/ext/libcouchbase/packaging/parse-git-describe.pl +166 -0
  188. data/ext/libcouchbase/packaging/rpm/libcouchbase.spec.in +108 -0
  189. data/ext/libcouchbase/packaging/rpm/package.mk +40 -0
  190. data/ext/libcouchbase/plugins/io/iocp/CMakeLists.txt +9 -0
  191. data/ext/libcouchbase/plugins/io/iocp/iocp_iops.c +466 -0
  192. data/ext/libcouchbase/plugins/io/iocp/iocp_iops.h +217 -0
  193. data/ext/libcouchbase/plugins/io/iocp/iocp_loop.c +295 -0
  194. data/ext/libcouchbase/plugins/io/iocp/iocp_timer.c +79 -0
  195. data/ext/libcouchbase/plugins/io/iocp/iocp_util.c +229 -0
  196. data/ext/libcouchbase/plugins/io/libev/CMakeLists.txt +29 -0
  197. data/ext/libcouchbase/plugins/io/libev/libev_io_opts.h +65 -0
  198. data/ext/libcouchbase/plugins/io/libev/plugin-libev.c +289 -0
  199. data/ext/libcouchbase/plugins/io/libevent/CMakeLists.txt +29 -0
  200. data/ext/libcouchbase/plugins/io/libevent/libevent_io_opts.h +67 -0
  201. data/ext/libcouchbase/plugins/io/libevent/plugin-libevent.c +292 -0
  202. data/ext/libcouchbase/plugins/io/libuv/CMakeLists.txt +42 -0
  203. data/ext/libcouchbase/plugins/io/libuv/libuv_compat.h +212 -0
  204. data/ext/libcouchbase/plugins/io/libuv/libuv_io_opts.h +118 -0
  205. data/ext/libcouchbase/plugins/io/libuv/plugin-internal.h +148 -0
  206. data/ext/libcouchbase/plugins/io/libuv/plugin-libuv.c +648 -0
  207. data/ext/libcouchbase/plugins/io/select/CMakeLists.txt +11 -0
  208. data/ext/libcouchbase/plugins/io/select/plugin-select.c +448 -0
  209. data/ext/libcouchbase/plugins/io/select/select_io_opts.h +39 -0
  210. data/ext/libcouchbase/src/README.md +103 -0
  211. data/ext/libcouchbase/src/aspend.h +106 -0
  212. data/ext/libcouchbase/src/auth.cc +74 -0
  213. data/ext/libcouchbase/src/auth.h +54 -0
  214. data/ext/libcouchbase/src/bootstrap.c +269 -0
  215. data/ext/libcouchbase/src/bootstrap.h +129 -0
  216. data/ext/libcouchbase/src/bucketconfig/bc_cccp.c +495 -0
  217. data/ext/libcouchbase/src/bucketconfig/bc_file.c +347 -0
  218. data/ext/libcouchbase/src/bucketconfig/bc_http.c +630 -0
  219. data/ext/libcouchbase/src/bucketconfig/bc_http.h +82 -0
  220. data/ext/libcouchbase/src/bucketconfig/bc_mcraw.c +150 -0
  221. data/ext/libcouchbase/src/bucketconfig/clconfig.h +681 -0
  222. data/ext/libcouchbase/src/bucketconfig/confmon.c +474 -0
  223. data/ext/libcouchbase/src/callbacks.c +378 -0
  224. data/ext/libcouchbase/src/cbft.cc +210 -0
  225. data/ext/libcouchbase/src/cntl.cc +847 -0
  226. data/ext/libcouchbase/src/config_static.h +159 -0
  227. data/ext/libcouchbase/src/connspec.cc +462 -0
  228. data/ext/libcouchbase/src/connspec.h +105 -0
  229. data/ext/libcouchbase/src/ctx-log-inl.h +27 -0
  230. data/ext/libcouchbase/src/dump.c +98 -0
  231. data/ext/libcouchbase/src/getconfig.c +100 -0
  232. data/ext/libcouchbase/src/gethrtime.c +109 -0
  233. data/ext/libcouchbase/src/handler.c +922 -0
  234. data/ext/libcouchbase/src/hashset.c +164 -0
  235. data/ext/libcouchbase/src/hashset.h +86 -0
  236. data/ext/libcouchbase/src/hashtable.c +75 -0
  237. data/ext/libcouchbase/src/hdr_timings.c +92 -0
  238. data/ext/libcouchbase/src/hostlist.cc +301 -0
  239. data/ext/libcouchbase/src/hostlist.h +171 -0
  240. data/ext/libcouchbase/src/http/http-priv.h +307 -0
  241. data/ext/libcouchbase/src/http/http.cc +633 -0
  242. data/ext/libcouchbase/src/http/http.h +34 -0
  243. data/ext/libcouchbase/src/http/http_io.cc +307 -0
  244. data/ext/libcouchbase/src/instance.cc +722 -0
  245. data/ext/libcouchbase/src/internal.h +244 -0
  246. data/ext/libcouchbase/src/iofactory.c +575 -0
  247. data/ext/libcouchbase/src/jsparse/parser.cc +519 -0
  248. data/ext/libcouchbase/src/jsparse/parser.h +173 -0
  249. data/ext/libcouchbase/src/lcbht/lcbht.c +282 -0
  250. data/ext/libcouchbase/src/lcbht/lcbht.h +199 -0
  251. data/ext/libcouchbase/src/lcbio/connect.c +557 -0
  252. data/ext/libcouchbase/src/lcbio/connect.h +364 -0
  253. data/ext/libcouchbase/src/lcbio/ctx.c +611 -0
  254. data/ext/libcouchbase/src/lcbio/ctx.h +405 -0
  255. data/ext/libcouchbase/src/lcbio/iotable.c +290 -0
  256. data/ext/libcouchbase/src/lcbio/iotable.h +84 -0
  257. data/ext/libcouchbase/src/lcbio/ioutils.c +350 -0
  258. data/ext/libcouchbase/src/lcbio/ioutils.h +203 -0
  259. data/ext/libcouchbase/src/lcbio/lcbio.h +51 -0
  260. data/ext/libcouchbase/src/lcbio/manager.c +584 -0
  261. data/ext/libcouchbase/src/lcbio/manager.h +156 -0
  262. data/ext/libcouchbase/src/lcbio/protoctx.c +84 -0
  263. data/ext/libcouchbase/src/lcbio/rw-inl.h +115 -0
  264. data/ext/libcouchbase/src/lcbio/ssl.h +149 -0
  265. data/ext/libcouchbase/src/lcbio/timer-ng.h +179 -0
  266. data/ext/libcouchbase/src/lcbio/timer.c +132 -0
  267. data/ext/libcouchbase/src/legacy.c +430 -0
  268. data/ext/libcouchbase/src/list.c +144 -0
  269. data/ext/libcouchbase/src/list.h +127 -0
  270. data/ext/libcouchbase/src/logging.c +244 -0
  271. data/ext/libcouchbase/src/logging.h +86 -0
  272. data/ext/libcouchbase/src/mc/compress.c +90 -0
  273. data/ext/libcouchbase/src/mc/compress.h +61 -0
  274. data/ext/libcouchbase/src/mc/forward.c +186 -0
  275. data/ext/libcouchbase/src/mc/forward.h +90 -0
  276. data/ext/libcouchbase/src/mc/iovcursor-inl.h +279 -0
  277. data/ext/libcouchbase/src/mc/iovcursor.h +66 -0
  278. data/ext/libcouchbase/src/mc/mcreq-flush-inl.h +111 -0
  279. data/ext/libcouchbase/src/mc/mcreq.c +954 -0
  280. data/ext/libcouchbase/src/mc/mcreq.h +977 -0
  281. data/ext/libcouchbase/src/mcserver/mcserver.c +784 -0
  282. data/ext/libcouchbase/src/mcserver/mcserver.h +121 -0
  283. data/ext/libcouchbase/src/mcserver/negotiate.c +656 -0
  284. data/ext/libcouchbase/src/mcserver/negotiate.h +119 -0
  285. data/ext/libcouchbase/src/n1ql/ixmgmt.cc +860 -0
  286. data/ext/libcouchbase/src/n1ql/n1ql-internal.h +22 -0
  287. data/ext/libcouchbase/src/n1ql/n1ql.cc +729 -0
  288. data/ext/libcouchbase/src/n1ql/params.cc +215 -0
  289. data/ext/libcouchbase/src/netbuf/netbuf-defs.h +89 -0
  290. data/ext/libcouchbase/src/netbuf/netbuf-mblock.h +235 -0
  291. data/ext/libcouchbase/src/netbuf/netbuf.c +929 -0
  292. data/ext/libcouchbase/src/netbuf/netbuf.h +452 -0
  293. data/ext/libcouchbase/src/newconfig.c +385 -0
  294. data/ext/libcouchbase/src/nodeinfo.cc +194 -0
  295. data/ext/libcouchbase/src/operations/cbflush.c +71 -0
  296. data/ext/libcouchbase/src/operations/counter.c +116 -0
  297. data/ext/libcouchbase/src/operations/durability-cas.c +224 -0
  298. data/ext/libcouchbase/src/operations/durability-seqno.c +157 -0
  299. data/ext/libcouchbase/src/operations/durability.c +668 -0
  300. data/ext/libcouchbase/src/operations/durability_internal.h +199 -0
  301. data/ext/libcouchbase/src/operations/get.c +409 -0
  302. data/ext/libcouchbase/src/operations/observe-seqno.c +96 -0
  303. data/ext/libcouchbase/src/operations/observe.c +340 -0
  304. data/ext/libcouchbase/src/operations/pktfwd.c +86 -0
  305. data/ext/libcouchbase/src/operations/remove.c +83 -0
  306. data/ext/libcouchbase/src/operations/stats.c +461 -0
  307. data/ext/libcouchbase/src/operations/store.c +360 -0
  308. data/ext/libcouchbase/src/operations/subdoc.cc +510 -0
  309. data/ext/libcouchbase/src/operations/touch.c +81 -0
  310. data/ext/libcouchbase/src/packetutils.c +60 -0
  311. data/ext/libcouchbase/src/packetutils.h +147 -0
  312. data/ext/libcouchbase/src/probes.d +211 -0
  313. data/ext/libcouchbase/src/rdb/bigalloc.c +225 -0
  314. data/ext/libcouchbase/src/rdb/bigalloc.h +73 -0
  315. data/ext/libcouchbase/src/rdb/chunkalloc.c +174 -0
  316. data/ext/libcouchbase/src/rdb/libcalloc.c +94 -0
  317. data/ext/libcouchbase/src/rdb/rope.c +419 -0
  318. data/ext/libcouchbase/src/rdb/rope.h +488 -0
  319. data/ext/libcouchbase/src/retrychk.c +113 -0
  320. data/ext/libcouchbase/src/retryq.c +424 -0
  321. data/ext/libcouchbase/src/retryq.h +157 -0
  322. data/ext/libcouchbase/src/ringbuffer.c +442 -0
  323. data/ext/libcouchbase/src/ringbuffer.h +100 -0
  324. data/ext/libcouchbase/src/settings.c +95 -0
  325. data/ext/libcouchbase/src/settings.h +188 -0
  326. data/ext/libcouchbase/src/simplestring.c +211 -0
  327. data/ext/libcouchbase/src/simplestring.h +228 -0
  328. data/ext/libcouchbase/src/sllist-inl.h +197 -0
  329. data/ext/libcouchbase/src/sllist.h +76 -0
  330. data/ext/libcouchbase/src/ssl/CMakeLists.txt +23 -0
  331. data/ext/libcouchbase/src/ssl/ssl_c.c +415 -0
  332. data/ext/libcouchbase/src/ssl/ssl_common.c +454 -0
  333. data/ext/libcouchbase/src/ssl/ssl_e.c +408 -0
  334. data/ext/libcouchbase/src/ssl/ssl_iot_common.h +180 -0
  335. data/ext/libcouchbase/src/ssobuf.h +82 -0
  336. data/ext/libcouchbase/src/strcodecs/base64.c +123 -0
  337. data/ext/libcouchbase/src/strcodecs/strcodecs.h +285 -0
  338. data/ext/libcouchbase/src/timings.c +208 -0
  339. data/ext/libcouchbase/src/trace.h +105 -0
  340. data/ext/libcouchbase/src/utilities.c +171 -0
  341. data/ext/libcouchbase/src/vbucket/CMakeLists.txt +2 -0
  342. data/ext/libcouchbase/src/vbucket/aliases.h +35 -0
  343. data/ext/libcouchbase/src/vbucket/crc32.h +83 -0
  344. data/ext/libcouchbase/src/vbucket/hash.h +30 -0
  345. data/ext/libcouchbase/src/vbucket/json-inl.h +112 -0
  346. data/ext/libcouchbase/src/vbucket/ketama.c +66 -0
  347. data/ext/libcouchbase/src/vbucket/rfc1321/global.h +32 -0
  348. data/ext/libcouchbase/src/vbucket/rfc1321/md5.h +35 -0
  349. data/ext/libcouchbase/src/vbucket/rfc1321/md5c-inl.h +335 -0
  350. data/ext/libcouchbase/src/vbucket/vbucket.c +1543 -0
  351. data/ext/libcouchbase/src/views/docreq.c +194 -0
  352. data/ext/libcouchbase/src/views/docreq.h +83 -0
  353. data/ext/libcouchbase/src/views/viewreq.c +358 -0
  354. data/ext/libcouchbase/src/views/viewreq.h +36 -0
  355. data/ext/libcouchbase/src/wait.c +161 -0
  356. data/ext/libcouchbase/tests/CMakeLists.txt +140 -0
  357. data/ext/libcouchbase/tests/basic/t_base64.cc +81 -0
  358. data/ext/libcouchbase/tests/basic/t_ccbc103.cc +95 -0
  359. data/ext/libcouchbase/tests/basic/t_connstr.cc +404 -0
  360. data/ext/libcouchbase/tests/basic/t_creds.cc +32 -0
  361. data/ext/libcouchbase/tests/basic/t_ctlcodes.cc +92 -0
  362. data/ext/libcouchbase/tests/basic/t_hashset.cc +262 -0
  363. data/ext/libcouchbase/tests/basic/t_host.cc +198 -0
  364. data/ext/libcouchbase/tests/basic/t_jsparse.cc +137 -0
  365. data/ext/libcouchbase/tests/basic/t_jsparse.h +589 -0
  366. data/ext/libcouchbase/tests/basic/t_list.cc +155 -0
  367. data/ext/libcouchbase/tests/basic/t_logger.cc +65 -0
  368. data/ext/libcouchbase/tests/basic/t_misc.cc +24 -0
  369. data/ext/libcouchbase/tests/basic/t_n1qlstrings.cc +18 -0
  370. data/ext/libcouchbase/tests/basic/t_netbuf.cc +446 -0
  371. data/ext/libcouchbase/tests/basic/t_packet.cc +222 -0
  372. data/ext/libcouchbase/tests/basic/t_ringbuffer.cc +278 -0
  373. data/ext/libcouchbase/tests/basic/t_slist.cc +429 -0
  374. data/ext/libcouchbase/tests/basic/t_strerror.cc +64 -0
  375. data/ext/libcouchbase/tests/basic/t_string.cc +112 -0
  376. data/ext/libcouchbase/tests/basic/t_urlencode.cc +132 -0
  377. data/ext/libcouchbase/tests/check-all.cc +608 -0
  378. data/ext/libcouchbase/tests/htparse/t_basic.cc +193 -0
  379. data/ext/libcouchbase/tests/ioserver/connection.cc +166 -0
  380. data/ext/libcouchbase/tests/ioserver/future.cc +50 -0
  381. data/ext/libcouchbase/tests/ioserver/ioserver.cc +104 -0
  382. data/ext/libcouchbase/tests/ioserver/ioserver.h +478 -0
  383. data/ext/libcouchbase/tests/ioserver/socket.cc +88 -0
  384. data/ext/libcouchbase/tests/ioserver/ssl_connection.cc +145 -0
  385. data/ext/libcouchbase/tests/ioserver/threads-pthreads.cc +119 -0
  386. data/ext/libcouchbase/tests/ioserver/threads-win32.cc +117 -0
  387. data/ext/libcouchbase/tests/ioserver/threads.h +66 -0
  388. data/ext/libcouchbase/tests/iotests/iotests.h +15 -0
  389. data/ext/libcouchbase/tests/iotests/mock-environment.cc +524 -0
  390. data/ext/libcouchbase/tests/iotests/mock-environment.h +385 -0
  391. data/ext/libcouchbase/tests/iotests/mock-unit-test.cc +67 -0
  392. data/ext/libcouchbase/tests/iotests/mock-unit-test.h +61 -0
  393. data/ext/libcouchbase/tests/iotests/serverparams.h +76 -0
  394. data/ext/libcouchbase/tests/iotests/t_arithmetic.cc +143 -0
  395. data/ext/libcouchbase/tests/iotests/t_behavior.cc +226 -0
  396. data/ext/libcouchbase/tests/iotests/t_configcache.cc +117 -0
  397. data/ext/libcouchbase/tests/iotests/t_confmon.cc +241 -0
  398. data/ext/libcouchbase/tests/iotests/t_durability.cc +1059 -0
  399. data/ext/libcouchbase/tests/iotests/t_forward.cc +110 -0
  400. data/ext/libcouchbase/tests/iotests/t_get.cc +512 -0
  401. data/ext/libcouchbase/tests/iotests/t_http.cc +438 -0
  402. data/ext/libcouchbase/tests/iotests/t_iops.cc +175 -0
  403. data/ext/libcouchbase/tests/iotests/t_lock.cc +275 -0
  404. data/ext/libcouchbase/tests/iotests/t_misc.cc +713 -0
  405. data/ext/libcouchbase/tests/iotests/t_mutate.cc +609 -0
  406. data/ext/libcouchbase/tests/iotests/t_n1ql.cc +270 -0
  407. data/ext/libcouchbase/tests/iotests/t_netfail.cc +654 -0
  408. data/ext/libcouchbase/tests/iotests/t_obseqno.cc +157 -0
  409. data/ext/libcouchbase/tests/iotests/t_regression.cc +321 -0
  410. data/ext/libcouchbase/tests/iotests/t_sched.cc +88 -0
  411. data/ext/libcouchbase/tests/iotests/t_serverops.cc +230 -0
  412. data/ext/libcouchbase/tests/iotests/t_smoke.cc +528 -0
  413. data/ext/libcouchbase/tests/iotests/t_subdoc.cc +822 -0
  414. data/ext/libcouchbase/tests/iotests/t_syncmode.cc +64 -0
  415. data/ext/libcouchbase/tests/iotests/t_views.cc +405 -0
  416. data/ext/libcouchbase/tests/iotests/testutil.cc +250 -0
  417. data/ext/libcouchbase/tests/iotests/testutil.h +163 -0
  418. data/ext/libcouchbase/tests/mc/mctest.h +119 -0
  419. data/ext/libcouchbase/tests/mc/pktmaker.h +101 -0
  420. data/ext/libcouchbase/tests/mc/t_alloc.cc +269 -0
  421. data/ext/libcouchbase/tests/mc/t_context.cc +100 -0
  422. data/ext/libcouchbase/tests/mc/t_flush.cc +185 -0
  423. data/ext/libcouchbase/tests/mc/t_forward.cc +239 -0
  424. data/ext/libcouchbase/tests/mc/t_ioflush.cc +102 -0
  425. data/ext/libcouchbase/tests/mc/t_iovcursor.cc +173 -0
  426. data/ext/libcouchbase/tests/mocksupport/procutil.c +305 -0
  427. data/ext/libcouchbase/tests/mocksupport/procutil.h +89 -0
  428. data/ext/libcouchbase/tests/mocksupport/server.c +391 -0
  429. data/ext/libcouchbase/tests/mocksupport/server.h +72 -0
  430. data/ext/libcouchbase/tests/mocksupport/timeout.c +69 -0
  431. data/ext/libcouchbase/tests/nonio_tests.cc +23 -0
  432. data/ext/libcouchbase/tests/rdb/rdbtest.h +133 -0
  433. data/ext/libcouchbase/tests/rdb/t_basic.cc +128 -0
  434. data/ext/libcouchbase/tests/rdb/t_bigalloc.cc +93 -0
  435. data/ext/libcouchbase/tests/rdb/t_refs.cc +112 -0
  436. data/ext/libcouchbase/tests/socktests/socktest.cc +347 -0
  437. data/ext/libcouchbase/tests/socktests/socktest.h +448 -0
  438. data/ext/libcouchbase/tests/socktests/t_basic.cc +143 -0
  439. data/ext/libcouchbase/tests/socktests/t_ctx.cc +73 -0
  440. data/ext/libcouchbase/tests/socktests/t_manager.cc +179 -0
  441. data/ext/libcouchbase/tests/socktests/t_putex.cc +256 -0
  442. data/ext/libcouchbase/tests/socktests/t_read.cc +187 -0
  443. data/ext/libcouchbase/tests/socktests/t_reentrant.cc +143 -0
  444. data/ext/libcouchbase/tests/socktests/t_ssl.cc +80 -0
  445. data/ext/libcouchbase/tests/socktests/t_write.cc +95 -0
  446. data/ext/libcouchbase/tests/start_mock.bat +15 -0
  447. data/ext/libcouchbase/tests/start_mock.sh +42 -0
  448. data/ext/libcouchbase/tests/unit_tests.cc +43 -0
  449. data/ext/libcouchbase/tests/vbucket/confdata/bad.json +101 -0
  450. data/ext/libcouchbase/tests/vbucket/confdata/full_25.json +363 -0
  451. data/ext/libcouchbase/tests/vbucket/confdata/memd_25.json +90 -0
  452. data/ext/libcouchbase/tests/vbucket/confdata/memd_30.json +1 -0
  453. data/ext/libcouchbase/tests/vbucket/confdata/memd_45.json +1 -0
  454. data/ext/libcouchbase/tests/vbucket/confdata/terse_25.json +291 -0
  455. data/ext/libcouchbase/tests/vbucket/confdata/terse_30.json +1 -0
  456. data/ext/libcouchbase/tests/vbucket/t_config.cc +341 -0
  457. data/ext/libcouchbase/tools/CMakeLists.txt +51 -0
  458. data/ext/libcouchbase/tools/cbc-handlers.h +462 -0
  459. data/ext/libcouchbase/tools/cbc-n1qlback.cc +439 -0
  460. data/ext/libcouchbase/tools/cbc-pillowfight.cc +822 -0
  461. data/ext/libcouchbase/tools/cbc.cc +1541 -0
  462. data/ext/libcouchbase/tools/common/histogram.cc +43 -0
  463. data/ext/libcouchbase/tools/common/histogram.h +23 -0
  464. data/ext/libcouchbase/tools/common/my_inttypes.h +22 -0
  465. data/ext/libcouchbase/tools/common/options.cc +420 -0
  466. data/ext/libcouchbase/tools/common/options.h +81 -0
  467. data/ext/libcouchbase/tools/docgen/docgen.h +469 -0
  468. data/ext/libcouchbase/tools/docgen/loc.h +210 -0
  469. data/ext/libcouchbase/tools/docgen/placeholders.h +211 -0
  470. data/ext/libcouchbase/tools/docgen/seqgen.h +94 -0
  471. data/lib/libcouchbase.rb +36 -0
  472. data/lib/libcouchbase/bucket.rb +819 -0
  473. data/lib/libcouchbase/callbacks.rb +72 -0
  474. data/lib/libcouchbase/connection.rb +790 -0
  475. data/lib/libcouchbase/design_docs.rb +86 -0
  476. data/lib/libcouchbase/error.rb +68 -0
  477. data/lib/libcouchbase/ext/libcouchbase.rb +1135 -0
  478. data/lib/libcouchbase/ext/libcouchbase/cmdbase.rb +23 -0
  479. data/lib/libcouchbase/ext/libcouchbase/cmdcounter.rb +36 -0
  480. data/lib/libcouchbase/ext/libcouchbase/cmdendure.rb +26 -0
  481. data/lib/libcouchbase/ext/libcouchbase/cmdfts.rb +24 -0
  482. data/lib/libcouchbase/ext/libcouchbase/cmdget.rb +30 -0
  483. data/lib/libcouchbase/ext/libcouchbase/cmdgetreplica.rb +49 -0
  484. data/lib/libcouchbase/ext/libcouchbase/cmdhttp.rb +58 -0
  485. data/lib/libcouchbase/ext/libcouchbase/cmdn1ql.rb +40 -0
  486. data/lib/libcouchbase/ext/libcouchbase/cmdobseqno.rb +33 -0
  487. data/lib/libcouchbase/ext/libcouchbase/cmdobserve.rb +30 -0
  488. data/lib/libcouchbase/ext/libcouchbase/cmdstore.rb +40 -0
  489. data/lib/libcouchbase/ext/libcouchbase/cmdstoredur.rb +45 -0
  490. data/lib/libcouchbase/ext/libcouchbase/cmdsubdoc.rb +49 -0
  491. data/lib/libcouchbase/ext/libcouchbase/cmdverbosity.rb +29 -0
  492. data/lib/libcouchbase/ext/libcouchbase/cmdviewquery.rb +61 -0
  493. data/lib/libcouchbase/ext/libcouchbase/contigbuf.rb +14 -0
  494. data/lib/libcouchbase/ext/libcouchbase/create_st.rb +15 -0
  495. data/lib/libcouchbase/ext/libcouchbase/create_st0.rb +23 -0
  496. data/lib/libcouchbase/ext/libcouchbase/create_st1.rb +26 -0
  497. data/lib/libcouchbase/ext/libcouchbase/create_st2.rb +32 -0
  498. data/lib/libcouchbase/ext/libcouchbase/create_st3.rb +26 -0
  499. data/lib/libcouchbase/ext/libcouchbase/crst_u.rb +20 -0
  500. data/lib/libcouchbase/ext/libcouchbase/durability_opts_st_v.rb +11 -0
  501. data/lib/libcouchbase/ext/libcouchbase/durability_opts_t.rb +14 -0
  502. data/lib/libcouchbase/ext/libcouchbase/durabilityopt_sv0.rb +63 -0
  503. data/lib/libcouchbase/ext/libcouchbase/enums.rb +991 -0
  504. data/lib/libcouchbase/ext/libcouchbase/fragbuf.rb +18 -0
  505. data/lib/libcouchbase/ext/libcouchbase/ftshandle.rb +7 -0
  506. data/lib/libcouchbase/ext/libcouchbase/histogram.rb +34 -0
  507. data/lib/libcouchbase/ext/libcouchbase/http_request_t.rb +7 -0
  508. data/lib/libcouchbase/ext/libcouchbase/keybuf.rb +20 -0
  509. data/lib/libcouchbase/ext/libcouchbase/multicmd_ctx.rb +30 -0
  510. data/lib/libcouchbase/ext/libcouchbase/mutation_token.rb +17 -0
  511. data/lib/libcouchbase/ext/libcouchbase/n1qlhandle.rb +7 -0
  512. data/lib/libcouchbase/ext/libcouchbase/n1qlparams.rb +7 -0
  513. data/lib/libcouchbase/ext/libcouchbase/respbase.rb +29 -0
  514. data/lib/libcouchbase/ext/libcouchbase/respcounter.rb +32 -0
  515. data/lib/libcouchbase/ext/libcouchbase/respendure.rb +49 -0
  516. data/lib/libcouchbase/ext/libcouchbase/respfts.rb +40 -0
  517. data/lib/libcouchbase/ext/libcouchbase/respget.rb +44 -0
  518. data/lib/libcouchbase/ext/libcouchbase/resphttp.rb +48 -0
  519. data/lib/libcouchbase/ext/libcouchbase/respmcversion.rb +38 -0
  520. data/lib/libcouchbase/ext/libcouchbase/respn1ql.rb +41 -0
  521. data/lib/libcouchbase/ext/libcouchbase/respobseqno.rb +52 -0
  522. data/lib/libcouchbase/ext/libcouchbase/respobserve.rb +41 -0
  523. data/lib/libcouchbase/ext/libcouchbase/respserverbase.rb +32 -0
  524. data/lib/libcouchbase/ext/libcouchbase/respstats.rb +38 -0
  525. data/lib/libcouchbase/ext/libcouchbase/respstore.rb +32 -0
  526. data/lib/libcouchbase/ext/libcouchbase/respstoredur.rb +38 -0
  527. data/lib/libcouchbase/ext/libcouchbase/respsubdoc.rb +35 -0
  528. data/lib/libcouchbase/ext/libcouchbase/respviewquery.rb +67 -0
  529. data/lib/libcouchbase/ext/libcouchbase/sdentry.rb +22 -0
  530. data/lib/libcouchbase/ext/libcouchbase/sdspec.rb +26 -0
  531. data/lib/libcouchbase/ext/libcouchbase/t.rb +7 -0
  532. data/lib/libcouchbase/ext/libcouchbase/valbuf.rb +22 -0
  533. data/lib/libcouchbase/ext/libcouchbase/valbuf_u_buf.rb +14 -0
  534. data/lib/libcouchbase/ext/libcouchbase/viewhandle.rb +7 -0
  535. data/lib/libcouchbase/ext/libcouchbase_iocp.rb +26 -0
  536. data/lib/libcouchbase/ext/libcouchbase_libuv.rb +18 -0
  537. data/lib/libcouchbase/ext/tasks.rb +87 -0
  538. data/lib/libcouchbase/n1ql.rb +73 -0
  539. data/lib/libcouchbase/query_full_text.rb +147 -0
  540. data/lib/libcouchbase/query_n1ql.rb +121 -0
  541. data/lib/libcouchbase/query_view.rb +129 -0
  542. data/lib/libcouchbase/results_fiber.rb +262 -0
  543. data/lib/libcouchbase/results_native.rb +211 -0
  544. data/lib/libcouchbase/version.rb +5 -0
  545. data/libcouchbase.gemspec +61 -0
  546. data/spec/bucket_spec.rb +270 -0
  547. data/spec/connection_spec.rb +277 -0
  548. data/spec/design_docs_spec.rb +23 -0
  549. data/spec/error_spec.rb +26 -0
  550. data/spec/fts_spec.rb +129 -0
  551. data/spec/n1ql_spec.rb +201 -0
  552. data/spec/results_libuv_spec.rb +229 -0
  553. data/spec/results_native_spec.rb +259 -0
  554. data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/design.json +1 -0
  555. data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/data-0000.cbb +0 -0
  556. data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/failover.json +1 -0
  557. data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/meta.json +1 -0
  558. data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/seqno.json +1 -0
  559. data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/snapshot_markers.json +1 -0
  560. data/spec/view_spec.rb +195 -0
  561. metadata +775 -0
@@ -0,0 +1,1543 @@
1
+ /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2014 Couchbase, Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ #include <stdlib.h>
19
+ #include <string.h>
20
+ #include <stddef.h>
21
+ #include <assert.h>
22
+ #include <libcouchbase/couchbase.h>
23
+ #include <libcouchbase/vbucket.h>
24
+ #include "config.h"
25
+ #include "contrib/cJSON/cJSON.h"
26
+ #include "json-inl.h"
27
+ #include "hash.h"
28
+ #include "crc32.h"
29
+ #include "simplestring.h"
30
+
31
+ #define STRINGIFY_(X) #X
32
+ #define STRINGIFY(X) STRINGIFY_(X)
33
+ #define MAX_AUTHORITY_SIZE 100
34
+ #define SET_ERRSTR(cfg, s) if (!(cfg)->errstr) { \
35
+ (cfg)->errstr = __FILE__ ":" STRINGIFY(__LINE__) " " s ; \
36
+ }
37
+
38
+ /******************************************************************************
39
+ ******************************************************************************
40
+ ** Core Parsing Routines **
41
+ ******************************************************************************
42
+ ******************************************************************************/
43
+ static lcbvb_VBUCKET *
44
+ build_vbmap(lcbvb_CONFIG *cfg, cJSON *cj, unsigned *nitems)
45
+ {
46
+ lcbvb_VBUCKET *vblist = NULL;
47
+ cJSON *jvb;
48
+ unsigned ii, nalloc;
49
+
50
+ /** FIXME: Realloc dynamically when too small */
51
+ if (!(nalloc = cJSON_GetArraySize(cj))) {
52
+ goto GT_ERR;
53
+ }
54
+
55
+ if (!(vblist = calloc(nalloc, sizeof(*vblist)))) {
56
+ goto GT_ERR;
57
+ }
58
+
59
+ /* Iterate over all the vbuckets */
60
+ jvb = cj->child;
61
+ for (ii = 0; ii < nalloc && jvb; ++ii, jvb = jvb->next) {
62
+ cJSON *jsix;
63
+ lcbvb_VBUCKET *cvb;
64
+ unsigned jj, nservers;
65
+
66
+ if (jvb->type != cJSON_Array) {
67
+ goto GT_ERR;
68
+ }
69
+
70
+ nservers = cJSON_GetArraySize(jvb);
71
+ jsix = jvb->child;
72
+ cvb = vblist + ii;
73
+
74
+ /* Iterate over each index in the vbucket */
75
+ for (jj = 0; jj < nservers && jsix; ++jj, jsix = jsix->next) {
76
+ if (jsix->type != cJSON_Number) {
77
+ goto GT_ERR;
78
+ }
79
+ cvb->servers[jj] = jsix->valueint;
80
+ if (cvb->servers[jj] > (int)cfg->nsrv-1) {
81
+ SET_ERRSTR(cfg, "Invalid vBucket map received from server. Above-bounds vBucket target found");
82
+ goto GT_ERR;
83
+ }
84
+ }
85
+ }
86
+
87
+ *nitems = nalloc;
88
+ return vblist;
89
+
90
+ GT_ERR:
91
+ free(vblist);
92
+ return NULL;
93
+ }
94
+
95
+ static lcbvb_SERVER *
96
+ find_server_memd(lcbvb_SERVER *servers, unsigned n, const char *s)
97
+ {
98
+ unsigned ii;
99
+ for (ii = 0; ii < n; ii++) {
100
+ char buf[4096] = { 0 };
101
+ lcbvb_SERVER *cur = servers + ii;
102
+ snprintf(buf, sizeof(buf), "%s:%d", cur->hostname, cur->svc.data);
103
+ if (!strncmp(s, buf, sizeof(buf))) {
104
+ return cur;
105
+ }
106
+ }
107
+ return NULL;
108
+ }
109
+
110
+ static int
111
+ assign_dumy_server(lcbvb_CONFIG *cfg, lcbvb_SERVER *dst, const char *s)
112
+ {
113
+ int itmp;
114
+ char *colon;
115
+ if (!(dst->authority = strdup(s))) {
116
+ SET_ERRSTR(cfg, "Couldn't allocate authority string");
117
+ goto GT_ERR;
118
+ }
119
+
120
+ if (!(colon = strstr(s, ":"))) {
121
+ SET_ERRSTR(cfg, "Badly formatted name string");
122
+ goto GT_ERR;
123
+ }
124
+
125
+ if (sscanf(colon+1, "%d", &itmp) != 1) {
126
+ SET_ERRSTR(cfg, "Badly formatted port");
127
+ goto GT_ERR;
128
+ }
129
+
130
+ dst->svc.data = itmp;
131
+ return 1;
132
+
133
+ GT_ERR:
134
+ free(dst->authority);
135
+ return 0;
136
+ }
137
+
138
+ static void
139
+ set_vb_count(lcbvb_CONFIG *cfg, lcbvb_VBUCKET *vbs)
140
+ {
141
+ unsigned ii, jj;
142
+ if (!vbs) {
143
+ return;
144
+ }
145
+
146
+ for (ii = 0; ii < cfg->nvb; ++ii) {
147
+ for (jj = 0; jj < cfg->nrepl+1; ++jj) {
148
+ int ix = vbs[ii].servers[jj];
149
+ if (ix < 0 || (unsigned)ix > cfg->nsrv) {
150
+ continue;
151
+ }
152
+ cfg->servers[ix].nvbs++;
153
+ }
154
+ }
155
+ }
156
+
157
+ static int
158
+ pair_server_list(lcbvb_CONFIG *cfg, cJSON *vbconfig)
159
+ {
160
+ cJSON *servers;
161
+ lcbvb_SERVER *newlist = NULL;
162
+ unsigned ii, nsrv;
163
+
164
+ if (!get_jarray(vbconfig, "serverList", &servers)) {
165
+ SET_ERRSTR(cfg, "Couldn't find serverList");
166
+ goto GT_ERROR;
167
+ }
168
+
169
+ nsrv = cJSON_GetArraySize(servers);
170
+
171
+ if (nsrv > cfg->nsrv) {
172
+ /* nodes in serverList which are not in nodes/nodesExt */
173
+ void *tmp = realloc(cfg->servers, sizeof(*cfg->servers) * nsrv);
174
+ if (!tmp) {
175
+ SET_ERRSTR(cfg, "Couldn't allocate memory for server list");
176
+ goto GT_ERROR;
177
+ }
178
+ cfg->servers = tmp;
179
+ cfg->nsrv = nsrv;
180
+ }
181
+
182
+ /* allocate an array for the reordered server list */
183
+ newlist = malloc(sizeof(*cfg->servers) * nsrv);
184
+
185
+ for (ii = 0; ii < nsrv; ii++) {
186
+ char *tmp;
187
+ cJSON *jst;
188
+ lcbvb_SERVER *cur;
189
+ jst = cJSON_GetArrayItem(servers, ii);
190
+ tmp = jst->valuestring;
191
+ cur = find_server_memd(cfg->servers, cfg->nsrv, tmp);
192
+
193
+ if (cur) {
194
+ newlist[ii] = *cur;
195
+ } else {
196
+ /* found server inside serverList but not in nodes? */
197
+ if (!assign_dumy_server(cfg, &newlist[ii], tmp)) {
198
+ goto GT_ERROR;
199
+ }
200
+ }
201
+ }
202
+
203
+ free(cfg->servers);
204
+ cfg->servers = newlist;
205
+ return 1;
206
+
207
+ GT_ERROR:
208
+ free(newlist);
209
+ return 0;
210
+
211
+ }
212
+
213
+ static int
214
+ parse_vbucket(lcbvb_CONFIG *cfg, cJSON *cj)
215
+ {
216
+ cJSON *vbconfig, *vbmap, *ffmap = NULL;
217
+
218
+ if (!get_jobj(cj, "vBucketServerMap", &vbconfig)) {
219
+ SET_ERRSTR(cfg, "Expected top-level 'vBucketServerMap'");
220
+ goto GT_ERROR;
221
+ }
222
+
223
+ if (!get_juint(vbconfig, "numReplicas", &cfg->nrepl)) {
224
+ SET_ERRSTR(cfg, "'numReplicas' missing");
225
+ goto GT_ERROR;
226
+ }
227
+
228
+ if (!get_jarray(vbconfig, "vBucketMap", &vbmap)) {
229
+ SET_ERRSTR(cfg, "Missing 'vBucketMap'");
230
+ goto GT_ERROR;
231
+ }
232
+
233
+ get_jarray(vbconfig, "vBucketMapForward", &ffmap);
234
+
235
+ if ((cfg->vbuckets = build_vbmap(cfg, vbmap, &cfg->nvb)) == NULL) {
236
+ goto GT_ERROR;
237
+ }
238
+
239
+ if (ffmap && (cfg->ffvbuckets = build_vbmap(cfg, ffmap, &cfg->nvb)) == NULL) {
240
+ goto GT_ERROR;
241
+ }
242
+
243
+ if (!cfg->is3x) {
244
+ if (!pair_server_list(cfg, vbconfig)) {
245
+ goto GT_ERROR;
246
+ }
247
+ }
248
+
249
+ /** Now figure out which server goes where */
250
+ set_vb_count(cfg, cfg->vbuckets);
251
+ set_vb_count(cfg, cfg->ffvbuckets);
252
+ return 1;
253
+
254
+ GT_ERROR:
255
+ return 0;
256
+ }
257
+
258
+ static int server_cmp(const void *s1, const void *s2)
259
+ {
260
+ return strcmp(((const lcbvb_SERVER *)s1)->authority,
261
+ ((const lcbvb_SERVER *)s2)->authority);
262
+ }
263
+
264
+ static int continuum_item_cmp(const void *t1, const void *t2)
265
+ {
266
+ const lcbvb_CONTINUUM *ct1 = t1, *ct2 = t2;
267
+
268
+ if (ct1->point == ct2->point) {
269
+ return 0;
270
+ } else if (ct1->point > ct2->point) {
271
+ return 1;
272
+ } else {
273
+ return -1;
274
+ }
275
+ }
276
+
277
+ static int
278
+ update_ketama(lcbvb_CONFIG *cfg)
279
+ {
280
+ char host[MAX_AUTHORITY_SIZE+10] = "";
281
+ int nhost;
282
+ unsigned pp, hh, ss, nn;
283
+ unsigned char digest[16];
284
+ lcbvb_CONTINUUM *new_continuum, *old_continuum;
285
+
286
+ qsort(cfg->servers, cfg->ndatasrv, sizeof(*cfg->servers), server_cmp);
287
+
288
+ new_continuum = calloc(160 * cfg->ndatasrv, sizeof(*new_continuum));
289
+ /* 40 hashes, 4 numbers per hash = 160 points per server */
290
+ for (ss = 0, pp = 0; ss < cfg->ndatasrv; ++ss) {
291
+ /* we can add more points to server which have more memory */
292
+ for (hh = 0; hh < 40; ++hh) {
293
+ lcbvb_SERVER *srv = cfg->servers + ss;
294
+ nhost = snprintf(host, MAX_AUTHORITY_SIZE+10, "%s-%u", srv->authority, hh);
295
+ vb__hash_md5(host, nhost, digest);
296
+ for (nn = 0; nn < 4; ++nn, ++pp) {
297
+ new_continuum[pp].index = ss;
298
+ new_continuum[pp].point = ((uint32_t) (digest[3 + nn * 4] & 0xFF) << 24)
299
+ | ((uint32_t) (digest[2 + nn * 4] & 0xFF) << 16)
300
+ | ((uint32_t) (digest[1 + nn * 4] & 0xFF) << 8)
301
+ | (digest[0 + nn * 4] & 0xFF);
302
+ }
303
+ }
304
+ }
305
+
306
+ qsort(new_continuum, pp, sizeof *new_continuum, continuum_item_cmp);
307
+ old_continuum = cfg->continuum;
308
+ cfg->continuum = new_continuum;
309
+ cfg->ncontinuum = pp;
310
+ free(old_continuum);
311
+ return 1;
312
+ }
313
+
314
+ static int
315
+ extract_services(lcbvb_CONFIG *cfg, cJSON *jsvc, lcbvb_SERVICES *svc, int is_ssl)
316
+ {
317
+ int itmp;
318
+ int rv;
319
+ const char *key;
320
+
321
+ #define EXTRACT_SERVICE(k, fld) \
322
+ key = is_ssl ? k"SSL" : k; \
323
+ rv = get_jint(jsvc, key, &itmp); \
324
+ if (rv) { svc->fld = itmp; } else { svc->fld = 0; }
325
+
326
+ EXTRACT_SERVICE("kv", data);
327
+ EXTRACT_SERVICE("mgmt", mgmt);
328
+ EXTRACT_SERVICE("capi", views);
329
+ EXTRACT_SERVICE("n1ql", n1ql);
330
+ EXTRACT_SERVICE("fts", fts);
331
+ EXTRACT_SERVICE("indexAdmin", ixadmin);
332
+ EXTRACT_SERVICE("indexScan", ixquery);
333
+
334
+ #undef EXTRACT_SERVICE
335
+
336
+ (void)cfg;
337
+ return 1;
338
+ }
339
+
340
+ static int
341
+ build_server_strings(lcbvb_CONFIG *cfg, lcbvb_SERVER *server)
342
+ {
343
+ /* get the authority */
344
+ char tmpbuf[4096];
345
+
346
+ sprintf(tmpbuf, "%s:%d", server->hostname, server->svc.data);
347
+ server->authority = strdup(tmpbuf);
348
+ if (!server->authority) {
349
+ SET_ERRSTR(cfg, "Couldn't allocate authority");
350
+ return 0;
351
+ }
352
+
353
+ server->svc.hoststrs[LCBVB_SVCTYPE_DATA] = server->authority;
354
+ if (server->viewpath == NULL && server->svc.views) {
355
+ server->viewpath = malloc(strlen(cfg->bname) + 2);
356
+ sprintf(server->viewpath, "/%s", cfg->bname);
357
+ }
358
+ if (server->querypath == NULL && server->svc.n1ql) {
359
+ server->querypath = strdup("/query/service");
360
+ }
361
+ if (server->ftspath == NULL && server->svc.fts) {
362
+ server->ftspath = strdup("/");
363
+ }
364
+ return 1;
365
+ }
366
+
367
+ /**
368
+ * Parse a node from the 'nodesExt' array
369
+ * @param cfg
370
+ * @param server
371
+ * @param js
372
+ * @return
373
+ */
374
+ static int
375
+ build_server_3x(lcbvb_CONFIG *cfg, lcbvb_SERVER *server, cJSON *js)
376
+ {
377
+ cJSON *jsvcs;
378
+ char *htmp;
379
+
380
+ if (!get_jstr(js, "hostname", &htmp)) {
381
+ htmp = "$HOST";
382
+ }
383
+ if (!(server->hostname = strdup(htmp))) {
384
+ SET_ERRSTR(cfg, "Couldn't allocate memory");
385
+ goto GT_ERR;
386
+ }
387
+
388
+ if (!get_jobj(js, "services", &jsvcs)) {
389
+ SET_ERRSTR(cfg, "Couldn't find 'services'");
390
+ goto GT_ERR;
391
+ }
392
+
393
+ if (!extract_services(cfg, jsvcs, &server->svc, 0)) {
394
+ goto GT_ERR;
395
+ }
396
+ if (!extract_services(cfg, jsvcs, &server->svc_ssl, 1)) {
397
+ goto GT_ERR;
398
+ }
399
+
400
+ if (!build_server_strings(cfg, server)) {
401
+ goto GT_ERR;
402
+ }
403
+
404
+ return 1;
405
+
406
+ GT_ERR:
407
+ return 0;
408
+ }
409
+
410
+ /**
411
+ * Initialize a server from a JSON Object
412
+ * @param server The server to initialize
413
+ * @param js The object which contains the server information
414
+ * @return nonzero on success, 0 on failure.
415
+ */
416
+ static int
417
+ build_server_2x(lcbvb_CONFIG *cfg, lcbvb_SERVER *server, cJSON *js)
418
+ {
419
+ char *tmp = NULL, *colon;
420
+ int itmp;
421
+ cJSON *jsports;
422
+
423
+ if (!get_jstr(js, "hostname", &tmp)) {
424
+ SET_ERRSTR(cfg, "Couldn't find hostname");
425
+ goto GT_ERR;
426
+ }
427
+
428
+ /** Hostname is the _rest_ API host, e.g. '8091' */
429
+ if ((server->hostname = strdup(tmp)) == NULL) {
430
+ SET_ERRSTR(cfg, "Couldn't allocate hostname");
431
+ goto GT_ERR;
432
+ }
433
+
434
+ colon = strchr(server->hostname, ':');
435
+ if (!colon) {
436
+ SET_ERRSTR(cfg, "Expected ':' in 'hostname'");
437
+ goto GT_ERR;
438
+ }
439
+ if (sscanf(colon+1, "%d", &itmp) != 1) {
440
+ SET_ERRSTR(cfg, "Expected port after ':'");
441
+ goto GT_ERR;
442
+ }
443
+
444
+ /* plain mgmt port is extracted from hostname */
445
+ server->svc.mgmt = itmp;
446
+ *colon = '\0';
447
+
448
+ /** Handle the views name */
449
+ if (get_jstr(js, "couchApiBase", &tmp)) {
450
+ /** Have views */
451
+ char *path_begin;
452
+ colon = strrchr(tmp, ':');
453
+
454
+ if (!colon) {
455
+ /* no port */
456
+ goto GT_ERR;
457
+ }
458
+ if (sscanf(colon+1, "%d", &itmp) != 1) {
459
+ goto GT_ERR;
460
+ }
461
+
462
+ /* Assign the port */
463
+ server->svc.views = itmp;
464
+ path_begin = strstr(colon, "/");
465
+ if (!path_begin) {
466
+ SET_ERRSTR(cfg, "Expected path in couchApiBase");
467
+ goto GT_ERR;
468
+ }
469
+ server->viewpath = strdup(path_begin);
470
+ } else {
471
+ server->svc.views = 0;
472
+ }
473
+
474
+ /* get the 'ports' dictionary */
475
+ if (!get_jobj(js, "ports", &jsports)) {
476
+ SET_ERRSTR(cfg, "Expected 'ports' dictionary");
477
+ goto GT_ERR;
478
+ }
479
+
480
+ /* memcached port */
481
+ if (get_jint(jsports, "direct", &itmp)) {
482
+ server->svc.data = itmp;
483
+ } else {
484
+ SET_ERRSTR(cfg, "Expected 'direct' field in 'ports'");
485
+ goto GT_ERR;
486
+ }
487
+
488
+ /* set the authority */
489
+ if (!build_server_strings(cfg, server)) {
490
+ goto GT_ERR;
491
+ }
492
+ return 1;
493
+
494
+ GT_ERR:
495
+ return 0;
496
+ }
497
+
498
+ int
499
+ lcbvb_load_json(lcbvb_CONFIG *cfg, const char *data)
500
+ {
501
+ cJSON *cj = NULL, *jnodes = NULL;
502
+ char *tmp = NULL;
503
+ unsigned ii;
504
+
505
+ if ((cj = cJSON_Parse(data)) == NULL) {
506
+ SET_ERRSTR(cfg, "Couldn't parse JSON");
507
+ goto GT_ERROR;
508
+ }
509
+
510
+ if (!get_jstr(cj, "name", &tmp)) {
511
+ SET_ERRSTR(cfg, "Expected 'name' key");
512
+ goto GT_ERROR;
513
+ }
514
+ cfg->bname = strdup(tmp);
515
+
516
+ if (!get_jstr(cj, "nodeLocator", &tmp)) {
517
+ SET_ERRSTR(cfg, "Expected 'nodeLocator' key");
518
+ goto GT_ERROR;
519
+ }
520
+
521
+ if (get_jarray(cj, "nodesExt", &jnodes)) {
522
+ cfg->is3x = 1;
523
+ } else if (!get_jarray(cj, "nodes", &jnodes)) {
524
+ SET_ERRSTR(cfg, "expected 'nodesExt' or 'nodes' array");
525
+ goto GT_ERROR;
526
+ }
527
+
528
+ if (!strcmp(tmp, "ketama")) {
529
+ cfg->dtype = LCBVB_DIST_KETAMA;
530
+ } else {
531
+ cfg->dtype = LCBVB_DIST_VBUCKET;
532
+ }
533
+
534
+ if (get_jstr(cj, "uuid", &tmp)) {
535
+ cfg->buuid = strdup(tmp);
536
+ }
537
+
538
+ if (!get_jint(cj, "rev", &cfg->revid)) {
539
+ cfg->revid = -1;
540
+ }
541
+
542
+ /** Get the number of nodes. This traverses the list. Yuck */
543
+ cfg->nsrv = cJSON_GetArraySize(jnodes);
544
+
545
+ /** Allocate a temporary one on the heap */
546
+ cfg->servers = calloc(cfg->nsrv, sizeof(*cfg->servers));
547
+ for (ii = 0; ii < cfg->nsrv; ii++) {
548
+ int rv;
549
+ cJSON *jsrv = cJSON_GetArrayItem(jnodes, ii);
550
+
551
+ if (cfg->is3x) {
552
+ rv = build_server_3x(cfg, cfg->servers + ii, jsrv);
553
+ } else {
554
+ rv = build_server_2x(cfg, cfg->servers + ii, jsrv);
555
+ }
556
+
557
+ if (!rv) {
558
+ SET_ERRSTR(cfg, "Failed to build server");
559
+ goto GT_ERROR;
560
+ }
561
+ }
562
+
563
+ /* Count the number of _data_ servers in the cluster. Per the spec,
564
+ * these will always appear in order (so that we won't ever have "holes") */
565
+ for (ii = 0; ii < cfg->nsrv; ii++) {
566
+ if (!cfg->servers[ii].svc.data) {
567
+ break;
568
+ }
569
+ }
570
+ cfg->ndatasrv = ii;
571
+
572
+ if (cfg->dtype == LCBVB_DIST_VBUCKET) {
573
+ if (!parse_vbucket(cfg, cj)) {
574
+ SET_ERRSTR(cfg, "Failed to parse vBucket map");
575
+ goto GT_ERROR;
576
+ }
577
+ } else {
578
+ /* If there is no $HOST then we can update the ketama config, otherwise
579
+ * we must wait for the hostname to be replaced! */
580
+ if (strstr(data, "$HOST") == NULL) {
581
+ if (!update_ketama(cfg)) {
582
+ SET_ERRSTR(cfg, "Failed to establish ketama continuums");
583
+ }
584
+ }
585
+ }
586
+ cfg->servers = realloc(cfg->servers, sizeof(*cfg->servers) * cfg->nsrv);
587
+ cfg->randbuf = malloc(cfg->nsrv * sizeof(*cfg->randbuf));
588
+ cJSON_Delete(cj);
589
+ return 0;
590
+
591
+ GT_ERROR:
592
+ if (cj) {
593
+ cJSON_Delete(cj);
594
+ }
595
+ return -1;
596
+ }
597
+
598
+ static void
599
+ replace_hoststr(char **orig, const char *replacement)
600
+ {
601
+ char *match;
602
+ char *newbuf;
603
+
604
+ if (!*orig) {
605
+ return;
606
+ }
607
+
608
+ match = strstr(*orig, "$HOST");
609
+ if (match == NULL || *match == '\0') {
610
+ return;
611
+ }
612
+
613
+ newbuf = malloc(strlen(*orig) + strlen(replacement));
614
+ *match = '\0';
615
+
616
+ /* copy until the placeholder */
617
+ strcpy(newbuf, *orig);
618
+ /* copy the host */
619
+ strcat(newbuf, replacement);
620
+ /* copy after the placeholder */
621
+ match += sizeof("$HOST")-1;
622
+ strcat(newbuf, match);
623
+ free(*orig);
624
+ *orig = newbuf;
625
+ }
626
+
627
+ LIBCOUCHBASE_API
628
+ void
629
+ lcbvb_replace_host(lcbvb_CONFIG *cfg, const char *hoststr)
630
+ {
631
+ unsigned ii;
632
+ for (ii = 0; ii < cfg->nsrv; ++ii) {
633
+ unsigned jj;
634
+ lcbvb_SERVER *srv = cfg->servers + ii;
635
+ lcbvb_SERVICES *svcs[] = { &srv->svc, &srv->svc_ssl };
636
+
637
+ replace_hoststr(&srv->hostname, hoststr);
638
+ for (jj = 0; jj < 2; ++jj) {
639
+ unsigned kk;
640
+ lcbvb_SERVICES *cursvc = svcs[jj];
641
+ replace_hoststr(&cursvc->views_base_, hoststr);
642
+ for (kk = 0; kk < LCBVB_SVCTYPE__MAX; ++kk) {
643
+ replace_hoststr(&cursvc->hoststrs[kk], hoststr);
644
+ }
645
+ }
646
+ /* reassign authority */
647
+ srv->authority = srv->svc.hoststrs[LCBVB_SVCTYPE_DATA];
648
+ }
649
+ if (cfg->dtype == LCBVB_DIST_KETAMA) {
650
+ update_ketama(cfg);
651
+ }
652
+ }
653
+
654
+ lcbvb_CONFIG *
655
+ lcbvb_parse_json(const char *js)
656
+ {
657
+ int rv;
658
+ lcbvb_CONFIG *cfg = calloc(1, sizeof(*cfg));
659
+ rv = lcbvb_load_json(cfg, js);
660
+ if (rv) {
661
+ lcbvb_destroy(cfg);
662
+ return NULL;
663
+ }
664
+ return cfg;
665
+ }
666
+
667
+ LIBCOUCHBASE_API
668
+ lcbvb_CONFIG *
669
+ lcbvb_create(void)
670
+ {
671
+ return calloc(1, sizeof(lcbvb_CONFIG));
672
+ }
673
+
674
+ static void
675
+ free_service_strs(lcbvb_SERVICES *svc)
676
+ {
677
+ unsigned ii;
678
+ for (ii = 0; ii < LCBVB_SVCTYPE__MAX; ii++) {
679
+ free(svc->hoststrs[ii]);
680
+ }
681
+ free(svc->views_base_);
682
+ free(svc->query_base_);
683
+ free(svc->fts_base_);
684
+ }
685
+
686
+ void
687
+ lcbvb_destroy(lcbvb_CONFIG *conf)
688
+ {
689
+ unsigned ii;
690
+ for (ii = 0; ii < conf->nsrv; ii++) {
691
+ lcbvb_SERVER *srv = conf->servers + ii;
692
+ free(srv->hostname);
693
+ free(srv->viewpath);
694
+ free(srv->querypath);
695
+ free(srv->ftspath);
696
+ free_service_strs(&srv->svc);
697
+ free_service_strs(&srv->svc_ssl);
698
+ }
699
+ free(conf->servers);
700
+ free(conf->continuum);
701
+ free(conf->buuid);
702
+ free(conf->bname);
703
+ free(conf->vbuckets);
704
+ free(conf->ffvbuckets);
705
+ free(conf->randbuf);
706
+ free(conf);
707
+ }
708
+
709
+ static void
710
+ svcs_to_json(lcbvb_SERVICES *svc, cJSON *jsvc, int is_ssl)
711
+ {
712
+ cJSON *tmp;
713
+ const char *key;
714
+ #define EXTRACT_SERVICE(name, fld) \
715
+ if (svc->fld) { \
716
+ key = is_ssl ? name"SSL" : name; \
717
+ tmp = cJSON_CreateNumber(svc->fld); \
718
+ cJSON_AddItemToObject(jsvc, key, tmp); \
719
+ }
720
+
721
+ EXTRACT_SERVICE("mgmt", mgmt);
722
+ EXTRACT_SERVICE("capi", views);
723
+ EXTRACT_SERVICE("kv", data);
724
+ EXTRACT_SERVICE("n1ql", n1ql);
725
+ EXTRACT_SERVICE("indexScan", ixquery);
726
+ EXTRACT_SERVICE("indexAdmin", ixadmin);
727
+ #undef EXTRACT_SERVICE
728
+ }
729
+
730
+ LIBCOUCHBASE_API
731
+ char *
732
+ lcbvb_save_json(lcbvb_CONFIG *cfg)
733
+ {
734
+ unsigned ii;
735
+ char *ret;
736
+ cJSON *tmp = NULL, *nodes = NULL;
737
+ cJSON *root = cJSON_CreateObject();
738
+
739
+ if (cfg->dtype == LCBVB_DIST_VBUCKET) {
740
+ tmp = cJSON_CreateString("vbucket");
741
+ } else {
742
+ tmp = cJSON_CreateString("ketama");
743
+ }
744
+ cJSON_AddItemToObject(root, "nodeLocator", tmp);
745
+
746
+ if (cfg->buuid) {
747
+ tmp = cJSON_CreateString(cfg->buuid);
748
+ cJSON_AddItemToObject(root, "uuid", tmp);
749
+ }
750
+ if (cfg->revid > -1) {
751
+ tmp = cJSON_CreateNumber(cfg->revid);
752
+ cJSON_AddItemToObject(root, "rev", tmp);
753
+ }
754
+ tmp = cJSON_CreateString(cfg->bname);
755
+ cJSON_AddItemToObject(root, "name", tmp);
756
+
757
+ nodes = cJSON_CreateArray();
758
+ cJSON_AddItemToObject(root, "nodesExt", nodes);
759
+
760
+ for (ii = 0; ii < cfg->nsrv; ii++) {
761
+ cJSON *sj = cJSON_CreateObject(), *jsvc = cJSON_CreateObject();
762
+ lcbvb_SERVER *srv = cfg->servers + ii;
763
+
764
+ tmp = cJSON_CreateString(srv->hostname);
765
+ cJSON_AddItemToObject(sj, "hostname", tmp);
766
+ svcs_to_json(&srv->svc, jsvc, 0);
767
+ svcs_to_json(&srv->svc_ssl, jsvc, 1);
768
+
769
+ /* add the services to the server */
770
+ cJSON_AddItemToObject(sj, "services", jsvc);
771
+ cJSON_AddItemToArray(nodes, sj);
772
+ }
773
+
774
+ /* Now either add the vbucket or ketama stuff */
775
+ if (cfg->dtype == LCBVB_DIST_VBUCKET) {
776
+ cJSON *vbroot = cJSON_CreateObject();
777
+ cJSON *vbmap = cJSON_CreateArray();
778
+
779
+ tmp = cJSON_CreateNumber(cfg->nrepl);
780
+ cJSON_AddItemToObject(vbroot, "numReplicas", tmp);
781
+
782
+ for (ii = 0; ii < cfg->nvb; ii++) {
783
+ cJSON *curvb = cJSON_CreateIntArray(
784
+ cfg->vbuckets[ii].servers, cfg->nrepl+1);
785
+ cJSON_AddItemToArray(vbmap, curvb);
786
+ }
787
+
788
+ cJSON_AddItemToObject(vbroot, "vBucketMap", vbmap);
789
+ cJSON_AddItemToObject(root, "vBucketServerMap", vbroot);
790
+ }
791
+
792
+ ret = cJSON_PrintUnformatted(root);
793
+ cJSON_Delete(root);
794
+ return ret;
795
+ }
796
+
797
+ /******************************************************************************
798
+ ******************************************************************************
799
+ ** Mapping Routines **
800
+ ******************************************************************************
801
+ ******************************************************************************/
802
+
803
+ static int
804
+ map_ketama(lcbvb_CONFIG *cfg, const void *key, size_t nkey)
805
+ {
806
+ uint32_t digest, mid, prev;
807
+ lcbvb_CONTINUUM *beginp, *endp, *midp, *highp, *lowp;
808
+ assert(cfg->continuum);
809
+ digest = vb__hash_ketama(key, nkey);
810
+ beginp = lowp = cfg->continuum;
811
+ endp = highp = cfg->continuum + cfg->ncontinuum;
812
+
813
+ /* divide and conquer array search to find server with next biggest
814
+ * point after what this key hashes to */
815
+ while (1)
816
+ {
817
+ /* pick the middle point */
818
+ midp = lowp + (highp - lowp) / 2;
819
+
820
+ if (midp == endp) {
821
+ /* if at the end, roll back to zeroth */
822
+ return beginp->index;
823
+ break;
824
+ }
825
+
826
+ mid = midp->point;
827
+ prev = (midp == beginp) ? 0 : (midp-1)->point;
828
+
829
+ if (digest <= mid && digest > prev) {
830
+ /* we found nearest server */
831
+ return midp->index;
832
+ break;
833
+ }
834
+
835
+ /* adjust the limits */
836
+ if (mid < digest) {
837
+ lowp = midp + 1;
838
+ } else {
839
+ highp = midp - 1;
840
+ }
841
+
842
+ if (lowp > highp) {
843
+ return beginp->index;
844
+ break;
845
+ }
846
+ }
847
+ return -1;
848
+ }
849
+
850
+ int
851
+ lcbvb_k2vb(lcbvb_CONFIG *cfg, const void *k, lcb_SIZE n)
852
+ {
853
+ uint32_t digest = hash_crc32(k, n);
854
+ return digest % cfg->nvb;
855
+ }
856
+
857
+ int
858
+ lcbvb_vbmaster(lcbvb_CONFIG *cfg, int vbid)
859
+ {
860
+ return cfg->vbuckets[vbid].servers[0];
861
+ }
862
+
863
+ int
864
+ lcbvb_vbreplica(lcbvb_CONFIG *cfg, int vbid, unsigned ix)
865
+ {
866
+ if (ix < cfg->nrepl) {
867
+ return cfg->vbuckets[vbid].servers[ix+1];
868
+ } else {
869
+ return -1;
870
+ }
871
+ }
872
+
873
+ /*
874
+ * (https://www.couchbase.com/issues/browse/MB-12268?focusedCommentId=101894&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-101894)
875
+ *
876
+ * So (from my possibly partially ignorant view of that matter) I'd do the following:
877
+ *
878
+ * 1) Send first request according to lated vbucket map you have.
879
+ * If it works, we're good. Exit.
880
+ *
881
+ * 2) if that fails, look if you've newer vbucket map. If there's newer vbucket map
882
+ * and it points to _different_ node, send request to that node and proceed
883
+ * to step 3. Otherwise go to step 4
884
+ *
885
+ * 3) if newer node still gives you not-my-vbucket, go to step 4
886
+ *
887
+ * 4) if there's fast forward map in latest bucket info and fast forward map
888
+ * points to different node, send request to that node. And go to step 5.
889
+ * Otherwise (not ff map or it points to one of nodes you've tried already),
890
+ * go to step 6
891
+ *
892
+ * 5) if ff map node request succeeds. Exit. Otherwise go to step 6.
893
+ *
894
+ * 6) Try first replica unless it's one of nodes you've already tried.
895
+ * If it succeeds. Exit. Otherwise go to step 7.
896
+ *
897
+ * 7) Try all nodes in turn, prioritizing other replicas to beginning of list
898
+ * and nodes you have already tried to end. If one of nodes agrees to perform
899
+ * your request. Exit. Otherwise propagate error to back to app
900
+ */
901
+ int
902
+ lcbvb_nmv_remap_ex(lcbvb_CONFIG *cfg, int vbid, int bad, int heuristic)
903
+ {
904
+ int cur = cfg->vbuckets[vbid].servers[0];
905
+ int rv = cur;
906
+ unsigned ii;
907
+
908
+ if (bad != cur) {
909
+ return cur;
910
+ }
911
+
912
+ /* if a forward table exists, then return the vbucket id from the forward table
913
+ * and update that information in the current table. We also need to Update the
914
+ * replica information for that vbucket */
915
+
916
+ if (cfg->ffvbuckets &&
917
+ (rv = cfg->ffvbuckets[vbid].servers[0]) != bad && rv > -1) {
918
+ memcpy(&cfg->vbuckets[vbid], &cfg->ffvbuckets[vbid], sizeof (lcbvb_VBUCKET));
919
+ }
920
+
921
+ /* this path is usually only followed if fvbuckets is not present */
922
+ if (heuristic && cur == bad) {
923
+ int validrv = -1;
924
+ for (ii = 0; ii < cfg->ndatasrv; ii++) {
925
+ rv = (rv + 1) % cfg->ndatasrv;
926
+ /* check that the new index has assigned vbuckets (master or replica) */
927
+ if (cfg->servers[rv].nvbs) {
928
+ validrv = rv;
929
+ cfg->vbuckets[vbid].servers[0] = rv;
930
+ break;
931
+ }
932
+ }
933
+
934
+ if (validrv == -1) {
935
+ /* this should happen when there is only one valid node remaining
936
+ * in the cluster, and we've removed serveral other nodes that are
937
+ * still present in the map due to the grace period window.*/
938
+ return -1;
939
+ }
940
+ }
941
+
942
+ if (rv == bad) {
943
+ return -1;
944
+ }
945
+
946
+ return rv;
947
+ }
948
+
949
+
950
+ int
951
+ lcbvb_map_key(lcbvb_CONFIG *cfg, const void *key, lcb_SIZE nkey,
952
+ int *vbid, int *srvix)
953
+ {
954
+ if (cfg->dtype == LCBVB_DIST_KETAMA) {
955
+ *srvix = map_ketama(cfg, key, nkey);
956
+ *vbid = 0;
957
+ return 0;
958
+ } else {
959
+ *vbid = lcbvb_k2vb(cfg, key, nkey);
960
+ *srvix = lcbvb_vbmaster(cfg, *vbid);
961
+ }
962
+ return 0;
963
+ }
964
+
965
+ int
966
+ lcbvb_has_vbucket(lcbvb_CONFIG *vbc, int vbid, int ix)
967
+ {
968
+ unsigned ii;
969
+ lcbvb_VBUCKET *vb = & vbc->vbuckets[vbid];
970
+ for (ii = 0; ii < vbc->nrepl+1; ii++) {
971
+ if (vb->servers[ii] == ix) {
972
+ return 1;
973
+ }
974
+ }
975
+ return 0;
976
+ }
977
+
978
+ /******************************************************************************
979
+ ******************************************************************************
980
+ ** Configuration Comparisons/Diffs **
981
+ ******************************************************************************
982
+ ******************************************************************************/
983
+ static void
984
+ compute_vb_list_diff(lcbvb_CONFIG *from, lcbvb_CONFIG *to, char **out)
985
+ {
986
+ int offset = 0;
987
+ unsigned ii, jj;
988
+
989
+ for (ii = 0; ii < to->nsrv; ii++) {
990
+ int found = 0;
991
+ lcbvb_SERVER *newsrv = to->servers + ii;
992
+ for (jj = 0; !found && jj < from->nsrv; jj++) {
993
+ lcbvb_SERVER *oldsrv = from->servers + jj;
994
+ found |= (strcmp(newsrv->authority, oldsrv->authority) == 0);
995
+ }
996
+ if (!found) {
997
+ char *infostr = malloc(strlen(newsrv->authority) + 128);
998
+ assert(infostr);
999
+ sprintf(infostr, "%s(Data=%d, Index=%d, Query=%d)",
1000
+ newsrv->authority,
1001
+ newsrv->svc.data, newsrv->svc.n1ql, newsrv->svc.ixquery);
1002
+ out[offset] = infostr;
1003
+ ++offset;
1004
+ }
1005
+ }
1006
+ }
1007
+
1008
+ lcbvb_CONFIGDIFF *
1009
+ lcbvb_compare(lcbvb_CONFIG *from, lcbvb_CONFIG *to)
1010
+ {
1011
+ int nservers;
1012
+ lcbvb_CONFIGDIFF *ret;
1013
+ unsigned ii;
1014
+
1015
+ ret = calloc(1, sizeof(*ret));
1016
+ nservers = (from->nsrv > to->nsrv ? from->nsrv : to->nsrv) + 1;
1017
+ ret->servers_added = calloc(nservers, sizeof(*ret->servers_added));
1018
+ ret->servers_removed = calloc(nservers, sizeof(*ret->servers_removed));
1019
+ compute_vb_list_diff(from, to, ret->servers_added);
1020
+ compute_vb_list_diff(to, from, ret->servers_removed);
1021
+
1022
+ if (to->nsrv == from->nsrv) {
1023
+ for (ii = 0; ii < from->nsrv; ii++) {
1024
+ const char *sa, *sb;
1025
+ sa = from->servers[ii].authority;
1026
+ sb = to->servers[ii].authority;
1027
+ ret->sequence_changed |= (0 != strcmp(sa, sb));
1028
+ }
1029
+ } else {
1030
+ ret->sequence_changed = 1;
1031
+ }
1032
+
1033
+ if (from->nvb == to->nvb) {
1034
+ for (ii = 0; ii < from->nvb; ii++) {
1035
+ lcbvb_VBUCKET *vba = from->vbuckets + ii, *vbb = to->vbuckets + ii;
1036
+ if (vba->servers[0] != vbb->servers[0]) {
1037
+ ret->n_vb_changes++;
1038
+ }
1039
+ }
1040
+ } else {
1041
+ ret->n_vb_changes = -1;
1042
+ }
1043
+ return ret;
1044
+ }
1045
+
1046
+ static void
1047
+ free_array_helper(char **l)
1048
+ {
1049
+ int ii;
1050
+ for (ii = 0; l[ii]; ii++) {
1051
+ free(l[ii]);
1052
+ }
1053
+ free(l);
1054
+ }
1055
+
1056
+ void
1057
+ lcbvb_free_diff(lcbvb_CONFIGDIFF *diff) {
1058
+ assert(diff);
1059
+ free_array_helper(diff->servers_added);
1060
+ free_array_helper(diff->servers_removed);
1061
+ free(diff);
1062
+ }
1063
+
1064
+
1065
+ lcbvb_CHANGETYPE
1066
+ lcbvb_get_changetype(lcbvb_CONFIGDIFF *diff)
1067
+ {
1068
+ lcbvb_CHANGETYPE ret = 0;
1069
+ if (diff->n_vb_changes) {
1070
+ ret |= LCBVB_MAP_MODIFIED;
1071
+ }
1072
+ if (*diff->servers_added || *diff->servers_removed || diff->sequence_changed) {
1073
+ ret |= LCBVB_SERVERS_MODIFIED;
1074
+ }
1075
+ return ret;
1076
+ }
1077
+
1078
+ /******************************************************************************
1079
+ ******************************************************************************
1080
+ ** String/Port Getters **
1081
+ ******************************************************************************
1082
+ ******************************************************************************/
1083
+ LIBCOUCHBASE_API
1084
+ unsigned
1085
+ lcbvb_get_port(lcbvb_CONFIG *cfg,
1086
+ unsigned ix, lcbvb_SVCTYPE type, lcbvb_SVCMODE mode)
1087
+ {
1088
+ lcbvb_SERVICES *svc;
1089
+ lcbvb_SERVER *srv;
1090
+ if (type >= LCBVB_SVCTYPE__MAX || mode >= LCBVB_SVCMODE__MAX) {
1091
+ return 0;
1092
+ }
1093
+ if (ix >= cfg->nsrv) {
1094
+ return 0;
1095
+ }
1096
+
1097
+ srv = cfg->servers + ix;
1098
+
1099
+ if (mode == LCBVB_SVCMODE_PLAIN) {
1100
+ svc = &srv->svc;
1101
+ } else {
1102
+ svc = &srv->svc_ssl;
1103
+ }
1104
+
1105
+ if (type == LCBVB_SVCTYPE_DATA) {
1106
+ return svc->data;
1107
+ } else if (type == LCBVB_SVCTYPE_MGMT) {
1108
+ return svc->mgmt;
1109
+ } else if (type == LCBVB_SVCTYPE_VIEWS) {
1110
+ return svc->views;
1111
+ } else if (type == LCBVB_SVCTYPE_IXADMIN) {
1112
+ return svc->ixadmin;
1113
+ } else if (type == LCBVB_SVCTYPE_IXQUERY) {
1114
+ return svc->ixquery;
1115
+ } else if (type == LCBVB_SVCTYPE_N1QL) {
1116
+ return svc->n1ql;
1117
+ } else if (type == LCBVB_SVCTYPE_FTS) {
1118
+ return svc->fts;
1119
+ } else {
1120
+ return 0;
1121
+ }
1122
+ }
1123
+
1124
+ LIBCOUCHBASE_API
1125
+ const char *
1126
+ lcbvb_get_hostport(lcbvb_CONFIG *cfg,
1127
+ unsigned ix, lcbvb_SVCTYPE type, lcbvb_SVCMODE mode)
1128
+ {
1129
+ char **strp;
1130
+ lcbvb_SERVER *srv;
1131
+ lcbvb_SERVICES *svc;
1132
+ unsigned port = lcbvb_get_port(cfg, ix, type, mode);
1133
+
1134
+ if (!port) {
1135
+ return NULL;
1136
+ }
1137
+
1138
+ srv = cfg->servers + ix;
1139
+ if (mode == LCBVB_SVCMODE_PLAIN) {
1140
+ svc = &srv->svc;
1141
+ } else {
1142
+ svc = &srv->svc_ssl;
1143
+ }
1144
+
1145
+ strp = &svc->hoststrs[type];
1146
+ if (*strp == NULL) {
1147
+ *strp = malloc(strlen(srv->hostname) + 20);
1148
+ sprintf(*strp, "%s:%d", srv->hostname, port);
1149
+ }
1150
+ return *strp;
1151
+ }
1152
+
1153
+ LIBCOUCHBASE_API
1154
+ const char *
1155
+ lcbvb_get_hostname(const lcbvb_CONFIG *cfg, unsigned ix)
1156
+ {
1157
+ if (cfg->nsrv > ix) {
1158
+ return cfg->servers[ix].hostname;
1159
+ } else {
1160
+ return NULL;
1161
+ }
1162
+ }
1163
+
1164
+ LIBCOUCHBASE_API
1165
+ int
1166
+ lcbvb_get_randhost_ex(const lcbvb_CONFIG *cfg,
1167
+ lcbvb_SVCTYPE type, lcbvb_SVCMODE mode, int *used)
1168
+ {
1169
+ size_t nn, oix = 0;
1170
+
1171
+ /*
1172
+ * Since not all nodes support all service types, we need to make it a
1173
+ * fair selection by pre-filtering the nodes which actually support the
1174
+ * service, and then proceed to actually select a suitable node.
1175
+ */
1176
+ for (nn = 0; nn < cfg->nsrv; nn++) {
1177
+ const lcbvb_SERVER *server = cfg->servers + nn;
1178
+ const lcbvb_SERVICES *svcs = mode == LCBVB_SVCMODE_PLAIN ?
1179
+ &server->svc : &server->svc_ssl;
1180
+ int has_svc = 0;
1181
+
1182
+ // Check if this node is in the exclude list
1183
+ if (used && used[nn]) {
1184
+ continue;
1185
+ }
1186
+
1187
+ has_svc =
1188
+ (type == LCBVB_SVCTYPE_DATA && svcs->data) ||
1189
+ (type == LCBVB_SVCTYPE_IXADMIN && svcs->ixadmin) ||
1190
+ (type == LCBVB_SVCTYPE_IXQUERY && svcs->ixquery) ||
1191
+ (type == LCBVB_SVCTYPE_MGMT && svcs->mgmt) ||
1192
+ (type == LCBVB_SVCTYPE_N1QL && svcs->n1ql) ||
1193
+ (type == LCBVB_SVCTYPE_FTS && svcs->fts) ||
1194
+ (type == LCBVB_SVCTYPE_VIEWS && svcs->views);
1195
+
1196
+ if (has_svc) {
1197
+ cfg->randbuf[oix++] = (int)nn;
1198
+ }
1199
+ }
1200
+
1201
+ if (!oix) {
1202
+ /* nothing supports it! */
1203
+ return -1;
1204
+ }
1205
+
1206
+ nn = rand();
1207
+ nn %= oix;
1208
+ return cfg->randbuf[nn];
1209
+ }
1210
+
1211
+ LIBCOUCHBASE_API
1212
+ int
1213
+ lcbvb_get_randhost(const lcbvb_CONFIG *cfg,
1214
+ lcbvb_SVCTYPE type, lcbvb_SVCMODE mode)
1215
+ {
1216
+ return lcbvb_get_randhost_ex(cfg, type, mode, NULL);
1217
+ }
1218
+
1219
+ LIBCOUCHBASE_API
1220
+ const char *
1221
+ lcbvb_get_resturl(lcbvb_CONFIG *cfg, unsigned ix,
1222
+ lcbvb_SVCTYPE svc, lcbvb_SVCMODE mode)
1223
+ {
1224
+ char **strp;
1225
+ char buf[4096];
1226
+ const char *prefix;
1227
+ const char *path;
1228
+
1229
+ lcbvb_SERVER *srv;
1230
+ lcbvb_SERVICES *svcs;
1231
+ unsigned port;
1232
+ port = lcbvb_get_port(cfg, ix, svc, mode);
1233
+ if (!port) {
1234
+ return NULL;
1235
+ }
1236
+
1237
+ srv = cfg->servers + ix;
1238
+ if (mode == LCBVB_SVCMODE_PLAIN) {
1239
+ prefix = "http";
1240
+ svcs = &srv->svc;
1241
+ } else {
1242
+ prefix = "https";
1243
+ svcs = &srv->svc_ssl;
1244
+ }
1245
+
1246
+ if (svc == LCBVB_SVCTYPE_VIEWS) {
1247
+ path = srv->viewpath;
1248
+ strp = &svcs->views_base_;
1249
+ } else if (svc == LCBVB_SVCTYPE_N1QL) {
1250
+ path = srv->querypath;
1251
+ strp = &svcs->query_base_;
1252
+ } else if (svc == LCBVB_SVCTYPE_FTS) {
1253
+ path = srv->ftspath;
1254
+ strp = &svcs->fts_base_;
1255
+ } else {
1256
+ /* Unknown service! */
1257
+ return NULL;
1258
+ }
1259
+
1260
+ if (path == NULL) {
1261
+ return NULL;
1262
+ } else if (!*strp) {
1263
+ sprintf(buf, "%s://%s:%d%s", prefix, srv->hostname, port, path);
1264
+ *strp = strdup(buf);
1265
+ }
1266
+
1267
+ return *strp;
1268
+ }
1269
+
1270
+ LIBCOUCHBASE_API
1271
+ const char *
1272
+ lcbvb_get_capibase(lcbvb_CONFIG *cfg, unsigned ix, lcbvb_SVCMODE mode)
1273
+ {
1274
+ return lcbvb_get_resturl(cfg, ix, LCBVB_SVCTYPE_VIEWS, mode);
1275
+ }
1276
+
1277
+ LIBCOUCHBASE_API int lcbvb_get_revision(const lcbvb_CONFIG *cfg) {
1278
+ return cfg->revid;
1279
+ }
1280
+ LIBCOUCHBASE_API unsigned lcbvb_get_nservers(const lcbvb_CONFIG *cfg) {
1281
+ return cfg->nsrv;
1282
+ }
1283
+ LIBCOUCHBASE_API unsigned lcbvb_get_nreplicas(const lcbvb_CONFIG *cfg) {
1284
+ return cfg->nrepl;
1285
+ }
1286
+ LIBCOUCHBASE_API lcbvb_DISTMODE lcbvb_get_distmode(const lcbvb_CONFIG *cfg) {
1287
+ return cfg->dtype;
1288
+ }
1289
+ LIBCOUCHBASE_API const char *lcbvb_get_error(const lcbvb_CONFIG *cfg) {
1290
+ return cfg->errstr;
1291
+ }
1292
+ /******************************************************************************
1293
+ ******************************************************************************
1294
+ ** Generation Functions **
1295
+ ******************************************************************************
1296
+ ******************************************************************************/
1297
+
1298
+ static void
1299
+ copy_service(const char *hostname,
1300
+ const lcbvb_SERVICES *src, lcbvb_SERVICES *dst)
1301
+ {
1302
+ char buf[4096];
1303
+ *dst = *src;
1304
+ memset(&dst->hoststrs, 0, sizeof dst->hoststrs);
1305
+ if (src->views_base_) {
1306
+ dst->views_base_ = strdup(src->views_base_);
1307
+ }
1308
+ if (src->query_base_) {
1309
+ dst->query_base_ = strdup(src->query_base_);
1310
+ }
1311
+ if (src->fts_base_) {
1312
+ dst->fts_base_ = strdup(src->fts_base_);
1313
+ }
1314
+ if (dst->data) {
1315
+ sprintf(buf, "%s:%d", hostname, dst->data);
1316
+ dst->hoststrs[LCBVB_SVCTYPE_DATA] = strdup(buf);
1317
+ }
1318
+ }
1319
+
1320
+ LIBCOUCHBASE_API
1321
+ int
1322
+ lcbvb_genconfig_ex(lcbvb_CONFIG *vb,
1323
+ const char *name, const char *uuid,
1324
+ const lcbvb_SERVER *servers,
1325
+ unsigned nservers, unsigned nreplica, unsigned nvbuckets)
1326
+ {
1327
+ unsigned ii, jj;
1328
+ int srvix = 0, in_nondata = 0;
1329
+
1330
+ assert(nservers);
1331
+
1332
+ if (!name) {
1333
+ name = "default";
1334
+ }
1335
+
1336
+ memset(vb, 0, sizeof(*vb));
1337
+ vb->dtype = LCBVB_DIST_VBUCKET;
1338
+ vb->nvb = nvbuckets;
1339
+ vb->nrepl = nreplica;
1340
+ vb->nsrv = nservers;
1341
+ vb->bname = strdup(name);
1342
+ if (uuid) {
1343
+ vb->buuid = strdup(uuid);
1344
+ }
1345
+
1346
+ if (nreplica >= nservers) {
1347
+ vb->errstr = "nservers must be > nreplicas";
1348
+ return -1;
1349
+ }
1350
+
1351
+ if (nreplica > 4) {
1352
+ vb->errstr = "Replicas must be <= 4";
1353
+ return -1;
1354
+ }
1355
+
1356
+ /* Count the number of data servers.. */
1357
+ for (ii = 0; ii < nservers; ii++) {
1358
+ const lcbvb_SERVER *server = servers + ii;
1359
+ if (server->svc.data) {
1360
+ if (in_nondata) {
1361
+ vb->errstr = "All data servers must be specified before non-data servers";
1362
+ return -1;
1363
+ }
1364
+ vb->ndatasrv++;
1365
+ } else {
1366
+ in_nondata = 1;
1367
+ }
1368
+ }
1369
+
1370
+ if (!vb->ndatasrv) {
1371
+ vb->errstr = "No data servers in list";
1372
+ return -1;
1373
+ }
1374
+
1375
+ vb->vbuckets = malloc(vb->nvb * sizeof(*vb->vbuckets));
1376
+ if (!vb->vbuckets) {
1377
+ vb->errstr = "Couldn't allocate vbucket array";
1378
+ return -1;
1379
+ }
1380
+
1381
+ for (ii = 0; ii < vb->nvb; ii++) {
1382
+ lcbvb_VBUCKET *cur = vb->vbuckets + ii;
1383
+ cur->servers[0] = srvix;
1384
+ for (jj = 1; jj < vb->nrepl+1; jj++) {
1385
+ cur->servers[jj] = (srvix + jj) % vb->ndatasrv;
1386
+ }
1387
+ srvix = (srvix + 1) % vb->ndatasrv;
1388
+ }
1389
+
1390
+ vb->servers = calloc(vb->nsrv, sizeof(*vb->servers));
1391
+ vb->randbuf = calloc(vb->nsrv, sizeof(*vb->randbuf));
1392
+
1393
+ for (ii = 0; ii < vb->nsrv; ii++) {
1394
+ lcbvb_SERVER *dst = vb->servers + ii;
1395
+ const lcbvb_SERVER *src = servers + ii;
1396
+
1397
+ *dst = *src;
1398
+ dst->hostname = strdup(src->hostname);
1399
+ if (src->viewpath) {
1400
+ dst->viewpath = strdup(src->viewpath);
1401
+ }
1402
+ if (src->querypath) {
1403
+ dst->querypath = strdup(src->querypath);
1404
+ }
1405
+ if (src->ftspath) {
1406
+ dst->ftspath = strdup(src->ftspath);
1407
+ }
1408
+
1409
+ copy_service(src->hostname, &src->svc, &dst->svc);
1410
+ copy_service(src->hostname, &src->svc_ssl, &dst->svc_ssl);
1411
+ dst->authority = dst->svc.hoststrs[LCBVB_SVCTYPE_DATA];
1412
+ }
1413
+
1414
+ for (ii = 0; ii < vb->nvb; ii++) {
1415
+ for (jj = 0; jj < vb->nrepl+1; jj++) {
1416
+ int ix = vb->vbuckets[ii].servers[jj];
1417
+ if (ix >= 0) {
1418
+ vb->servers[ix].nvbs++;
1419
+ }
1420
+ }
1421
+ }
1422
+ return 0;
1423
+ }
1424
+
1425
+ int
1426
+ lcbvb_genconfig(lcbvb_CONFIG *vb,
1427
+ unsigned nservers, unsigned nreplica, unsigned nvbuckets)
1428
+ {
1429
+ unsigned ii;
1430
+ int rv;
1431
+ lcbvb_SERVER *srvarry;
1432
+
1433
+ srvarry = calloc(nservers, sizeof(*srvarry));
1434
+ for (ii = 0; ii < nservers; ii++) {
1435
+ srvarry[ii].svc.data = 1000 + ii;
1436
+ srvarry[ii].svc.views = 2000 + ii;
1437
+ srvarry[ii].svc.mgmt = 3000 + ii;
1438
+ srvarry[ii].hostname = "localhost";
1439
+ srvarry[ii].svc.views_base_ = "/default";
1440
+ }
1441
+ rv = lcbvb_genconfig_ex(vb,
1442
+ "default", NULL, srvarry, nservers, nreplica, nvbuckets);
1443
+ free(srvarry);
1444
+ return rv;
1445
+ }
1446
+
1447
+ void
1448
+ lcbvb_genffmap(lcbvb_CONFIG *cfg)
1449
+ {
1450
+ size_t ii;
1451
+ assert(cfg->nrepl);
1452
+ if (cfg->ffvbuckets) {
1453
+ free(cfg->ffvbuckets);
1454
+ }
1455
+ cfg->ffvbuckets = calloc(cfg->nvb, sizeof *cfg->ffvbuckets);
1456
+ for (ii = 0; ii < cfg->nvb; ++ii) {
1457
+ size_t jj;
1458
+ lcbvb_VBUCKET *vb = cfg->ffvbuckets + ii;
1459
+ memcpy(vb, cfg->vbuckets + ii, sizeof *vb);
1460
+ for (jj = 0; jj < cfg->ndatasrv; ++jj) {
1461
+ vb->servers[jj] = (vb->servers[jj] + 1) % cfg->ndatasrv;
1462
+ }
1463
+ }
1464
+ }
1465
+
1466
+ void
1467
+ lcbvb_make_ketama(lcbvb_CONFIG *vb)
1468
+ {
1469
+ if (vb->dtype == LCBVB_DIST_KETAMA) {
1470
+ return;
1471
+ }
1472
+ vb->dtype = LCBVB_DIST_KETAMA;
1473
+ vb->nrepl = 0;
1474
+ vb->nvb = 0;
1475
+ update_ketama(vb);
1476
+ }
1477
+
1478
+
1479
+ /******************************************************************************
1480
+ ******************************************************************************
1481
+ ** Compatibility APIs **
1482
+ ******************************************************************************
1483
+ ******************************************************************************/
1484
+ LIBCOUCHBASE_API lcbvb_CONFIG* vbucket_config_create(void) {
1485
+ return lcbvb_create();
1486
+ }
1487
+ LIBCOUCHBASE_API void vbucket_config_destroy(lcbvb_CONFIG*h) {
1488
+ lcbvb_destroy(h);
1489
+ }
1490
+ LIBCOUCHBASE_API int vbucket_config_parse(lcbvb_CONFIG*h, vbucket_source_t src, const char *s) {
1491
+ (void)src; return lcbvb_load_json(h, s);
1492
+ }
1493
+ LIBCOUCHBASE_API const char * vbucket_get_error_message(lcbvb_CONFIG*h) {
1494
+ return h->errstr;
1495
+ }
1496
+ LIBCOUCHBASE_API int vbucket_config_get_num_servers(lcbvb_CONFIG *cfg) {
1497
+ return cfg->nsrv;
1498
+ }
1499
+ LIBCOUCHBASE_API int vbucket_config_get_num_replicas(lcbvb_CONFIG *cfg) {
1500
+ return cfg->nrepl;
1501
+ }
1502
+ LIBCOUCHBASE_API int vbucket_config_get_num_vbuckets(lcbvb_CONFIG *cfg) {
1503
+ return cfg->nvb;
1504
+ }
1505
+ LIBCOUCHBASE_API const char *vbucket_config_get_server(lcbvb_CONFIG *cfg, int ix) {
1506
+ return lcbvb_get_hostport(cfg, ix, LCBVB_SVCTYPE_DATA, LCBVB_SVCMODE_PLAIN);
1507
+ }
1508
+ LIBCOUCHBASE_API const char *vbucket_config_get_rest_api_server(lcbvb_CONFIG *cfg, int ix) {
1509
+ return lcbvb_get_hostport(cfg, ix, LCBVB_SVCTYPE_MGMT, LCBVB_SVCMODE_PLAIN);
1510
+ }
1511
+ LIBCOUCHBASE_API const char *vbucket_config_get_couch_api_base(lcbvb_CONFIG *cfg, int ix) {
1512
+ return lcbvb_get_capibase(cfg, ix, LCBVB_SVCMODE_PLAIN);
1513
+ }
1514
+ LIBCOUCHBASE_API lcbvb_DISTMODE vbucket_config_get_distribution_type(lcbvb_CONFIG *cfg) {
1515
+ return cfg->dtype;
1516
+ }
1517
+ LIBCOUCHBASE_API int vbucket_map(lcbvb_CONFIG *cfg, const void *k, lcb_SIZE nk, int *pvb, int *pix) {
1518
+ return lcbvb_map_key(cfg, k, nk, pvb, pix);
1519
+ }
1520
+ LIBCOUCHBASE_API int vbucket_get_vbucket_by_key(lcbvb_CONFIG *cfg, const void *k, lcb_SIZE nk) {
1521
+ return lcbvb_k2vb(cfg, k, nk);
1522
+ }
1523
+ LIBCOUCHBASE_API int vbucket_get_master(lcbvb_CONFIG *cfg, int vb) {
1524
+ return lcbvb_vbmaster(cfg, vb);
1525
+ }
1526
+ LIBCOUCHBASE_API int vbucket_get_replica(lcbvb_CONFIG *cfg, int vb, int repl) {
1527
+ return lcbvb_vbreplica(cfg, vb, repl);
1528
+ }
1529
+ LIBCOUCHBASE_API lcbvb_CONFIGDIFF *vbucket_compare(lcbvb_CONFIG*a,lcbvb_CONFIG*b) {
1530
+ return lcbvb_compare(a,b);
1531
+ }
1532
+ LIBCOUCHBASE_API void vbucket_free_diff(lcbvb_CONFIGDIFF *p) {
1533
+ lcbvb_free_diff(p);
1534
+ }
1535
+ LIBCOUCHBASE_API int vbucket_config_get_revision(lcbvb_CONFIG *p) {
1536
+ return lcbvb_get_revision(p);
1537
+ }
1538
+ LIBCOUCHBASE_API lcbvb_CHANGETYPE vbucket_what_changed(lcbvb_CONFIGDIFF *diff) {
1539
+ return lcbvb_get_changetype(diff);
1540
+ }
1541
+ LIBCOUCHBASE_API int vbucket_config_generate(lcbvb_CONFIG*cfg, unsigned nsrv, unsigned nrepl, unsigned nvb) {
1542
+ return lcbvb_genconfig(cfg,nsrv,nrepl,nvb);
1543
+ }