heroku-tokyotyrant 0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (340) hide show
  1. data/COPYING +504 -0
  2. data/README.rdoc +231 -0
  3. data/Rakefile +72 -0
  4. data/benchmarks/balancer.rb +101 -0
  5. data/benchmarks/bulk_db.rb +74 -0
  6. data/benchmarks/bulk_table.rb +87 -0
  7. data/benchmarks/db.rb +114 -0
  8. data/benchmarks/table.rb +161 -0
  9. data/ext/extconf.rb +43 -0
  10. data/ext/tokyo/bin/tcamgr +0 -0
  11. data/ext/tokyo/bin/tcamttest +0 -0
  12. data/ext/tokyo/bin/tcatest +0 -0
  13. data/ext/tokyo/bin/tcbmgr +0 -0
  14. data/ext/tokyo/bin/tcbmttest +0 -0
  15. data/ext/tokyo/bin/tcbtest +0 -0
  16. data/ext/tokyo/bin/tcfmgr +0 -0
  17. data/ext/tokyo/bin/tcfmttest +0 -0
  18. data/ext/tokyo/bin/tcftest +0 -0
  19. data/ext/tokyo/bin/tchmgr +0 -0
  20. data/ext/tokyo/bin/tchmttest +0 -0
  21. data/ext/tokyo/bin/tchtest +0 -0
  22. data/ext/tokyo/bin/tcrmgr +0 -0
  23. data/ext/tokyo/bin/tcrmttest +0 -0
  24. data/ext/tokyo/bin/tcrtest +0 -0
  25. data/ext/tokyo/bin/tctmgr +0 -0
  26. data/ext/tokyo/bin/tctmttest +0 -0
  27. data/ext/tokyo/bin/tcttest +0 -0
  28. data/ext/tokyo/bin/tcucodec +0 -0
  29. data/ext/tokyo/bin/tcumttest +0 -0
  30. data/ext/tokyo/bin/tcutest +0 -0
  31. data/ext/tokyo/bin/ttserver +0 -0
  32. data/ext/tokyo/bin/ttulmgr +0 -0
  33. data/ext/tokyo/bin/ttultest +0 -0
  34. data/ext/tokyo/include/tcadb.h +548 -0
  35. data/ext/tokyo/include/tcbdb.h +1101 -0
  36. data/ext/tokyo/include/tcfdb.h +858 -0
  37. data/ext/tokyo/include/tchdb.h +871 -0
  38. data/ext/tokyo/include/tcrdb.h +801 -0
  39. data/ext/tokyo/include/tctdb.h +1086 -0
  40. data/ext/tokyo/include/tculog.h +392 -0
  41. data/ext/tokyo/include/tcutil.h +4184 -0
  42. data/ext/tokyo/include/ttutil.h +494 -0
  43. data/ext/tokyo/lib/libtokyocabinet.9.4.0.dylib +0 -0
  44. data/ext/tokyo/lib/libtokyocabinet.9.dylib +0 -0
  45. data/ext/tokyo/lib/libtokyocabinet.a +0 -0
  46. data/ext/tokyo/lib/libtokyocabinet.dylib +0 -0
  47. data/ext/tokyo/lib/libtokyotyrant.3.22.0.dylib +0 -0
  48. data/ext/tokyo/lib/libtokyotyrant.3.dylib +0 -0
  49. data/ext/tokyo/lib/libtokyotyrant.a +0 -0
  50. data/ext/tokyo/lib/libtokyotyrant.dylib +0 -0
  51. data/ext/tokyo/lib/pkgconfig/tokyocabinet.pc +14 -0
  52. data/ext/tokyo/lib/pkgconfig/tokyotyrant.pc +14 -0
  53. data/ext/tokyo/lib/ttskeldir.bundle +0 -0
  54. data/ext/tokyo/lib/ttskelmock.bundle +0 -0
  55. data/ext/tokyo/lib/ttskelnull.bundle +0 -0
  56. data/ext/tokyo/lib/ttskelproxy.bundle +0 -0
  57. data/ext/tokyo/libexec/tcawmgr.cgi +0 -0
  58. data/ext/tokyo/sbin/ttservctl +163 -0
  59. data/ext/tokyo/share/man/man1/tcamgr.1 +97 -0
  60. data/ext/tokyo/share/man/man1/tcamttest.1 +35 -0
  61. data/ext/tokyo/share/man/man1/tcatest.1 +55 -0
  62. data/ext/tokyo/share/man/man1/tcbmgr.1 +125 -0
  63. data/ext/tokyo/share/man/man1/tcbmttest.1 +81 -0
  64. data/ext/tokyo/share/man/man1/tcbtest.1 +107 -0
  65. data/ext/tokyo/share/man/man1/tcfmgr.1 +98 -0
  66. data/ext/tokyo/share/man/man1/tcfmttest.1 +62 -0
  67. data/ext/tokyo/share/man/man1/tcftest.1 +73 -0
  68. data/ext/tokyo/share/man/man1/tchmgr.1 +110 -0
  69. data/ext/tokyo/share/man/man1/tchmttest.1 +85 -0
  70. data/ext/tokyo/share/man/man1/tchtest.1 +95 -0
  71. data/ext/tokyo/share/man/man1/tcrmgr.1 +164 -0
  72. data/ext/tokyo/share/man/man1/tcrmttest.1 +55 -0
  73. data/ext/tokyo/share/man/man1/tcrtest.1 +89 -0
  74. data/ext/tokyo/share/man/man1/tctmgr.1 +140 -0
  75. data/ext/tokyo/share/man/man1/tctmttest.1 +92 -0
  76. data/ext/tokyo/share/man/man1/tcttest.1 +105 -0
  77. data/ext/tokyo/share/man/man1/tcucodec.1 +162 -0
  78. data/ext/tokyo/share/man/man1/tcumttest.1 +41 -0
  79. data/ext/tokyo/share/man/man1/tcutest.1 +81 -0
  80. data/ext/tokyo/share/man/man1/ttserver.1 +84 -0
  81. data/ext/tokyo/share/man/man1/ttulmgr.1 +40 -0
  82. data/ext/tokyo/share/man/man1/ttultest.1 +16 -0
  83. data/ext/tokyo/share/man/man3/tcadb.3 +676 -0
  84. data/ext/tokyo/share/man/man3/tcbdb.3 +1355 -0
  85. data/ext/tokyo/share/man/man3/tcfdb.3 +975 -0
  86. data/ext/tokyo/share/man/man3/tchdb.3 +898 -0
  87. data/ext/tokyo/share/man/man3/tclist.3 +1 -0
  88. data/ext/tokyo/share/man/man3/tcmap.3 +1 -0
  89. data/ext/tokyo/share/man/man3/tcmdb.3 +1 -0
  90. data/ext/tokyo/share/man/man3/tcmpool.3 +1 -0
  91. data/ext/tokyo/share/man/man3/tcrdb.3 +1309 -0
  92. data/ext/tokyo/share/man/man3/tctdb.3 +1110 -0
  93. data/ext/tokyo/share/man/man3/tctree.3 +1 -0
  94. data/ext/tokyo/share/man/man3/tculog.3 +15 -0
  95. data/ext/tokyo/share/man/man3/tcutil.3 +4518 -0
  96. data/ext/tokyo/share/man/man3/tcxstr.3 +1 -0
  97. data/ext/tokyo/share/man/man3/tokyocabinet.3 +132 -0
  98. data/ext/tokyo/share/man/man3/ttutil.3 +14 -0
  99. data/ext/tokyo/share/man/man8/ttservctl.8 +37 -0
  100. data/ext/tokyo/share/tokyocabinet/COPYING +504 -0
  101. data/ext/tokyo/share/tokyocabinet/ChangeLog +1252 -0
  102. data/ext/tokyo/share/tokyocabinet/THANKS +12 -0
  103. data/ext/tokyo/share/tokyocabinet/doc/benchmark.pdf +0 -0
  104. data/ext/tokyo/share/tokyocabinet/doc/common.css +211 -0
  105. data/ext/tokyo/share/tokyocabinet/doc/icon16.png +0 -0
  106. data/ext/tokyo/share/tokyocabinet/doc/index.html +156 -0
  107. data/ext/tokyo/share/tokyocabinet/doc/index.ja.html +197 -0
  108. data/ext/tokyo/share/tokyocabinet/doc/logo-ja.png +0 -0
  109. data/ext/tokyo/share/tokyocabinet/doc/logo.png +0 -0
  110. data/ext/tokyo/share/tokyocabinet/doc/spex-en.html +7145 -0
  111. data/ext/tokyo/share/tokyocabinet/doc/spex-ja.html +7476 -0
  112. data/ext/tokyo/share/tokyocabinet/doc/tokyoproducts.pdf +0 -0
  113. data/ext/tokyo/share/tokyocabinet/doc/tokyoproducts.ppt +0 -0
  114. data/ext/tokyo/share/tokyotyrant/COPYING +504 -0
  115. data/ext/tokyo/share/tokyotyrant/ChangeLog +578 -0
  116. data/ext/tokyo/share/tokyotyrant/THANKS +15 -0
  117. data/ext/tokyo/share/tokyotyrant/doc/common.css +211 -0
  118. data/ext/tokyo/share/tokyotyrant/doc/index.html +79 -0
  119. data/ext/tokyo/share/tokyotyrant/doc/spex.html +2264 -0
  120. data/ext/tokyo/share/tokyotyrant/ext/mapreduce.lua +57 -0
  121. data/ext/tokyo/share/tokyotyrant/ext/queue.lua +55 -0
  122. data/ext/tokyo/share/tokyotyrant/ext/senatus.lua +532 -0
  123. data/ext/tokyo/share/tokyotyrant/ext/usherette.lua +438 -0
  124. data/ext/tokyo_tyrant.c +147 -0
  125. data/ext/tokyo_tyrant.h +48 -0
  126. data/ext/tokyo_tyrant_db.c +227 -0
  127. data/ext/tokyo_tyrant_db.h +8 -0
  128. data/ext/tokyo_tyrant_module.c +453 -0
  129. data/ext/tokyo_tyrant_module.h +10 -0
  130. data/ext/tokyo_tyrant_query.c +226 -0
  131. data/ext/tokyo_tyrant_query.h +9 -0
  132. data/ext/tokyo_tyrant_table.c +319 -0
  133. data/ext/tokyo_tyrant_table.h +8 -0
  134. data/ext/tokyocabinet-1.4.41/COPYING +504 -0
  135. data/ext/tokyocabinet-1.4.41/ChangeLog +1252 -0
  136. data/ext/tokyocabinet-1.4.41/Makefile.in +825 -0
  137. data/ext/tokyocabinet-1.4.41/README +38 -0
  138. data/ext/tokyocabinet-1.4.41/THANKS +12 -0
  139. data/ext/tokyocabinet-1.4.41/bros/Makefile +133 -0
  140. data/ext/tokyocabinet-1.4.41/bros/bdbtest.c +438 -0
  141. data/ext/tokyocabinet-1.4.41/bros/cdbtest.c +219 -0
  142. data/ext/tokyocabinet-1.4.41/bros/cmpsqltctest.c +186 -0
  143. data/ext/tokyocabinet-1.4.41/bros/gdbmtest.c +216 -0
  144. data/ext/tokyocabinet-1.4.41/bros/mapreporter +72 -0
  145. data/ext/tokyocabinet-1.4.41/bros/maptest.cc +677 -0
  146. data/ext/tokyocabinet-1.4.41/bros/ndbmtest.c +204 -0
  147. data/ext/tokyocabinet-1.4.41/bros/qdbmtest.c +375 -0
  148. data/ext/tokyocabinet-1.4.41/bros/reporter +141 -0
  149. data/ext/tokyocabinet-1.4.41/bros/result.xls +0 -0
  150. data/ext/tokyocabinet-1.4.41/bros/sdbmtest.c +204 -0
  151. data/ext/tokyocabinet-1.4.41/bros/sqltest.c +404 -0
  152. data/ext/tokyocabinet-1.4.41/bros/tctest.c +748 -0
  153. data/ext/tokyocabinet-1.4.41/bros/tdbtest.c +205 -0
  154. data/ext/tokyocabinet-1.4.41/configure +7402 -0
  155. data/ext/tokyocabinet-1.4.41/configure.in +362 -0
  156. data/ext/tokyocabinet-1.4.41/doc/benchmark.pdf +0 -0
  157. data/ext/tokyocabinet-1.4.41/doc/common.css +211 -0
  158. data/ext/tokyocabinet-1.4.41/doc/icon16.png +0 -0
  159. data/ext/tokyocabinet-1.4.41/doc/index.html +156 -0
  160. data/ext/tokyocabinet-1.4.41/doc/index.ja.html +197 -0
  161. data/ext/tokyocabinet-1.4.41/doc/logo-ja.png +0 -0
  162. data/ext/tokyocabinet-1.4.41/doc/logo.png +0 -0
  163. data/ext/tokyocabinet-1.4.41/doc/spex-en.html +7145 -0
  164. data/ext/tokyocabinet-1.4.41/doc/spex-ja.html +7476 -0
  165. data/ext/tokyocabinet-1.4.41/doc/tokyoproducts.pdf +0 -0
  166. data/ext/tokyocabinet-1.4.41/doc/tokyoproducts.ppt +0 -0
  167. data/ext/tokyocabinet-1.4.41/example/Makefile +113 -0
  168. data/ext/tokyocabinet-1.4.41/example/tcadbex.c +55 -0
  169. data/ext/tokyocabinet-1.4.41/example/tcbdbex.c +64 -0
  170. data/ext/tokyocabinet-1.4.41/example/tcfdbex.c +60 -0
  171. data/ext/tokyocabinet-1.4.41/example/tchdbex.c +60 -0
  172. data/ext/tokyocabinet-1.4.41/example/tctchat.c +97 -0
  173. data/ext/tokyocabinet-1.4.41/example/tctchat.tmpl +141 -0
  174. data/ext/tokyocabinet-1.4.41/example/tctdbex.c +85 -0
  175. data/ext/tokyocabinet-1.4.41/example/tctsearch.c +95 -0
  176. data/ext/tokyocabinet-1.4.41/example/tctsearch.tmpl +122 -0
  177. data/ext/tokyocabinet-1.4.41/example/tcutilex.c +77 -0
  178. data/ext/tokyocabinet-1.4.41/f.tsv +2 -0
  179. data/ext/tokyocabinet-1.4.41/lab/calccomp +118 -0
  180. data/ext/tokyocabinet-1.4.41/lab/datechange +56 -0
  181. data/ext/tokyocabinet-1.4.41/lab/diffcheck +45 -0
  182. data/ext/tokyocabinet-1.4.41/lab/htmltotsv +102 -0
  183. data/ext/tokyocabinet-1.4.41/lab/magic +19 -0
  184. data/ext/tokyocabinet-1.4.41/lab/printenv.cgi +27 -0
  185. data/ext/tokyocabinet-1.4.41/lab/stepcount +26 -0
  186. data/ext/tokyocabinet-1.4.41/lab/stopwatch +61 -0
  187. data/ext/tokyocabinet-1.4.41/lab/tabcheck +43 -0
  188. data/ext/tokyocabinet-1.4.41/lab/wgettsv +239 -0
  189. data/ext/tokyocabinet-1.4.41/lab/widthcheck +57 -0
  190. data/ext/tokyocabinet-1.4.41/man/htmltoman +104 -0
  191. data/ext/tokyocabinet-1.4.41/man/tcadb.3 +676 -0
  192. data/ext/tokyocabinet-1.4.41/man/tcamgr.1 +97 -0
  193. data/ext/tokyocabinet-1.4.41/man/tcamttest.1 +35 -0
  194. data/ext/tokyocabinet-1.4.41/man/tcatest.1 +55 -0
  195. data/ext/tokyocabinet-1.4.41/man/tcbdb.3 +1355 -0
  196. data/ext/tokyocabinet-1.4.41/man/tcbmgr.1 +125 -0
  197. data/ext/tokyocabinet-1.4.41/man/tcbmttest.1 +81 -0
  198. data/ext/tokyocabinet-1.4.41/man/tcbtest.1 +107 -0
  199. data/ext/tokyocabinet-1.4.41/man/tcfdb.3 +975 -0
  200. data/ext/tokyocabinet-1.4.41/man/tcfmgr.1 +98 -0
  201. data/ext/tokyocabinet-1.4.41/man/tcfmttest.1 +62 -0
  202. data/ext/tokyocabinet-1.4.41/man/tcftest.1 +73 -0
  203. data/ext/tokyocabinet-1.4.41/man/tchdb.3 +898 -0
  204. data/ext/tokyocabinet-1.4.41/man/tchmgr.1 +110 -0
  205. data/ext/tokyocabinet-1.4.41/man/tchmttest.1 +85 -0
  206. data/ext/tokyocabinet-1.4.41/man/tchtest.1 +95 -0
  207. data/ext/tokyocabinet-1.4.41/man/tclist.3 +1 -0
  208. data/ext/tokyocabinet-1.4.41/man/tcmap.3 +1 -0
  209. data/ext/tokyocabinet-1.4.41/man/tcmdb.3 +1 -0
  210. data/ext/tokyocabinet-1.4.41/man/tcmpool.3 +1 -0
  211. data/ext/tokyocabinet-1.4.41/man/tctdb.3 +1110 -0
  212. data/ext/tokyocabinet-1.4.41/man/tctmgr.1 +140 -0
  213. data/ext/tokyocabinet-1.4.41/man/tctmttest.1 +92 -0
  214. data/ext/tokyocabinet-1.4.41/man/tctree.3 +1 -0
  215. data/ext/tokyocabinet-1.4.41/man/tcttest.1 +105 -0
  216. data/ext/tokyocabinet-1.4.41/man/tcucodec.1 +162 -0
  217. data/ext/tokyocabinet-1.4.41/man/tcumttest.1 +41 -0
  218. data/ext/tokyocabinet-1.4.41/man/tcutest.1 +81 -0
  219. data/ext/tokyocabinet-1.4.41/man/tcutil.3 +4518 -0
  220. data/ext/tokyocabinet-1.4.41/man/tcxstr.3 +1 -0
  221. data/ext/tokyocabinet-1.4.41/man/tokyocabinet.3 +132 -0
  222. data/ext/tokyocabinet-1.4.41/md5.c +381 -0
  223. data/ext/tokyocabinet-1.4.41/md5.h +101 -0
  224. data/ext/tokyocabinet-1.4.41/myconf.c +493 -0
  225. data/ext/tokyocabinet-1.4.41/myconf.h +549 -0
  226. data/ext/tokyocabinet-1.4.41/tcadb.c +4339 -0
  227. data/ext/tokyocabinet-1.4.41/tcadb.h +548 -0
  228. data/ext/tokyocabinet-1.4.41/tcamgr.c +1019 -0
  229. data/ext/tokyocabinet-1.4.41/tcamttest.c +542 -0
  230. data/ext/tokyocabinet-1.4.41/tcatest.c +1845 -0
  231. data/ext/tokyocabinet-1.4.41/tcawmgr.c +482 -0
  232. data/ext/tokyocabinet-1.4.41/tcbdb.c +4180 -0
  233. data/ext/tokyocabinet-1.4.41/tcbdb.h +1101 -0
  234. data/ext/tokyocabinet-1.4.41/tcbmgr.c +1012 -0
  235. data/ext/tokyocabinet-1.4.41/tcbmttest.c +1810 -0
  236. data/ext/tokyocabinet-1.4.41/tcbtest.c +2586 -0
  237. data/ext/tokyocabinet-1.4.41/tcfdb.c +2746 -0
  238. data/ext/tokyocabinet-1.4.41/tcfdb.h +858 -0
  239. data/ext/tokyocabinet-1.4.41/tcfmgr.c +786 -0
  240. data/ext/tokyocabinet-1.4.41/tcfmttest.c +1220 -0
  241. data/ext/tokyocabinet-1.4.41/tcftest.c +1695 -0
  242. data/ext/tokyocabinet-1.4.41/tchdb.c +5153 -0
  243. data/ext/tokyocabinet-1.4.41/tchdb.h +871 -0
  244. data/ext/tokyocabinet-1.4.41/tchmgr.c +842 -0
  245. data/ext/tokyocabinet-1.4.41/tchmttest.c +1757 -0
  246. data/ext/tokyocabinet-1.4.41/tchtest.c +2129 -0
  247. data/ext/tokyocabinet-1.4.41/tctdb.c +6199 -0
  248. data/ext/tokyocabinet-1.4.41/tctdb.h +1086 -0
  249. data/ext/tokyocabinet-1.4.41/tctmgr.c +1241 -0
  250. data/ext/tokyocabinet-1.4.41/tctmttest.c +1563 -0
  251. data/ext/tokyocabinet-1.4.41/tcttest.c +2062 -0
  252. data/ext/tokyocabinet-1.4.41/tcucodec.c +1357 -0
  253. data/ext/tokyocabinet-1.4.41/tcumttest.c +578 -0
  254. data/ext/tokyocabinet-1.4.41/tcutest.c +1875 -0
  255. data/ext/tokyocabinet-1.4.41/tcutil.c +10528 -0
  256. data/ext/tokyocabinet-1.4.41/tcutil.h +4184 -0
  257. data/ext/tokyocabinet-1.4.41/tokyocabinet.idl +336 -0
  258. data/ext/tokyocabinet-1.4.41/tokyocabinet.pc.in +14 -0
  259. data/ext/tokyotyrant-1.1.39/COPYING +504 -0
  260. data/ext/tokyotyrant-1.1.39/ChangeLog +578 -0
  261. data/ext/tokyotyrant-1.1.39/Makefile.in +365 -0
  262. data/ext/tokyotyrant-1.1.39/README +38 -0
  263. data/ext/tokyotyrant-1.1.39/THANKS +15 -0
  264. data/ext/tokyotyrant-1.1.39/configure +6979 -0
  265. data/ext/tokyotyrant-1.1.39/configure.in +300 -0
  266. data/ext/tokyotyrant-1.1.39/doc/common.css +211 -0
  267. data/ext/tokyotyrant-1.1.39/doc/index.html +79 -0
  268. data/ext/tokyotyrant-1.1.39/doc/spex.html +2264 -0
  269. data/ext/tokyotyrant-1.1.39/example/Makefile +68 -0
  270. data/ext/tokyotyrant-1.1.39/example/httptest.pl +88 -0
  271. data/ext/tokyotyrant-1.1.39/example/mcftest.pl +39 -0
  272. data/ext/tokyotyrant-1.1.39/example/mctest.pl +43 -0
  273. data/ext/tokyotyrant-1.1.39/example/tcrdbex +0 -0
  274. data/ext/tokyotyrant-1.1.39/example/tcrdbex.c +49 -0
  275. data/ext/tokyotyrant-1.1.39/example/tcrdbex.o +0 -0
  276. data/ext/tokyotyrant-1.1.39/example/tcrdbtblex +0 -0
  277. data/ext/tokyotyrant-1.1.39/example/tcrdbtblex.c +79 -0
  278. data/ext/tokyotyrant-1.1.39/example/tcrdbtblex.o +0 -0
  279. data/ext/tokyotyrant-1.1.39/ext/mapreduce.lua +57 -0
  280. data/ext/tokyotyrant-1.1.39/ext/queue.lua +55 -0
  281. data/ext/tokyotyrant-1.1.39/ext/senatus.lua +532 -0
  282. data/ext/tokyotyrant-1.1.39/ext/usherette.lua +438 -0
  283. data/ext/tokyotyrant-1.1.39/lab/datechange +56 -0
  284. data/ext/tokyotyrant-1.1.39/lab/diffcheck +45 -0
  285. data/ext/tokyotyrant-1.1.39/lab/fibonacci.lua +20 -0
  286. data/ext/tokyotyrant-1.1.39/lab/footprint.lua +67 -0
  287. data/ext/tokyotyrant-1.1.39/lab/highlow.lua +88 -0
  288. data/ext/tokyotyrant-1.1.39/lab/killdualmaster +12 -0
  289. data/ext/tokyotyrant-1.1.39/lab/rundualmaster +38 -0
  290. data/ext/tokyotyrant-1.1.39/lab/stepcount +26 -0
  291. data/ext/tokyotyrant-1.1.39/lab/tabcheck +43 -0
  292. data/ext/tokyotyrant-1.1.39/lab/ushrtregister.pl +55 -0
  293. data/ext/tokyotyrant-1.1.39/lab/widthcheck +57 -0
  294. data/ext/tokyotyrant-1.1.39/man/htmltoman +100 -0
  295. data/ext/tokyotyrant-1.1.39/man/tcrdb.3 +1309 -0
  296. data/ext/tokyotyrant-1.1.39/man/tcrmgr.1 +164 -0
  297. data/ext/tokyotyrant-1.1.39/man/tcrmttest.1 +55 -0
  298. data/ext/tokyotyrant-1.1.39/man/tcrtest.1 +89 -0
  299. data/ext/tokyotyrant-1.1.39/man/tculog.3 +15 -0
  300. data/ext/tokyotyrant-1.1.39/man/ttservctl.8 +37 -0
  301. data/ext/tokyotyrant-1.1.39/man/ttserver.1 +84 -0
  302. data/ext/tokyotyrant-1.1.39/man/ttulmgr.1 +40 -0
  303. data/ext/tokyotyrant-1.1.39/man/ttultest.1 +16 -0
  304. data/ext/tokyotyrant-1.1.39/man/ttutil.3 +14 -0
  305. data/ext/tokyotyrant-1.1.39/myconf.c +169 -0
  306. data/ext/tokyotyrant-1.1.39/myconf.h +408 -0
  307. data/ext/tokyotyrant-1.1.39/scrext.c +2394 -0
  308. data/ext/tokyotyrant-1.1.39/scrext.h +96 -0
  309. data/ext/tokyotyrant-1.1.39/tcrdb.c +2637 -0
  310. data/ext/tokyotyrant-1.1.39/tcrdb.h +801 -0
  311. data/ext/tokyotyrant-1.1.39/tcrmgr.c +1559 -0
  312. data/ext/tokyotyrant-1.1.39/tcrmttest.c +915 -0
  313. data/ext/tokyotyrant-1.1.39/tcrtest.c +1542 -0
  314. data/ext/tokyotyrant-1.1.39/tculog.c +1211 -0
  315. data/ext/tokyotyrant-1.1.39/tculog.h +392 -0
  316. data/ext/tokyotyrant-1.1.39/tokyotyrant.idl +143 -0
  317. data/ext/tokyotyrant-1.1.39/tokyotyrant.pc.in +14 -0
  318. data/ext/tokyotyrant-1.1.39/ttservctl +163 -0
  319. data/ext/tokyotyrant-1.1.39/ttserver.c +3583 -0
  320. data/ext/tokyotyrant-1.1.39/ttskeldir.c +141 -0
  321. data/ext/tokyotyrant-1.1.39/ttskelmock.c +64 -0
  322. data/ext/tokyotyrant-1.1.39/ttskelnull.c +79 -0
  323. data/ext/tokyotyrant-1.1.39/ttskelproxy.c +74 -0
  324. data/ext/tokyotyrant-1.1.39/ttulmgr.c +266 -0
  325. data/ext/tokyotyrant-1.1.39/ttultest.c +371 -0
  326. data/ext/tokyotyrant-1.1.39/ttutil.c +1510 -0
  327. data/ext/tokyotyrant-1.1.39/ttutil.h +494 -0
  328. data/lib/tokyo_tyrant/balancer.rb +189 -0
  329. data/spec/ext.lua +4 -0
  330. data/spec/plu_db.rb +538 -0
  331. data/spec/spec.rb +1 -0
  332. data/spec/spec_base.rb +17 -0
  333. data/spec/start_tyrants.sh +36 -0
  334. data/spec/stop_tyrants.sh +9 -0
  335. data/spec/tokyo_tyrant_balancer_db_spec.rb +160 -0
  336. data/spec/tokyo_tyrant_balancer_table_spec.rb +177 -0
  337. data/spec/tokyo_tyrant_query_spec.rb +159 -0
  338. data/spec/tokyo_tyrant_spec.rb +254 -0
  339. data/spec/tokyo_tyrant_table_spec.rb +301 -0
  340. metadata +402 -0
@@ -0,0 +1,96 @@
1
+ /*************************************************************************************************
2
+ * Scripting language extension of Tokyo Tyrant
3
+ * Copyright (C) 2006-2009 Mikio Hirabayashi
4
+ * This file is part of Tokyo Tyrant.
5
+ * Tokyo Tyrant is free software; you can redistribute it and/or modify it under the terms of
6
+ * the GNU Lesser General Public License as published by the Free Software Foundation; either
7
+ * version 2.1 of the License or any later version. Tokyo Tyrant is distributed in the hope
8
+ * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
10
+ * License for more details.
11
+ * You should have received a copy of the GNU Lesser General Public License along with Tokyo
12
+ * Tyrant; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
13
+ * Boston, MA 02111-1307 USA.
14
+ *************************************************************************************************/
15
+
16
+
17
+ #ifndef _SCREXT_H // duplication check
18
+ #define _SCREXT_H
19
+
20
+
21
+
22
+ /*************************************************************************************************
23
+ * configuration
24
+ *************************************************************************************************/
25
+
26
+
27
+ #include "myconf.h"
28
+ #include <ttutil.h>
29
+ #include <tculog.h>
30
+ #include <tcrdb.h>
31
+
32
+
33
+ #if defined(_MYLUA)
34
+ #define TTLUAEXT
35
+ #else
36
+ #define TTNOEXT
37
+ #endif
38
+
39
+
40
+
41
+ /*************************************************************************************************
42
+ * pseudo API
43
+ *************************************************************************************************/
44
+
45
+
46
+ /* Initialize the scripting language extension.
47
+ `screxts' specifies an array of the scripting language extension objects.
48
+ `thnum' specifies the number of the native threads.
49
+ `thid' specifies the thread ID number.
50
+ `path' specifies the path of the initilizing script.
51
+ `adb' specifies the abstract database object.
52
+ `ulog' specifies the update log object.
53
+ `sid' specifies the server ID.
54
+ `stash' specifies the global stash object.
55
+ `lock' specifies the global lock object.
56
+ `logger' specifies the pointer to a function to do with a log message.
57
+ `logopq' specifies the opaque pointer for the logging function.
58
+ The return value is the scripting object or `NULL' on failure. */
59
+ void *scrextnew(void **screxts, int thnum, int thid, const char *path,
60
+ TCADB *adb, TCULOG *ulog, uint32_t sid, TCMDB *stash, TCMDB *lock,
61
+ void (*logger)(int, const char *, void *), void *logopq);
62
+
63
+
64
+ /* Destroy the scripting language extension.
65
+ `scr' specifies the scripting object.
66
+ If successful, the return value is true, else, it is false. */
67
+ bool scrextdel(void *scr);
68
+
69
+
70
+ /* Call a method of the scripting language extension.
71
+ `scr' specifies the scripting object.
72
+ `name' specifies the name of the method to be called.
73
+ `kbuf' specifies the pointer to the region of the key.
74
+ `ksiz' specifies the size of the region of the key.
75
+ `vbuf' specifies the pointer to the region of the value.
76
+ `vsiz' specifies the size of the region of the value.
77
+ `sp' specifies the pointer to the variable into which the size of the region of the return
78
+ value is assigned.
79
+ If successful, the return value is the pointer to the region of the value of the corresponding
80
+ record. It should be allocated by `malloc' call. `NULL' is returned on failure.
81
+ Note that the returned region is released by the caller. */
82
+ char *scrextcallmethod(void *scr, const char *name,
83
+ const void *kbuf, int ksiz, const void *vbuf, int vsiz, int *sp);
84
+
85
+
86
+ /* Send the terminate signal to the scripting language extension.
87
+ `scr' specifies the scripting object.
88
+ If successful, the return value is true, else, it is false. */
89
+ bool scrextkill(void *scr);
90
+
91
+
92
+
93
+ #endif // duplication check
94
+
95
+
96
+ // END OF FILE
@@ -0,0 +1,2637 @@
1
+ /*************************************************************************************************
2
+ * The remote database API of Tokyo Tyrant
3
+ * Copyright (C) 2006-2009 Mikio Hirabayashi
4
+ * This file is part of Tokyo Tyrant.
5
+ * Tokyo Tyrant is free software; you can redistribute it and/or modify it under the terms of
6
+ * the GNU Lesser General Public License as published by the Free Software Foundation; either
7
+ * version 2.1 of the License or any later version. Tokyo Tyrant is distributed in the hope
8
+ * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
10
+ * License for more details.
11
+ * You should have received a copy of the GNU Lesser General Public License along with Tokyo
12
+ * Tyrant; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
13
+ * Boston, MA 02111-1307 USA.
14
+ *************************************************************************************************/
15
+
16
+
17
+ #include "tcutil.h"
18
+ #include "tcadb.h"
19
+ #include "ttutil.h"
20
+ #include "tcrdb.h"
21
+ #include "myconf.h"
22
+
23
+ #define RDBRECONWAIT 0.1 // wait time to reconnect
24
+ #define RDBNUMCOLMAX 16 // maximum number of columns of the long double
25
+
26
+ typedef struct { // type of structure for a meta search query
27
+ pthread_t tid; // thread ID number
28
+ RDBQRY *qry; // query object
29
+ TCLIST *res; // response object
30
+ int max; // max number of retrieval
31
+ int skip; // skipping number of retrieval
32
+ } PARASEARCHARG;
33
+
34
+ typedef struct { // type of structure for a sort record
35
+ const char *cbuf; // pointer to the column buffer
36
+ int csiz; // size of the column buffer
37
+ char *obuf; // pointer to the sort key
38
+ int osiz; // size of the sort key
39
+ } RDBSORTREC;
40
+
41
+
42
+ /* private function prototypes */
43
+ static bool tcrdblockmethod(TCRDB *rdb);
44
+ static void tcrdbunlockmethod(TCRDB *rdb);
45
+ static bool tcrdbreconnect(TCRDB *rdb);
46
+ static bool tcrdbsend(TCRDB *rdb, const void *buf, int size);
47
+ static bool tcrdbtuneimpl(TCRDB *rdb, double timeout, int opts);
48
+ static bool tcrdbopenimpl(TCRDB *rdb, const char *host, int port);
49
+ static bool tcrdbcloseimpl(TCRDB *rdb);
50
+ static bool tcrdbputimpl(TCRDB *rdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
51
+ static bool tcrdbputkeepimpl(TCRDB *rdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
52
+ static bool tcrdbputcatimpl(TCRDB *rdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
53
+ static bool tcrdbputshlimpl(TCRDB *rdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz,
54
+ int width);
55
+ static bool tcrdbputnrimpl(TCRDB *rdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
56
+ static bool tcrdboutimpl(TCRDB *rdb, const void *kbuf, int ksiz);
57
+ static void *tcrdbgetimpl(TCRDB *rdb, const void *kbuf, int ksiz, int *sp);
58
+ static bool tcrdbmgetimpl(TCRDB *rdb, TCMAP *recs);
59
+ static int tcrdbvsizimpl(TCRDB *rdb, const void *kbuf, int ksiz);
60
+ static bool tcrdbiterinitimpl(TCRDB *rdb);
61
+ static void *tcrdbiternextimpl(TCRDB *rdb, int *sp);
62
+ static TCLIST *tcrdbfwmkeysimpl(TCRDB *rdb, const void *pbuf, int psiz, int max);
63
+ static int tcrdbaddintimpl(TCRDB *rdb, const void *kbuf, int ksiz, int num);
64
+ static double tcrdbadddoubleimpl(TCRDB *rdb, const void *kbuf, int ksiz, double num);
65
+ static void *tcrdbextimpl(TCRDB *rdb, const char *name, int opts,
66
+ const void *kbuf, int ksiz, const void *vbuf, int vsiz, int *sp);
67
+ static bool tcrdbsyncimpl(TCRDB *rdb);
68
+ static bool tcrdboptimizeimpl(TCRDB *rdb, const char *params);
69
+ static bool tcrdbvanishimpl(TCRDB *rdb);
70
+ static bool tcrdbcopyimpl(TCRDB *rdb, const char *path);
71
+ static bool tcrdbrestoreimpl(TCRDB *rdb, const char *path, uint64_t ts, int opts);
72
+ static bool tcrdbsetmstimpl(TCRDB *rdb, const char *host, int port, uint64_t ts, int opts);
73
+ const char *tcrdbexprimpl(TCRDB *rdb);
74
+ static uint64_t tcrdbrnumimpl(TCRDB *rdb);
75
+ static uint64_t tcrdbsizeimpl(TCRDB *rdb);
76
+ static char *tcrdbstatimpl(TCRDB *rdb);
77
+ static TCLIST *tcrdbmiscimpl(TCRDB *rdb, const char *name, int opts, const TCLIST *args);
78
+ static void tcrdbqrypopmeta(RDBQRY *qry, TCLIST *res);
79
+ static void *tcrdbparasearchworker(PARASEARCHARG *arg);
80
+ static long double tcrdbatof(const char *str);
81
+ static int rdbcmpsortrecstrasc(const RDBSORTREC *a, const RDBSORTREC *b);
82
+ static int rdbcmpsortrecstrdesc(const RDBSORTREC *a, const RDBSORTREC *b);
83
+ static int rdbcmpsortrecnumasc(const RDBSORTREC *a, const RDBSORTREC *b);
84
+ static int rdbcmpsortrecnumdesc(const RDBSORTREC *a, const RDBSORTREC *b);
85
+
86
+
87
+
88
+ /*************************************************************************************************
89
+ * API
90
+ *************************************************************************************************/
91
+
92
+
93
+ /* Get the message string corresponding to an error code. */
94
+ const char *tcrdberrmsg(int ecode){
95
+ switch(ecode){
96
+ case TTESUCCESS: return "success";
97
+ case TTEINVALID: return "invalid operation";
98
+ case TTENOHOST: return "host not found";
99
+ case TTEREFUSED: return "connection refused";
100
+ case TTESEND: return "send error";
101
+ case TTERECV: return "recv error";
102
+ case TTEKEEP: return "existing record";
103
+ case TTENOREC: return "no record found";
104
+ case TTEMISC: return "miscellaneous error";
105
+ }
106
+ return "unknown error";
107
+ }
108
+
109
+
110
+ /* Create a remote database object. */
111
+ TCRDB *tcrdbnew(void){
112
+ TCRDB *rdb = tcmalloc(sizeof(*rdb));
113
+ if(pthread_mutex_init(&rdb->mmtx, NULL) != 0) tcmyfatal("pthread_mutex_init failed");
114
+ if(pthread_key_create(&rdb->eckey, NULL) != 0) tcmyfatal("pthread_key_create failed");
115
+ rdb->host = NULL;
116
+ rdb->port = -1;
117
+ rdb->expr = NULL;
118
+ rdb->fd = -1;
119
+ rdb->sock = NULL;
120
+ rdb->timeout = UINT_MAX;
121
+ rdb->opts = 0;
122
+ tcrdbsetecode(rdb, TTESUCCESS);
123
+ return rdb;
124
+ }
125
+
126
+
127
+ /* Delete a remote database object. */
128
+ void tcrdbdel(TCRDB *rdb){
129
+ assert(rdb);
130
+ if(rdb->fd >= 0) tcrdbclose(rdb);
131
+ if(rdb->expr) tcfree(rdb->expr);
132
+ if(rdb->host) tcfree(rdb->host);
133
+ pthread_key_delete(rdb->eckey);
134
+ pthread_mutex_destroy(&rdb->mmtx);
135
+ tcfree(rdb);
136
+ }
137
+
138
+
139
+ /* Get the last happened error code of a remote database object. */
140
+ int tcrdbecode(TCRDB *rdb){
141
+ assert(rdb);
142
+ return (int)(intptr_t)pthread_getspecific(rdb->eckey);
143
+ }
144
+
145
+
146
+ /* Set the tuning parameters of a remote database object. */
147
+ bool tcrdbtune(TCRDB *rdb, double timeout, int opts){
148
+ assert(rdb);
149
+ if(!tcrdblockmethod(rdb)) return false;
150
+ bool rv;
151
+ pthread_cleanup_push((void (*)(void *))tcrdbunlockmethod, rdb);
152
+ rv = tcrdbtuneimpl(rdb, timeout, opts);
153
+ pthread_cleanup_pop(1);
154
+ return rv;
155
+ }
156
+
157
+
158
+ /* Open a remote database. */
159
+ bool tcrdbopen(TCRDB *rdb, const char *host, int port){
160
+ assert(rdb && host);
161
+ if(!tcrdblockmethod(rdb)) return false;
162
+ bool rv;
163
+ pthread_cleanup_push((void (*)(void *))tcrdbunlockmethod, rdb);
164
+ rv = tcrdbopenimpl(rdb, host, port);
165
+ pthread_cleanup_pop(1);
166
+ return rv;
167
+ }
168
+
169
+
170
+ /* Open a remote database with a simple server expression. */
171
+ bool tcrdbopen2(TCRDB *rdb, const char *expr){
172
+ assert(rdb && expr);
173
+ bool err = false;
174
+ int port;
175
+ char *host = ttbreakservexpr(expr, &port);
176
+ char *pv = strchr(expr, '#');
177
+ double tout = 0.0;
178
+ if(pv){
179
+ TCLIST *elems = tcstrsplit(pv + 1, "#");
180
+ int ln = tclistnum(elems);
181
+ for(int i = 0; i < ln; i++){
182
+ const char *elem = TCLISTVALPTR(elems, i);
183
+ pv = strchr(elem, '=');
184
+ if(!pv) continue;
185
+ *(pv++) = '\0';
186
+ if(!tcstricmp(elem, "host") || !tcstricmp(elem, "name")){
187
+ tcfree(host);
188
+ host = ttbreakservexpr(pv, NULL);
189
+ } else if(!tcstricmp(elem, "port")){
190
+ port = tcatoi(pv);
191
+ } else if(!tcstricmp(elem, "tout") || !tcstricmp(elem, "timeout")){
192
+ tout = tcatof(pv);
193
+ }
194
+ }
195
+ tclistdel(elems);
196
+ }
197
+ if(tout > 0) tcrdbtune(rdb, tout, RDBTRECON);
198
+ if(!tcrdbopen(rdb, host, port)) err = true;
199
+ tcfree(host);
200
+ return !err;
201
+ }
202
+
203
+
204
+ /* Close a remote database object. */
205
+ bool tcrdbclose(TCRDB *rdb){
206
+ assert(rdb);
207
+ if(!tcrdblockmethod(rdb)) return false;
208
+ bool rv;
209
+ pthread_cleanup_push((void (*)(void *))tcrdbunlockmethod, rdb);
210
+ rv = tcrdbcloseimpl(rdb);
211
+ pthread_cleanup_pop(1);
212
+ return rv;
213
+ }
214
+
215
+
216
+ /* Store a record into a remote database object. */
217
+ bool tcrdbput(TCRDB *rdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz){
218
+ assert(rdb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
219
+ if(!tcrdblockmethod(rdb)) return false;
220
+ bool rv;
221
+ pthread_cleanup_push((void (*)(void *))tcrdbunlockmethod, rdb);
222
+ rv = tcrdbputimpl(rdb, kbuf, ksiz, vbuf, vsiz);
223
+ pthread_cleanup_pop(1);
224
+ return rv;
225
+ }
226
+
227
+
228
+ /* Store a string record into a remote object. */
229
+ bool tcrdbput2(TCRDB *rdb, const char *kstr, const char *vstr){
230
+ assert(rdb && kstr && vstr);
231
+ return tcrdbput(rdb, kstr, strlen(kstr), vstr, strlen(vstr));
232
+ }
233
+
234
+
235
+ /* Store a new record into a remote database object. */
236
+ bool tcrdbputkeep(TCRDB *rdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz){
237
+ assert(rdb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
238
+ if(!tcrdblockmethod(rdb)) return false;
239
+ bool rv;
240
+ pthread_cleanup_push((void (*)(void *))tcrdbunlockmethod, rdb);
241
+ rv = tcrdbputkeepimpl(rdb, kbuf, ksiz, vbuf, vsiz);
242
+ pthread_cleanup_pop(1);
243
+ return rv;
244
+ }
245
+
246
+
247
+ /* Store a new string record into a remote database object. */
248
+ bool tcrdbputkeep2(TCRDB *rdb, const char *kstr, const char *vstr){
249
+ assert(rdb && kstr && vstr);
250
+ return tcrdbputkeep(rdb, kstr, strlen(kstr), vstr, strlen(vstr));
251
+ }
252
+
253
+
254
+ /* Concatenate a value at the end of the existing record in a remote database object. */
255
+ bool tcrdbputcat(TCRDB *rdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz){
256
+ assert(rdb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
257
+ if(!tcrdblockmethod(rdb)) return false;
258
+ bool rv;
259
+ pthread_cleanup_push((void (*)(void *))tcrdbunlockmethod, rdb);
260
+ rv = tcrdbputcatimpl(rdb, kbuf, ksiz, vbuf, vsiz);
261
+ pthread_cleanup_pop(1);
262
+ return rv;
263
+ }
264
+
265
+
266
+ /* Concatenate a string value at the end of the existing record in a remote database object. */
267
+ bool tcrdbputcat2(TCRDB *rdb, const char *kstr, const char *vstr){
268
+ assert(rdb && kstr && vstr);
269
+ return tcrdbputcat(rdb, kstr, strlen(kstr), vstr, strlen(vstr));
270
+ }
271
+
272
+
273
+ /* Concatenate a value at the end of the existing record and shift it to the left. */
274
+ bool tcrdbputshl(TCRDB *rdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz, int width){
275
+ assert(rdb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0 && width >= 0);
276
+ if(!tcrdblockmethod(rdb)) return false;
277
+ bool rv;
278
+ pthread_cleanup_push((void (*)(void *))tcrdbunlockmethod, rdb);
279
+ rv = tcrdbputshlimpl(rdb, kbuf, ksiz, vbuf, vsiz, width);
280
+ pthread_cleanup_pop(1);
281
+ return rv;
282
+ }
283
+
284
+
285
+ /* Concatenate a string value at the end of the existing record and shift it to the left. */
286
+ bool tcrdbputshl2(TCRDB *rdb, const char *kstr, const char *vstr, int width){
287
+ assert(rdb && kstr && vstr);
288
+ return tcrdbputshl(rdb, kstr, strlen(kstr), vstr, strlen(vstr), width);
289
+ }
290
+
291
+
292
+ /* Store a record into a remote database object without repsponse from the server. */
293
+ bool tcrdbputnr(TCRDB *rdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz){
294
+ assert(rdb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
295
+ if(!tcrdblockmethod(rdb)) return false;
296
+ bool rv;
297
+ pthread_cleanup_push((void (*)(void *))tcrdbunlockmethod, rdb);
298
+ rv = tcrdbputnrimpl(rdb, kbuf, ksiz, vbuf, vsiz);
299
+ pthread_cleanup_pop(1);
300
+ return rv;
301
+ }
302
+
303
+
304
+ /* Store a string record into a remote object without response from the server. */
305
+ bool tcrdbputnr2(TCRDB *rdb, const char *kstr, const char *vstr){
306
+ assert(rdb && kstr && vstr);
307
+ return tcrdbputnr(rdb, kstr, strlen(kstr), vstr, strlen(vstr));
308
+ }
309
+
310
+
311
+ /* Remove a record of a remote database object. */
312
+ bool tcrdbout(TCRDB *rdb, const void *kbuf, int ksiz){
313
+ assert(rdb && kbuf && ksiz >= 0);
314
+ if(!tcrdblockmethod(rdb)) return false;
315
+ bool rv;
316
+ pthread_cleanup_push((void (*)(void *))tcrdbunlockmethod, rdb);
317
+ rv = tcrdboutimpl(rdb, kbuf, ksiz);
318
+ pthread_cleanup_pop(1);
319
+ return rv;
320
+ }
321
+
322
+
323
+ /* Remove a string record of a remote database object. */
324
+ bool tcrdbout2(TCRDB *rdb, const char *kstr){
325
+ assert(rdb && kstr);
326
+ return tcrdbout(rdb, kstr, strlen(kstr));
327
+ }
328
+
329
+
330
+ /* Retrieve a record in a remote database object. */
331
+ void *tcrdbget(TCRDB *rdb, const void *kbuf, int ksiz, int *sp){
332
+ assert(rdb && kbuf && ksiz >= 0 && sp);
333
+ if(!tcrdblockmethod(rdb)) return NULL;
334
+ void *rv;
335
+ pthread_cleanup_push((void (*)(void *))tcrdbunlockmethod, rdb);
336
+ rv = tcrdbgetimpl(rdb, kbuf, ksiz, sp);
337
+ pthread_cleanup_pop(1);
338
+ return rv;
339
+ }
340
+
341
+
342
+ /* Retrieve a string record in a remote database object. */
343
+ char *tcrdbget2(TCRDB *rdb, const char *kstr){
344
+ assert(rdb && kstr);
345
+ int vsiz;
346
+ return tcrdbget(rdb, kstr, strlen(kstr), &vsiz);
347
+ }
348
+
349
+
350
+ /* Retrieve records in a remote database object. */
351
+ bool tcrdbget3(TCRDB *rdb, TCMAP *recs){
352
+ assert(rdb && recs);
353
+ if(!tcrdblockmethod(rdb)) return false;
354
+ bool rv;
355
+ pthread_cleanup_push((void (*)(void *))tcrdbunlockmethod, rdb);
356
+ rv = tcrdbmgetimpl(rdb, recs);
357
+ pthread_cleanup_pop(1);
358
+ return rv;
359
+ }
360
+
361
+
362
+ /* Get the size of the value of a record in a remote database object. */
363
+ int tcrdbvsiz(TCRDB *rdb, const void *kbuf, int ksiz){
364
+ assert(rdb && kbuf && ksiz >= 0);
365
+ if(!tcrdblockmethod(rdb)) return -1;
366
+ int rv;
367
+ pthread_cleanup_push((void (*)(void *))tcrdbunlockmethod, rdb);
368
+ rv = tcrdbvsizimpl(rdb, kbuf, ksiz);
369
+ pthread_cleanup_pop(1);
370
+ return rv;
371
+ }
372
+
373
+
374
+ /* Get the size of the value of a string record in a remote database object. */
375
+ int tcrdbvsiz2(TCRDB *rdb, const char *kstr){
376
+ assert(rdb && kstr);
377
+ return tcrdbvsiz(rdb, kstr, strlen(kstr));
378
+ }
379
+
380
+
381
+ /* Initialize the iterator of a remote database object. */
382
+ bool tcrdbiterinit(TCRDB *rdb){
383
+ assert(rdb);
384
+ if(!tcrdblockmethod(rdb)) return false;
385
+ bool rv;
386
+ pthread_cleanup_push((void (*)(void *))tcrdbunlockmethod, rdb);
387
+ rv = tcrdbiterinitimpl(rdb);
388
+ pthread_cleanup_pop(1);
389
+ return rv;
390
+ }
391
+
392
+
393
+ /* Get the next key of the iterator of a remote database object. */
394
+ void *tcrdbiternext(TCRDB *rdb, int *sp){
395
+ assert(rdb && sp);
396
+ if(!tcrdblockmethod(rdb)) return NULL;
397
+ void *rv;
398
+ pthread_cleanup_push((void (*)(void *))tcrdbunlockmethod, rdb);
399
+ rv = tcrdbiternextimpl(rdb, sp);
400
+ pthread_cleanup_pop(1);
401
+ return rv;
402
+ }
403
+
404
+
405
+ /* Get the next key string of the iterator of a remote database object. */
406
+ char *tcrdbiternext2(TCRDB *rdb){
407
+ assert(rdb);
408
+ int vsiz;
409
+ return tcrdbiternext(rdb, &vsiz);
410
+ }
411
+
412
+
413
+ /* Get forward matching keys in a remote database object. */
414
+ TCLIST *tcrdbfwmkeys(TCRDB *rdb, const void *pbuf, int psiz, int max){
415
+ assert(rdb && pbuf && psiz >= 0);
416
+ if(!tcrdblockmethod(rdb)) return tclistnew2(1);
417
+ TCLIST *rv;
418
+ pthread_cleanup_push((void (*)(void *))tcrdbunlockmethod, rdb);
419
+ rv = tcrdbfwmkeysimpl(rdb, pbuf, psiz, max);
420
+ pthread_cleanup_pop(1);
421
+ return rv;
422
+ }
423
+
424
+
425
+ /* Get forward matching string keys in a remote database object. */
426
+ TCLIST *tcrdbfwmkeys2(TCRDB *rdb, const char *pstr, int max){
427
+ assert(rdb && pstr);
428
+ return tcrdbfwmkeys(rdb, pstr, strlen(pstr), max);
429
+ }
430
+
431
+
432
+ /* Add an integer to a record in a remote database object. */
433
+ int tcrdbaddint(TCRDB *rdb, const void *kbuf, int ksiz, int num){
434
+ assert(rdb && kbuf && ksiz >= 0);
435
+ if(!tcrdblockmethod(rdb)) return INT_MIN;
436
+ int rv;
437
+ pthread_cleanup_push((void (*)(void *))tcrdbunlockmethod, rdb);
438
+ rv = tcrdbaddintimpl(rdb, kbuf, ksiz, num);
439
+ pthread_cleanup_pop(1);
440
+ return rv;
441
+ }
442
+
443
+
444
+ /* Add a real number to a record in a remote database object. */
445
+ double tcrdbadddouble(TCRDB *rdb, const void *kbuf, int ksiz, double num){
446
+ assert(rdb && kbuf && ksiz >= 0);
447
+ if(!tcrdblockmethod(rdb)) return nan("");
448
+ double rv;
449
+ pthread_cleanup_push((void (*)(void *))tcrdbunlockmethod, rdb);
450
+ rv = tcrdbadddoubleimpl(rdb, kbuf, ksiz, num);
451
+ pthread_cleanup_pop(1);
452
+ return rv;
453
+ }
454
+
455
+
456
+ /* Call a function of the scripting language extension. */
457
+ void *tcrdbext(TCRDB *rdb, const char *name, int opts,
458
+ const void *kbuf, int ksiz, const void *vbuf, int vsiz, int *sp){
459
+ assert(rdb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
460
+ if(!tcrdblockmethod(rdb)) return NULL;
461
+ void *rv;
462
+ pthread_cleanup_push((void (*)(void *))tcrdbunlockmethod, rdb);
463
+ rv = tcrdbextimpl(rdb, name, opts, kbuf, ksiz, vbuf, vsiz, sp);
464
+ pthread_cleanup_pop(1);
465
+ return rv;
466
+ }
467
+
468
+
469
+ /* Call a function of the scripting language extension with string parameters. */
470
+ char *tcrdbext2(TCRDB *rdb, const char *name, int opts, const char *kstr, const char *vstr){
471
+ assert(rdb && name && kstr && vstr);
472
+ int vsiz;
473
+ return tcrdbext(rdb, name, opts, kstr, strlen(kstr), vstr, strlen(vstr), &vsiz);
474
+ }
475
+
476
+
477
+ /* Synchronize updated contents of a remote database object with the file and the device. */
478
+ bool tcrdbsync(TCRDB *rdb){
479
+ assert(rdb);
480
+ if(!tcrdblockmethod(rdb)) return false;
481
+ bool rv;
482
+ pthread_cleanup_push((void (*)(void *))tcrdbunlockmethod, rdb);
483
+ rv = tcrdbsyncimpl(rdb);
484
+ pthread_cleanup_pop(1);
485
+ return rv;
486
+ }
487
+
488
+
489
+ /* Optimize the storage of a remove database object. */
490
+ bool tcrdboptimize(TCRDB *rdb, const char *params){
491
+ assert(rdb);
492
+ if(!tcrdblockmethod(rdb)) return false;
493
+ bool rv;
494
+ pthread_cleanup_push((void (*)(void *))tcrdbunlockmethod, rdb);
495
+ rv = tcrdboptimizeimpl(rdb, params);
496
+ pthread_cleanup_pop(1);
497
+ return rv;
498
+ }
499
+
500
+
501
+ /* Remove all records of a remote database object. */
502
+ bool tcrdbvanish(TCRDB *rdb){
503
+ assert(rdb);
504
+ if(!tcrdblockmethod(rdb)) return false;
505
+ bool rv;
506
+ pthread_cleanup_push((void (*)(void *))tcrdbunlockmethod, rdb);
507
+ rv = tcrdbvanishimpl(rdb);
508
+ pthread_cleanup_pop(1);
509
+ return rv;
510
+ }
511
+
512
+
513
+ /* Copy the database file of a remote database object. */
514
+ bool tcrdbcopy(TCRDB *rdb, const char *path){
515
+ assert(rdb && path);
516
+ if(!tcrdblockmethod(rdb)) return false;
517
+ bool rv;
518
+ pthread_cleanup_push((void (*)(void *))tcrdbunlockmethod, rdb);
519
+ rv = tcrdbcopyimpl(rdb, path);
520
+ pthread_cleanup_pop(1);
521
+ return rv;
522
+ }
523
+
524
+
525
+ /* Restore the database file of a remote database object from the update log. */
526
+ bool tcrdbrestore(TCRDB *rdb, const char *path, uint64_t ts, int opts){
527
+ assert(rdb && path);
528
+ if(!tcrdblockmethod(rdb)) return false;
529
+ bool rv;
530
+ pthread_cleanup_push((void (*)(void *))tcrdbunlockmethod, rdb);
531
+ rv = tcrdbrestoreimpl(rdb, path, ts, opts);
532
+ pthread_cleanup_pop(1);
533
+ return rv;
534
+ }
535
+
536
+
537
+ /* Set the replication master of a remote database object from the update log. */
538
+ bool tcrdbsetmst(TCRDB *rdb, const char *host, int port, uint64_t ts, int opts){
539
+ assert(rdb);
540
+ if(!tcrdblockmethod(rdb)) return false;
541
+ bool rv;
542
+ pthread_cleanup_push((void (*)(void *))tcrdbunlockmethod, rdb);
543
+ rv = tcrdbsetmstimpl(rdb, host, port, ts, opts);
544
+ pthread_cleanup_pop(1);
545
+ return rv;
546
+ }
547
+
548
+
549
+ /* Set the replication master of a remote database object with a simple server expression. */
550
+ bool tcrdbsetmst2(TCRDB *rdb, const char *expr, uint64_t ts, int opts){
551
+ assert(rdb && expr);
552
+ bool err = false;
553
+ int port;
554
+ char *host = ttbreakservexpr(expr, &port);
555
+ if(!tcrdbsetmst(rdb, host, port, ts, opts)) err = true;
556
+ tcfree(host);
557
+ return !err;
558
+ }
559
+
560
+
561
+ /* Get the simple server expression of an abstract database object. */
562
+ const char *tcrdbexpr(TCRDB *rdb){
563
+ assert(rdb);
564
+ if(!tcrdblockmethod(rdb)) return NULL;
565
+ const char *rv;
566
+ pthread_cleanup_push((void (*)(void *))tcrdbunlockmethod, rdb);
567
+ rv = tcrdbexprimpl(rdb);
568
+ pthread_cleanup_pop(1);
569
+ return rv;
570
+ }
571
+
572
+
573
+ /* Get the number of records of a remote database object. */
574
+ uint64_t tcrdbrnum(TCRDB *rdb){
575
+ assert(rdb);
576
+ if(!tcrdblockmethod(rdb)) return 0;
577
+ uint64_t rv;
578
+ pthread_cleanup_push((void (*)(void *))tcrdbunlockmethod, rdb);
579
+ rv = tcrdbrnumimpl(rdb);
580
+ pthread_cleanup_pop(1);
581
+ return rv;
582
+ }
583
+
584
+
585
+ /* Get the size of the database of a remote database object. */
586
+ uint64_t tcrdbsize(TCRDB *rdb){
587
+ assert(rdb);
588
+ if(!tcrdblockmethod(rdb)) return 0;
589
+ uint64_t rv;
590
+ pthread_cleanup_push((void (*)(void *))tcrdbunlockmethod, rdb);
591
+ rv = tcrdbsizeimpl(rdb);
592
+ pthread_cleanup_pop(1);
593
+ return rv;
594
+ }
595
+
596
+
597
+ /* Get the status string of the database of a remote database object. */
598
+ char *tcrdbstat(TCRDB *rdb){
599
+ assert(rdb);
600
+ if(!tcrdblockmethod(rdb)) return NULL;
601
+ char *rv;
602
+ pthread_cleanup_push((void (*)(void *))tcrdbunlockmethod, rdb);
603
+ rv = tcrdbstatimpl(rdb);
604
+ pthread_cleanup_pop(1);
605
+ return rv;
606
+ }
607
+
608
+
609
+ /* Call a versatile function for miscellaneous operations of a remote database object. */
610
+ TCLIST *tcrdbmisc(TCRDB *rdb, const char *name, int opts, const TCLIST *args){
611
+ assert(rdb && name && args);
612
+ if(!tcrdblockmethod(rdb)) return NULL;
613
+ TCLIST *rv;
614
+ pthread_cleanup_push((void (*)(void *))tcrdbunlockmethod, rdb);
615
+ rv = tcrdbmiscimpl(rdb, name, opts, args);
616
+ pthread_cleanup_pop(1);
617
+ return rv;
618
+ }
619
+
620
+
621
+
622
+ /*************************************************************************************************
623
+ * table extension
624
+ *************************************************************************************************/
625
+
626
+
627
+ /* Store a record into a remote database object. */
628
+ bool tcrdbtblput(TCRDB *rdb, const void *pkbuf, int pksiz, TCMAP *cols){
629
+ assert(rdb && pkbuf && pksiz >= 0 && cols);
630
+ TCLIST *args = tclistnew2(tcmaprnum(cols) * 2 + 1);
631
+ tclistpush(args, pkbuf, pksiz);
632
+ tcmapiterinit(cols);
633
+ const char *kbuf;
634
+ int ksiz;
635
+ while((kbuf = tcmapiternext(cols, &ksiz)) != NULL){
636
+ int vsiz;
637
+ const char *vbuf = tcmapiterval(kbuf, &vsiz);
638
+ tclistpush(args, kbuf, ksiz);
639
+ tclistpush(args, vbuf, vsiz);
640
+ }
641
+ TCLIST *rv = tcrdbmisc(rdb, "put", 0, args);
642
+ tclistdel(args);
643
+ if(!rv) return false;
644
+ tclistdel(rv);
645
+ return true;
646
+ }
647
+
648
+
649
+ /* Store a new record into a remote database object. */
650
+ bool tcrdbtblputkeep(TCRDB *rdb, const void *pkbuf, int pksiz, TCMAP *cols){
651
+ assert(rdb && pkbuf && pksiz >= 0 && cols);
652
+ TCLIST *args = tclistnew2(tcmaprnum(cols) * 2 + 1);
653
+ tclistpush(args, pkbuf, pksiz);
654
+ tcmapiterinit(cols);
655
+ const char *kbuf;
656
+ int ksiz;
657
+ while((kbuf = tcmapiternext(cols, &ksiz)) != NULL){
658
+ int vsiz;
659
+ const char *vbuf = tcmapiterval(kbuf, &vsiz);
660
+ tclistpush(args, kbuf, ksiz);
661
+ tclistpush(args, vbuf, vsiz);
662
+ }
663
+ TCLIST *rv = tcrdbmisc(rdb, "putkeep", 0, args);
664
+ tclistdel(args);
665
+ if(!rv){
666
+ if(tcrdbecode(rdb) == TTEMISC) tcrdbsetecode(rdb, TTEKEEP);
667
+ return false;
668
+ }
669
+ tclistdel(rv);
670
+ return true;
671
+ }
672
+
673
+
674
+ /* Concatenate columns of the existing record in a remote database object. */
675
+ bool tcrdbtblputcat(TCRDB *rdb, const void *pkbuf, int pksiz, TCMAP *cols){
676
+ assert(rdb && pkbuf && pksiz >= 0 && cols);
677
+ TCLIST *args = tclistnew2(tcmaprnum(cols) * 2 + 1);
678
+ tclistpush(args, pkbuf, pksiz);
679
+ tcmapiterinit(cols);
680
+ const char *kbuf;
681
+ int ksiz;
682
+ while((kbuf = tcmapiternext(cols, &ksiz)) != NULL){
683
+ int vsiz;
684
+ const char *vbuf = tcmapiterval(kbuf, &vsiz);
685
+ tclistpush(args, kbuf, ksiz);
686
+ tclistpush(args, vbuf, vsiz);
687
+ }
688
+ TCLIST *rv = tcrdbmisc(rdb, "putcat", 0, args);
689
+ tclistdel(args);
690
+ if(!rv) return false;
691
+ tclistdel(rv);
692
+ return true;
693
+ }
694
+
695
+
696
+ /* Remove a record of a remote database object. */
697
+ bool tcrdbtblout(TCRDB *rdb, const void *pkbuf, int pksiz){
698
+ assert(rdb && pkbuf && pksiz >= 0);
699
+ TCLIST *args = tclistnew2(1);
700
+ tclistpush(args, pkbuf, pksiz);
701
+ TCLIST *rv = tcrdbmisc(rdb, "out", 0, args);
702
+ tclistdel(args);
703
+ if(!rv){
704
+ if(tcrdbecode(rdb) == TTEMISC) tcrdbsetecode(rdb, TTENOREC);
705
+ return false;
706
+ }
707
+ tclistdel(rv);
708
+ return true;
709
+ }
710
+
711
+
712
+ /* Retrieve a record in a remote database object. */
713
+ TCMAP *tcrdbtblget(TCRDB *rdb, const void *pkbuf, int pksiz){
714
+ assert(rdb && pkbuf && pksiz >= 0);
715
+ TCLIST *args = tclistnew2(1);
716
+ tclistpush(args, pkbuf, pksiz);
717
+ TCLIST *rv = tcrdbmisc(rdb, "get", RDBMONOULOG, args);
718
+ tclistdel(args);
719
+ if(!rv){
720
+ if(tcrdbecode(rdb) == TTEMISC) tcrdbsetecode(rdb, TTENOREC);
721
+ return NULL;
722
+ }
723
+ int num = tclistnum(rv);
724
+ TCMAP *cols = tcmapnew2(num / 2 + 1);
725
+ num--;
726
+ for(int i = 0; i < num; i += 2){
727
+ int ksiz;
728
+ const char *kbuf = tclistval(rv, i, &ksiz);
729
+ int vsiz;
730
+ const char *vbuf = tclistval(rv, i + 1, &vsiz);
731
+ tcmapput(cols, kbuf, ksiz, vbuf, vsiz);
732
+ }
733
+ tclistdel(rv);
734
+ return cols;
735
+ }
736
+
737
+
738
+ /* Set a column index to a remote database object. */
739
+ bool tcrdbtblsetindex(TCRDB *rdb, const char *name, int type){
740
+ assert(rdb && name);
741
+ TCLIST *args = tclistnew2(2);
742
+ tclistpush2(args, name);
743
+ char typestr[TTNUMBUFSIZ];
744
+ sprintf(typestr, "%d", type);
745
+ tclistpush2(args, typestr);
746
+ TCLIST *rv = tcrdbmisc(rdb, "setindex", 0, args);
747
+ tclistdel(args);
748
+ if(!rv) return false;
749
+ tclistdel(rv);
750
+ return true;
751
+ }
752
+
753
+
754
+ /* Generate a unique ID number of a remote database object. */
755
+ int64_t tcrdbtblgenuid(TCRDB *rdb){
756
+ assert(rdb);
757
+ TCLIST *args = tclistnew2(1);
758
+ TCLIST *rv = tcrdbmisc(rdb, "genuid", 0, args);
759
+ tclistdel(args);
760
+ if(!rv) return -1;
761
+ int64_t uid = -1;
762
+ if(tclistnum(rv) > 0) uid = tcatoi(tclistval2(rv, 0));
763
+ tclistdel(rv);
764
+ return uid;
765
+ }
766
+
767
+
768
+ /* Create a query object. */
769
+ RDBQRY *tcrdbqrynew(TCRDB *rdb){
770
+ assert(rdb);
771
+ RDBQRY *qry = tcmalloc(sizeof(*qry));
772
+ qry->rdb = rdb;
773
+ qry->args = tclistnew();
774
+ qry->hint = tcxstrnew();
775
+ tclistpush(qry->args, "hint", 4);
776
+ return qry;
777
+ }
778
+
779
+
780
+ /* Delete a query object. */
781
+ void tcrdbqrydel(RDBQRY *qry){
782
+ assert(qry);
783
+ tcxstrdel(qry->hint);
784
+ tclistdel(qry->args);
785
+ tcfree(qry);
786
+ }
787
+
788
+
789
+ /* Add a narrowing condition to a query object. */
790
+ void tcrdbqryaddcond(RDBQRY *qry, const char *name, int op, const char *expr){
791
+ assert(qry && name && expr);
792
+ TCXSTR *xstr = tcxstrnew();
793
+ tcxstrcat2(xstr, "addcond");
794
+ tcxstrcat(xstr, "\0", 1);
795
+ tcxstrcat2(xstr, name);
796
+ tcxstrcat(xstr, "\0", 1);
797
+ tcxstrprintf(xstr, "%d", op);
798
+ tcxstrcat(xstr, "\0", 1);
799
+ tcxstrcat2(xstr, expr);
800
+ tclistpush(qry->args, tcxstrptr(xstr), tcxstrsize(xstr));
801
+ tcxstrdel(xstr);
802
+ }
803
+
804
+
805
+ /* Set the order of a query object. */
806
+ void tcrdbqrysetorder(RDBQRY *qry, const char *name, int type){
807
+ assert(qry && name);
808
+ TCXSTR *xstr = tcxstrnew();
809
+ tcxstrcat2(xstr, "setorder");
810
+ tcxstrcat(xstr, "\0", 1);
811
+ tcxstrcat2(xstr, name);
812
+ tcxstrcat(xstr, "\0", 1);
813
+ tcxstrprintf(xstr, "%d", type);
814
+ tclistpush(qry->args, tcxstrptr(xstr), tcxstrsize(xstr));
815
+ tcxstrdel(xstr);
816
+ }
817
+
818
+
819
+ /* Set the limit number of records of the result of a query object. */
820
+ void tcrdbqrysetlimit(RDBQRY *qry, int max, int skip){
821
+ TCXSTR *xstr = tcxstrnew();
822
+ tcxstrcat2(xstr, "setlimit");
823
+ tcxstrcat(xstr, "\0", 1);
824
+ tcxstrprintf(xstr, "%d", max);
825
+ tcxstrcat(xstr, "\0", 1);
826
+ tcxstrprintf(xstr, "%d", skip);
827
+ tclistpush(qry->args, tcxstrptr(xstr), tcxstrsize(xstr));
828
+ tcxstrdel(xstr);
829
+ }
830
+
831
+
832
+ /* Execute the search of a query object. */
833
+ TCLIST *tcrdbqrysearch(RDBQRY *qry){
834
+ assert(qry);
835
+ tcxstrclear(qry->hint);
836
+ TCLIST *rv = tcrdbmisc(qry->rdb, "search", RDBMONOULOG, qry->args);
837
+ if(!rv) return tclistnew2(1);
838
+ tcrdbqrypopmeta(qry, rv);
839
+ return rv;
840
+ }
841
+
842
+
843
+ /* Remove each record corresponding to a query object. */
844
+ bool tcrdbqrysearchout(RDBQRY *qry){
845
+ assert(qry);
846
+ TCLIST *args = tclistdup(qry->args);
847
+ tclistpush2(args, "out");
848
+ tcxstrclear(qry->hint);
849
+ TCLIST *rv = tcrdbmisc(qry->rdb, "search", 0, args);
850
+ tclistdel(args);
851
+ if(!rv) return false;
852
+ tcrdbqrypopmeta(qry, rv);
853
+ tclistdel(rv);
854
+ return true;
855
+ }
856
+
857
+
858
+ /* Get records corresponding to the search of a query object. */
859
+ TCLIST *tcrdbqrysearchget(RDBQRY *qry){
860
+ assert(qry);
861
+ TCLIST *args = tclistdup(qry->args);
862
+ tclistpush2(args, "get");
863
+ tcxstrclear(qry->hint);
864
+ TCLIST *rv = tcrdbmisc(qry->rdb, "search", RDBMONOULOG, args);
865
+ tclistdel(args);
866
+ if(!rv) return tclistnew2(1);
867
+ tcrdbqrypopmeta(qry, rv);
868
+ return rv;
869
+ }
870
+
871
+
872
+ /* Get columns of a record in a search result. */
873
+ TCMAP *tcrdbqryrescols(TCLIST *res, int index){
874
+ assert(res && index >= 0);
875
+ if(index >= tclistnum(res)) return NULL;
876
+ int csiz;
877
+ const char *cbuf = tclistval(res, index, &csiz);
878
+ return tcstrsplit4(cbuf, csiz);
879
+ }
880
+
881
+
882
+ /* Get the count of corresponding records of a query object. */
883
+ int tcrdbqrysearchcount(RDBQRY *qry){
884
+ assert(qry);
885
+ TCLIST *args = tclistdup(qry->args);
886
+ tclistpush2(args, "count");
887
+ tcxstrclear(qry->hint);
888
+ TCLIST *rv = tcrdbmisc(qry->rdb, "search", RDBMONOULOG, args);
889
+ tclistdel(args);
890
+ if(!rv) return 0;
891
+ tcrdbqrypopmeta(qry, rv);
892
+ int count = tclistnum(rv) > 0 ? tcatoi(tclistval2(rv, 0)) : 0;
893
+ tclistdel(rv);
894
+ return count;
895
+ }
896
+
897
+
898
+ /* Get the hint string of a query object. */
899
+ const char *tcrdbqryhint(RDBQRY *qry){
900
+ assert(qry);
901
+ return tcxstrptr(qry->hint);
902
+ }
903
+
904
+
905
+ /* Retrieve records with multiple query objects and get the set of the result. */
906
+ TCLIST *tcrdbmetasearch(RDBQRY **qrys, int num, int type){
907
+ assert(qrys && num >= 0);
908
+ if(num < 1) return tclistnew2(1);
909
+ if(num < 2) return tcrdbqrysearch(qrys[0]);
910
+ RDBQRY *qry = qrys[0];
911
+ TCLIST *args = tclistdup(qry->args);
912
+ for(int i = 1; i < num; i++){
913
+ tclistpush(args, "next", 4);
914
+ const TCLIST *targs = qrys[i]->args;
915
+ int tanum = tclistnum(targs);
916
+ for(int j = 0; j < tanum; j++){
917
+ int vsiz;
918
+ const char *vbuf = tclistval(targs, j, &vsiz);
919
+ tclistpush(args, vbuf, vsiz);
920
+ }
921
+ }
922
+ char buf[TTNUMBUFSIZ];
923
+ int len = sprintf(buf, "mstype");
924
+ len += 1 + sprintf(buf + len + 1, "%d", type);
925
+ tclistpush(args, buf, len);
926
+ tcxstrclear(qry->hint);
927
+ TCLIST *rv = tcrdbmisc(qry->rdb, "metasearch", RDBMONOULOG, args);
928
+ tclistdel(args);
929
+ if(!rv) rv = tclistnew2(1);
930
+ tcrdbqrypopmeta(qrys[0], rv);
931
+ return rv;
932
+ }
933
+
934
+
935
+ /* Search for multiple servers in parallel. */
936
+ TCLIST *tcrdbparasearch(RDBQRY **qrys, int num){
937
+ assert(qrys && num >= 0);
938
+ if(num < 1) return tclistnew2(1);
939
+ if(num < 2) return tcrdbqrysearchget(qrys[0]);
940
+ int ocs = PTHREAD_CANCEL_DISABLE;
941
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &ocs);
942
+ TCLIST *oargs = qrys[0]->args;
943
+ char *oname = NULL;
944
+ int otype = 0;
945
+ int max = INT_MAX / 2;
946
+ int skip = 0;
947
+ for(int i = 0; i < tclistnum(oargs); i++){
948
+ int osiz;
949
+ const char *obuf = tclistval(oargs, i, &osiz);
950
+ if(!strcmp(obuf, "setlimit")){
951
+ TCLIST *elems = tcstrsplit2(obuf, osiz);
952
+ if(tclistnum(elems) > 1) max = tcatoi(tclistval2(elems, 1));
953
+ if(tclistnum(elems) > 2) skip = tcatoi(tclistval2(elems, 2));
954
+ tclistdel(elems);
955
+ } else if(!strcmp(obuf, "setorder")){
956
+ TCLIST *elems = tcstrsplit2(obuf, osiz);
957
+ if(tclistnum(elems) > 2){
958
+ oname = tcstrdup(tclistval2(elems, 1));
959
+ otype = tcatoi(tclistval2(elems, 2));
960
+ }
961
+ tclistdel(elems);
962
+ }
963
+ }
964
+ int onsiz = oname ? strlen(oname) : 0;
965
+ if(max < 1 || max > INT_MAX / 2) max = INT_MAX / 2;
966
+ if(skip < 0) skip = 0;
967
+ PARASEARCHARG args[num];
968
+ for(int i = 0; i < num; i++){
969
+ PARASEARCHARG *arg = args + i;
970
+ arg->qry = qrys[i];
971
+ arg->res = NULL;
972
+ arg->max = max;
973
+ arg->skip = skip;
974
+ if(pthread_create(&arg->tid, NULL, (void *(*)(void *))tcrdbparasearchworker, arg) != 0)
975
+ arg->qry = NULL;
976
+ }
977
+ int all = 0;
978
+ for(int i = 0; i < num; i++){
979
+ PARASEARCHARG *arg = args + i;
980
+ if(arg->qry) pthread_join(arg->tid, NULL);
981
+ if(arg->res){
982
+ tcrdbqrypopmeta(arg->qry, arg->res);
983
+ all += tclistnum(arg->res);
984
+ }
985
+ }
986
+ RDBSORTREC *recs = tcmalloc(sizeof(*recs) * all + 1);
987
+ int rnum = 0;
988
+ for(int i = 0; i < num; i++){
989
+ PARASEARCHARG *arg = args + i;
990
+ if(arg->res){
991
+ int tnum = tclistnum(arg->res);
992
+ for(int j = 0; j < tnum; j++){
993
+ int csiz;
994
+ const char *cbuf = tclistval(arg->res, j, &csiz);
995
+ recs[rnum].cbuf = cbuf;
996
+ recs[rnum].csiz = csiz;
997
+ recs[rnum].obuf = NULL;
998
+ recs[rnum].osiz = 0;
999
+ if(oname){
1000
+ TCMAP *cols = tcstrsplit4(cbuf, csiz);
1001
+ int osiz;
1002
+ const char *obuf = tcmapget(cols, oname, onsiz, &osiz);
1003
+ if(obuf){
1004
+ recs[rnum].obuf = tcmemdup(obuf, osiz);
1005
+ recs[rnum].osiz = osiz;
1006
+ }
1007
+ tcmapdel(cols);
1008
+ }
1009
+ rnum++;
1010
+ }
1011
+ }
1012
+ }
1013
+ if(oname){
1014
+ int (*compar)(const RDBSORTREC *a, const RDBSORTREC *b) = NULL;
1015
+ switch(otype){
1016
+ case RDBQOSTRASC:
1017
+ compar = rdbcmpsortrecstrasc;
1018
+ break;
1019
+ case RDBQOSTRDESC:
1020
+ compar = rdbcmpsortrecstrdesc;
1021
+ break;
1022
+ case RDBQONUMASC:
1023
+ compar = rdbcmpsortrecnumasc;
1024
+ break;
1025
+ case RDBQONUMDESC:
1026
+ compar = rdbcmpsortrecnumdesc;
1027
+ break;
1028
+ }
1029
+ if(compar) qsort(recs, rnum, sizeof(*recs), (int (*)(const void *, const void *))compar);
1030
+ for(int i = 0; i < rnum; i++){
1031
+ tcfree(recs[i].obuf);
1032
+ }
1033
+ }
1034
+ TCLIST *res = tclistnew2(tclmin(rnum, max));
1035
+ TCMAP *uset = tcmapnew2(rnum + 1);
1036
+ for(int i = 0; max > 0 && i < rnum; i++){
1037
+ RDBSORTREC *rec = recs + i;
1038
+ if(tcmapputkeep(uset, rec->cbuf, rec->csiz, "", 0)){
1039
+ if(skip > 0){
1040
+ skip--;
1041
+ } else {
1042
+ tclistpush(res, rec->cbuf, rec->csiz);
1043
+ max--;
1044
+ }
1045
+ }
1046
+ }
1047
+ tcmapdel(uset);
1048
+ for(int i = 0; i < num; i++){
1049
+ PARASEARCHARG *arg = args + i;
1050
+ if(arg->res) tclistdel(arg->res);
1051
+ }
1052
+ tcfree(recs);
1053
+ tcfree(oname);
1054
+ pthread_setcancelstate(ocs, NULL);
1055
+ return res;
1056
+ }
1057
+
1058
+
1059
+
1060
+ /*************************************************************************************************
1061
+ * features for experts
1062
+ *************************************************************************************************/
1063
+
1064
+
1065
+ /* Set the error code of a remote database object. */
1066
+ void tcrdbsetecode(TCRDB *rdb, int ecode){
1067
+ assert(rdb);
1068
+ pthread_setspecific(rdb->eckey, (void *)(intptr_t)ecode);
1069
+ }
1070
+
1071
+
1072
+
1073
+ /*************************************************************************************************
1074
+ * private features
1075
+ *************************************************************************************************/
1076
+
1077
+
1078
+ /* Lock a method of the remote database object.
1079
+ `rdb' specifies the remote database object.
1080
+ If successful, the return value is true, else, it is false. */
1081
+ static bool tcrdblockmethod(TCRDB *rdb){
1082
+ assert(rdb);
1083
+ if(pthread_mutex_lock(&rdb->mmtx) != 0){
1084
+ tcrdbsetecode(rdb, TCEMISC);
1085
+ return false;
1086
+ }
1087
+ return true;
1088
+ }
1089
+
1090
+
1091
+ /* Unlock a method of the remote database object.
1092
+ `rdb' specifies the remote database object. */
1093
+ static void tcrdbunlockmethod(TCRDB *rdb){
1094
+ assert(rdb);
1095
+ if(pthread_mutex_unlock(&rdb->mmtx) != 0) tcrdbsetecode(rdb, TCEMISC);
1096
+ }
1097
+
1098
+
1099
+ /* Reconnect a remote database.
1100
+ `rdb' specifies the remote database object.
1101
+ If successful, the return value is true, else, it is false. */
1102
+ static bool tcrdbreconnect(TCRDB *rdb){
1103
+ assert(rdb);
1104
+ if(rdb->sock){
1105
+ ttsockdel(rdb->sock);
1106
+ ttclosesock(rdb->fd);
1107
+ rdb->fd = -1;
1108
+ rdb->sock = NULL;
1109
+ }
1110
+ int fd;
1111
+ if(rdb->port < 1){
1112
+ fd = ttopensockunix(rdb->host);
1113
+ } else {
1114
+ char addr[TTADDRBUFSIZ];
1115
+ if(!ttgethostaddr(rdb->host, addr)){
1116
+ tcrdbsetecode(rdb, TTENOHOST);
1117
+ return false;
1118
+ }
1119
+ fd = ttopensock(addr, rdb->port);
1120
+ }
1121
+ if(fd == -1){
1122
+ tcrdbsetecode(rdb, TTEREFUSED);
1123
+ return false;
1124
+ }
1125
+ rdb->fd = fd;
1126
+ rdb->sock = ttsocknew(fd);
1127
+ return true;
1128
+ }
1129
+
1130
+
1131
+ /* Send data of a remote database object.
1132
+ `rdb' specifies the remote database object.
1133
+ `buf' specifies the pointer to the region of the data to send.
1134
+ `size' specifies the size of the buffer.
1135
+ If successful, the return value is true, else, it is false. */
1136
+ static bool tcrdbsend(TCRDB *rdb, const void *buf, int size){
1137
+ assert(rdb && buf && size >= 0);
1138
+ if(ttsockcheckend(rdb->sock)){
1139
+ if(!(rdb->opts & RDBTRECON)) return false;
1140
+ tcsleep(RDBRECONWAIT);
1141
+ if(!tcrdbreconnect(rdb)) return false;
1142
+ if(ttsocksend(rdb->sock, buf, size)) return true;
1143
+ tcrdbsetecode(rdb, TTESEND);
1144
+ return false;
1145
+ }
1146
+ ttsocksetlife(rdb->sock, rdb->timeout);
1147
+ if(ttsocksend(rdb->sock, buf, size)) return true;
1148
+ tcrdbsetecode(rdb, TTESEND);
1149
+ if(!(rdb->opts & RDBTRECON)) return false;
1150
+ tcsleep(RDBRECONWAIT);
1151
+ if(!tcrdbreconnect(rdb)) return false;
1152
+ ttsocksetlife(rdb->sock, rdb->timeout);
1153
+ if(ttsocksend(rdb->sock, buf, size)) return true;
1154
+ tcrdbsetecode(rdb, TTESEND);
1155
+ return false;
1156
+ }
1157
+
1158
+
1159
+ /* Set the tuning parameters of a remote database object.
1160
+ `rdb' specifies the remote database object.
1161
+ `timeout' specifies the timeout of each query in seconds.
1162
+ `opts' specifies options by bitwise-or.
1163
+ If successful, the return value is true, else, it is false. */
1164
+ static bool tcrdbtuneimpl(TCRDB *rdb, double timeout, int opts){
1165
+ assert(rdb);
1166
+ if(rdb->fd >= 0){
1167
+ tcrdbsetecode(rdb, TTEINVALID);
1168
+ return false;
1169
+ }
1170
+ rdb->timeout = (timeout > 0.0) ? timeout : UINT_MAX;
1171
+ rdb->opts = opts;
1172
+ return true;
1173
+ }
1174
+
1175
+
1176
+ /* Open a remote database.
1177
+ `rdb' specifies the remote database object.
1178
+ `host' specifies the name or the address of the server.
1179
+ `port' specifies the port number.
1180
+ If successful, the return value is true, else, it is false. */
1181
+ static bool tcrdbopenimpl(TCRDB *rdb, const char *host, int port){
1182
+ assert(rdb && host);
1183
+ if(rdb->fd >= 0){
1184
+ tcrdbsetecode(rdb, TTEINVALID);
1185
+ return false;
1186
+ }
1187
+ int fd;
1188
+ if(port < 1){
1189
+ fd = ttopensockunix(host);
1190
+ } else {
1191
+ char addr[TTADDRBUFSIZ];
1192
+ if(!ttgethostaddr(host, addr)){
1193
+ tcrdbsetecode(rdb, TTENOHOST);
1194
+ return false;
1195
+ }
1196
+ fd = ttopensock(addr, port);
1197
+ }
1198
+ if(fd == -1){
1199
+ tcrdbsetecode(rdb, TTEREFUSED);
1200
+ return false;
1201
+ }
1202
+ if(rdb->host) tcfree(rdb->host);
1203
+ rdb->host = tcstrdup(host);
1204
+ rdb->port = port;
1205
+ rdb->expr = tcsprintf("%s:%d", host, port);
1206
+ rdb->fd = fd;
1207
+ rdb->sock = ttsocknew(fd);
1208
+ return true;
1209
+ }
1210
+
1211
+
1212
+ /* Close a remote database object.
1213
+ `rdb' specifies the remote database object.
1214
+ If successful, the return value is true, else, it is false. */
1215
+ static bool tcrdbcloseimpl(TCRDB *rdb){
1216
+ assert(rdb);
1217
+ if(rdb->fd < 0){
1218
+ tcrdbsetecode(rdb, TTEINVALID);
1219
+ return false;
1220
+ }
1221
+ bool err = false;
1222
+ ttsockdel(rdb->sock);
1223
+ if(!ttclosesock(rdb->fd)){
1224
+ tcrdbsetecode(rdb, TTEMISC);
1225
+ err = true;
1226
+ }
1227
+ tcfree(rdb->expr);
1228
+ tcfree(rdb->host);
1229
+ rdb->expr = NULL;
1230
+ rdb->host = NULL;
1231
+ rdb->port = -1;
1232
+ rdb->fd = -1;
1233
+ rdb->sock = NULL;
1234
+ return !err;
1235
+ }
1236
+
1237
+
1238
+ /* Store a record into a remote database object.
1239
+ `rdb' specifies the remote database object.
1240
+ `kbuf' specifies the pointer to the region of the key.
1241
+ `ksiz' specifies the size of the region of the key.
1242
+ `vbuf' specifies the pointer to the region of the value.
1243
+ `vsiz' specifies the size of the region of the value.
1244
+ If successful, the return value is true, else, it is false. */
1245
+ static bool tcrdbputimpl(TCRDB *rdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz){
1246
+ assert(rdb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
1247
+ if(rdb->fd < 0){
1248
+ if(!rdb->host || !(rdb->opts & RDBTRECON)){
1249
+ tcrdbsetecode(rdb, TTEINVALID);
1250
+ return false;
1251
+ }
1252
+ if(!tcrdbreconnect(rdb)) return false;
1253
+ }
1254
+ bool err = false;
1255
+ int rsiz = 2 + sizeof(uint32_t) * 2 + ksiz + vsiz;
1256
+ unsigned char stack[TTIOBUFSIZ];
1257
+ unsigned char *buf = (rsiz < TTIOBUFSIZ) ? stack : tcmalloc(rsiz);
1258
+ pthread_cleanup_push(free, (buf == stack) ? NULL : buf);
1259
+ unsigned char *wp = buf;
1260
+ *(wp++) = TTMAGICNUM;
1261
+ *(wp++) = TTCMDPUT;
1262
+ uint32_t num;
1263
+ num = TTHTONL((uint32_t)ksiz);
1264
+ memcpy(wp, &num, sizeof(uint32_t));
1265
+ wp += sizeof(uint32_t);
1266
+ num = TTHTONL((uint32_t)vsiz);
1267
+ memcpy(wp, &num, sizeof(uint32_t));
1268
+ wp += sizeof(uint32_t);
1269
+ memcpy(wp, kbuf, ksiz);
1270
+ wp += ksiz;
1271
+ memcpy(wp, vbuf, vsiz);
1272
+ wp += vsiz;
1273
+ if(tcrdbsend(rdb, buf, wp - buf)){
1274
+ int code = ttsockgetc(rdb->sock);
1275
+ if(code != 0){
1276
+ tcrdbsetecode(rdb, code == -1 ? TTERECV : TTEMISC);
1277
+ err = true;
1278
+ }
1279
+ } else {
1280
+ err = true;
1281
+ }
1282
+ pthread_cleanup_pop(1);
1283
+ return !err;
1284
+ }
1285
+
1286
+
1287
+ /* Store a new record into a remote database object.
1288
+ `rdb' specifies the remote database object.
1289
+ `kbuf' specifies the pointer to the region of the key.
1290
+ `ksiz' specifies the size of the region of the key.
1291
+ `vbuf' specifies the pointer to the region of the value.
1292
+ `vsiz' specifies the size of the region of the value.
1293
+ If successful, the return value is true, else, it is false. */
1294
+ static bool tcrdbputkeepimpl(TCRDB *rdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz){
1295
+ assert(rdb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
1296
+ if(rdb->fd < 0){
1297
+ if(!rdb->host || !(rdb->opts & RDBTRECON)){
1298
+ tcrdbsetecode(rdb, TTEINVALID);
1299
+ return false;
1300
+ }
1301
+ if(!tcrdbreconnect(rdb)) return false;
1302
+ }
1303
+ bool err = false;
1304
+ int rsiz = 2 + sizeof(uint32_t) * 2 + ksiz + vsiz;
1305
+ unsigned char stack[TTIOBUFSIZ];
1306
+ unsigned char *buf = (rsiz < TTIOBUFSIZ) ? stack : tcmalloc(rsiz);
1307
+ pthread_cleanup_push(free, (buf == stack) ? NULL : buf);
1308
+ unsigned char *wp = buf;
1309
+ *(wp++) = TTMAGICNUM;
1310
+ *(wp++) = TTCMDPUTKEEP;
1311
+ uint32_t num;
1312
+ num = TTHTONL((uint32_t)ksiz);
1313
+ memcpy(wp, &num, sizeof(uint32_t));
1314
+ wp += sizeof(uint32_t);
1315
+ num = TTHTONL((uint32_t)vsiz);
1316
+ memcpy(wp, &num, sizeof(uint32_t));
1317
+ wp += sizeof(uint32_t);
1318
+ memcpy(wp, kbuf, ksiz);
1319
+ wp += ksiz;
1320
+ memcpy(wp, vbuf, vsiz);
1321
+ wp += vsiz;
1322
+ if(tcrdbsend(rdb, buf, wp - buf)){
1323
+ int code = ttsockgetc(rdb->sock);
1324
+ if(code != 0){
1325
+ tcrdbsetecode(rdb, code == -1 ? TTERECV : TTEKEEP);
1326
+ err = true;
1327
+ }
1328
+ } else {
1329
+ err = true;
1330
+ }
1331
+ pthread_cleanup_pop(1);
1332
+ return !err;
1333
+ }
1334
+
1335
+
1336
+ /* Concatenate a value at the end of the existing record in a remote database object.
1337
+ `rdb' specifies the remote database object.
1338
+ `kbuf' specifies the pointer to the region of the key.
1339
+ `ksiz' specifies the size of the region of the key.
1340
+ `vbuf' specifies the pointer to the region of the value.
1341
+ `vsiz' specifies the size of the region of the value.
1342
+ If successful, the return value is true, else, it is false. */
1343
+ static bool tcrdbputcatimpl(TCRDB *rdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz){
1344
+ assert(rdb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
1345
+ if(rdb->fd < 0){
1346
+ if(!rdb->host || !(rdb->opts & RDBTRECON)){
1347
+ tcrdbsetecode(rdb, TTEINVALID);
1348
+ return false;
1349
+ }
1350
+ if(!tcrdbreconnect(rdb)) return false;
1351
+ }
1352
+ bool err = false;
1353
+ int rsiz = 2 + sizeof(uint32_t) * 2 + ksiz + vsiz;
1354
+ unsigned char stack[TTIOBUFSIZ];
1355
+ unsigned char *buf = (rsiz < TTIOBUFSIZ) ? stack : tcmalloc(rsiz);
1356
+ pthread_cleanup_push(free, (buf == stack) ? NULL : buf);
1357
+ unsigned char *wp = buf;
1358
+ *(wp++) = TTMAGICNUM;
1359
+ *(wp++) = TTCMDPUTCAT;
1360
+ uint32_t num;
1361
+ num = TTHTONL((uint32_t)ksiz);
1362
+ memcpy(wp, &num, sizeof(uint32_t));
1363
+ wp += sizeof(uint32_t);
1364
+ num = TTHTONL((uint32_t)vsiz);
1365
+ memcpy(wp, &num, sizeof(uint32_t));
1366
+ wp += sizeof(uint32_t);
1367
+ memcpy(wp, kbuf, ksiz);
1368
+ wp += ksiz;
1369
+ memcpy(wp, vbuf, vsiz);
1370
+ wp += vsiz;
1371
+ if(tcrdbsend(rdb, buf, wp - buf)){
1372
+ int code = ttsockgetc(rdb->sock);
1373
+ if(code != 0){
1374
+ tcrdbsetecode(rdb, code == -1 ? TTERECV : TTEMISC);
1375
+ err = true;
1376
+ }
1377
+ } else {
1378
+ err = true;
1379
+ }
1380
+ pthread_cleanup_pop(1);
1381
+ return !err;
1382
+ }
1383
+
1384
+
1385
+ /* Concatenate a value at the end of the existing record and shift it to the left.
1386
+ `rdb' specifies the remote database object.
1387
+ `kbuf' specifies the pointer to the region of the key.
1388
+ `ksiz' specifies the size of the region of the key.
1389
+ `vbuf' specifies the pointer to the region of the value.
1390
+ `vsiz' specifies the size of the region of the value.
1391
+ `width' specifies the width of the record.
1392
+ If successful, the return value is true, else, it is false. */
1393
+ static bool tcrdbputshlimpl(TCRDB *rdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz,
1394
+ int width){
1395
+ assert(rdb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0 && width >= 0);
1396
+ if(rdb->fd < 0){
1397
+ if(!rdb->host || !(rdb->opts & RDBTRECON)){
1398
+ tcrdbsetecode(rdb, TTEINVALID);
1399
+ return false;
1400
+ }
1401
+ if(!tcrdbreconnect(rdb)) return false;
1402
+ }
1403
+ bool err = false;
1404
+ int rsiz = 2 + sizeof(uint32_t) * 3 + ksiz + vsiz;
1405
+ unsigned char stack[TTIOBUFSIZ];
1406
+ unsigned char *buf = (rsiz < TTIOBUFSIZ) ? stack : tcmalloc(rsiz);
1407
+ pthread_cleanup_push(free, (buf == stack) ? NULL : buf);
1408
+ unsigned char *wp = buf;
1409
+ *(wp++) = TTMAGICNUM;
1410
+ *(wp++) = TTCMDPUTSHL;
1411
+ uint32_t num;
1412
+ num = TTHTONL((uint32_t)ksiz);
1413
+ memcpy(wp, &num, sizeof(uint32_t));
1414
+ wp += sizeof(uint32_t);
1415
+ num = TTHTONL((uint32_t)vsiz);
1416
+ memcpy(wp, &num, sizeof(uint32_t));
1417
+ wp += sizeof(uint32_t);
1418
+ num = TTHTONL((uint32_t)width);
1419
+ memcpy(wp, &num, sizeof(uint32_t));
1420
+ wp += sizeof(uint32_t);
1421
+ memcpy(wp, kbuf, ksiz);
1422
+ wp += ksiz;
1423
+ memcpy(wp, vbuf, vsiz);
1424
+ wp += vsiz;
1425
+ if(tcrdbsend(rdb, buf, wp - buf)){
1426
+ int code = ttsockgetc(rdb->sock);
1427
+ if(code != 0){
1428
+ tcrdbsetecode(rdb, code == -1 ? TTERECV : TTEMISC);
1429
+ err = true;
1430
+ }
1431
+ } else {
1432
+ err = true;
1433
+ }
1434
+ pthread_cleanup_pop(1);
1435
+ return !err;
1436
+ }
1437
+
1438
+
1439
+ /* Store a record into a remote database object without response from the server.
1440
+ `rdb' specifies the remote database object.
1441
+ `kbuf' specifies the pointer to the region of the key.
1442
+ `ksiz' specifies the size of the region of the key.
1443
+ `vbuf' specifies the pointer to the region of the value.
1444
+ `vsiz' specifies the size of the region of the value.
1445
+ If successful, the return value is true, else, it is false. */
1446
+ static bool tcrdbputnrimpl(TCRDB *rdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz){
1447
+ assert(rdb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
1448
+ if(rdb->fd < 0){
1449
+ if(!rdb->host || !(rdb->opts & RDBTRECON)){
1450
+ tcrdbsetecode(rdb, TTEINVALID);
1451
+ return false;
1452
+ }
1453
+ if(!tcrdbreconnect(rdb)) return false;
1454
+ }
1455
+ bool err = false;
1456
+ int rsiz = 2 + sizeof(uint32_t) * 2 + ksiz + vsiz;
1457
+ unsigned char stack[TTIOBUFSIZ];
1458
+ unsigned char *buf = (rsiz < TTIOBUFSIZ) ? stack : tcmalloc(rsiz);
1459
+ pthread_cleanup_push(free, (buf == stack) ? NULL : buf);
1460
+ unsigned char *wp = buf;
1461
+ *(wp++) = TTMAGICNUM;
1462
+ *(wp++) = TTCMDPUTNR;
1463
+ uint32_t num;
1464
+ num = TTHTONL((uint32_t)ksiz);
1465
+ memcpy(wp, &num, sizeof(uint32_t));
1466
+ wp += sizeof(uint32_t);
1467
+ num = TTHTONL((uint32_t)vsiz);
1468
+ memcpy(wp, &num, sizeof(uint32_t));
1469
+ wp += sizeof(uint32_t);
1470
+ memcpy(wp, kbuf, ksiz);
1471
+ wp += ksiz;
1472
+ memcpy(wp, vbuf, vsiz);
1473
+ wp += vsiz;
1474
+ if(!tcrdbsend(rdb, buf, wp - buf)) err = true;
1475
+ pthread_cleanup_pop(1);
1476
+ return !err;
1477
+ }
1478
+
1479
+
1480
+ /* Remove a record of a remote database object.
1481
+ `rdb' specifies the remote database object.
1482
+ `kbuf' specifies the pointer to the region of the key.
1483
+ `ksiz' specifies the size of the region of the key.
1484
+ If successful, the return value is true, else, it is false. */
1485
+ static bool tcrdboutimpl(TCRDB *rdb, const void *kbuf, int ksiz){
1486
+ assert(rdb && kbuf && ksiz >= 0);
1487
+ if(rdb->fd < 0){
1488
+ if(!rdb->host || !(rdb->opts & RDBTRECON)){
1489
+ tcrdbsetecode(rdb, TTEINVALID);
1490
+ return false;
1491
+ }
1492
+ if(!tcrdbreconnect(rdb)) return false;
1493
+ }
1494
+ bool err = false;
1495
+ int rsiz = 2 + sizeof(uint32_t) + ksiz;
1496
+ unsigned char stack[TTIOBUFSIZ];
1497
+ unsigned char *buf = (rsiz < TTIOBUFSIZ) ? stack : tcmalloc(rsiz);
1498
+ pthread_cleanup_push(free, (buf == stack) ? NULL : buf);
1499
+ unsigned char *wp = buf;
1500
+ *(wp++) = TTMAGICNUM;
1501
+ *(wp++) = TTCMDOUT;
1502
+ uint32_t num;
1503
+ num = TTHTONL((uint32_t)ksiz);
1504
+ memcpy(wp, &num, sizeof(uint32_t));
1505
+ wp += sizeof(uint32_t);
1506
+ memcpy(wp, kbuf, ksiz);
1507
+ wp += ksiz;
1508
+ if(tcrdbsend(rdb, buf, wp - buf)){
1509
+ int code = ttsockgetc(rdb->sock);
1510
+ if(code != 0){
1511
+ tcrdbsetecode(rdb, code == -1 ? TTERECV : TTENOREC);
1512
+ err = true;
1513
+ }
1514
+ } else {
1515
+ err = true;
1516
+ }
1517
+ pthread_cleanup_pop(1);
1518
+ return !err;
1519
+ }
1520
+
1521
+
1522
+ /* Retrieve a record in a remote database object.
1523
+ `rdb' specifies the remote database object.
1524
+ `kbuf' specifies the pointer to the region of the key.
1525
+ `ksiz' specifies the size of the region of the key.
1526
+ `sp' specifies the pointer to the variable into which the size of the region of the return
1527
+ value is assigned.
1528
+ If successful, the return value is the pointer to the region of the value of the corresponding
1529
+ record. */
1530
+ static void *tcrdbgetimpl(TCRDB *rdb, const void *kbuf, int ksiz, int *sp){
1531
+ assert(rdb && kbuf && ksiz >= 0 && sp);
1532
+ if(rdb->fd < 0){
1533
+ if(!rdb->host || !(rdb->opts & RDBTRECON)){
1534
+ tcrdbsetecode(rdb, TTEINVALID);
1535
+ return NULL;
1536
+ }
1537
+ if(!tcrdbreconnect(rdb)) return NULL;
1538
+ }
1539
+ char *vbuf = NULL;
1540
+ int rsiz = 2 + sizeof(uint32_t) + ksiz;
1541
+ unsigned char stack[TTIOBUFSIZ];
1542
+ unsigned char *buf = (rsiz < TTIOBUFSIZ) ? stack : tcmalloc(rsiz);
1543
+ pthread_cleanup_push(free, (buf == stack) ? NULL : buf);
1544
+ unsigned char *wp = buf;
1545
+ *(wp++) = TTMAGICNUM;
1546
+ *(wp++) = TTCMDGET;
1547
+ uint32_t num;
1548
+ num = TTHTONL((uint32_t)ksiz);
1549
+ memcpy(wp, &num, sizeof(uint32_t));
1550
+ wp += sizeof(uint32_t);
1551
+ memcpy(wp, kbuf, ksiz);
1552
+ wp += ksiz;
1553
+ if(tcrdbsend(rdb, buf, wp - buf)){
1554
+ int code = ttsockgetc(rdb->sock);
1555
+ if(code == 0){
1556
+ int vsiz = ttsockgetint32(rdb->sock);
1557
+ if(!ttsockcheckend(rdb->sock) && vsiz >= 0){
1558
+ vbuf = tcmalloc(vsiz + 1);
1559
+ if(ttsockrecv(rdb->sock, vbuf, vsiz)){
1560
+ vbuf[vsiz] = '\0';
1561
+ *sp = vsiz;
1562
+ } else {
1563
+ tcrdbsetecode(rdb, TTERECV);
1564
+ tcfree(vbuf);
1565
+ vbuf = NULL;
1566
+ }
1567
+ } else {
1568
+ tcrdbsetecode(rdb, TTERECV);
1569
+ }
1570
+ } else {
1571
+ tcrdbsetecode(rdb, code == -1 ? TTERECV : TTENOREC);
1572
+ }
1573
+ }
1574
+ pthread_cleanup_pop(1);
1575
+ return vbuf;
1576
+ }
1577
+
1578
+
1579
+ /* Retrieve records in a remote database object.
1580
+ `rdb' specifies the remote database object.
1581
+ `recs' specifies a map object containing the retrieval keys.
1582
+ If successful, the return value is true, else, it is false. */
1583
+ static bool tcrdbmgetimpl(TCRDB *rdb, TCMAP *recs){
1584
+ assert(rdb && recs);
1585
+ if(rdb->fd < 0){
1586
+ if(!rdb->host || !(rdb->opts & RDBTRECON)){
1587
+ tcrdbsetecode(rdb, TTEINVALID);
1588
+ return false;
1589
+ }
1590
+ if(!tcrdbreconnect(rdb)) return false;
1591
+ }
1592
+ bool err = false;
1593
+ TCXSTR *xstr = tcxstrnew();
1594
+ pthread_cleanup_push((void (*)(void *))tcxstrdel, xstr);
1595
+ uint8_t magic[2];
1596
+ magic[0] = TTMAGICNUM;
1597
+ magic[1] = TTCMDMGET;
1598
+ tcxstrcat(xstr, magic, sizeof(magic));
1599
+ uint32_t num;
1600
+ num = (uint32_t)tcmaprnum(recs);
1601
+ num = TTHTONL(num);
1602
+ tcxstrcat(xstr, &num, sizeof(num));
1603
+ tcmapiterinit(recs);
1604
+ const char *kbuf;
1605
+ int ksiz;
1606
+ while((kbuf = tcmapiternext(recs, &ksiz)) != NULL){
1607
+ num = TTHTONL((uint32_t)ksiz);
1608
+ tcxstrcat(xstr, &num, sizeof(num));
1609
+ tcxstrcat(xstr, kbuf, ksiz);
1610
+ }
1611
+ tcmapclear(recs);
1612
+ char stack[TTIOBUFSIZ];
1613
+ if(tcrdbsend(rdb, tcxstrptr(xstr), tcxstrsize(xstr))){
1614
+ int code = ttsockgetc(rdb->sock);
1615
+ int rnum = ttsockgetint32(rdb->sock);
1616
+ if(code == 0){
1617
+ if(!ttsockcheckend(rdb->sock) && rnum >= 0){
1618
+ for(int i = 0; i < rnum; i++){
1619
+ int rksiz = ttsockgetint32(rdb->sock);
1620
+ int rvsiz = ttsockgetint32(rdb->sock);
1621
+ if(ttsockcheckend(rdb->sock)){
1622
+ tcrdbsetecode(rdb, TTERECV);
1623
+ err = true;
1624
+ break;
1625
+ }
1626
+ int rsiz = rksiz + rvsiz;
1627
+ char *rbuf = (rsiz < TTIOBUFSIZ) ? stack : tcmalloc(rsiz + 1);
1628
+ if(ttsockrecv(rdb->sock, rbuf, rsiz)){
1629
+ tcmapput(recs, rbuf, rksiz, rbuf + rksiz, rvsiz);
1630
+ } else {
1631
+ tcrdbsetecode(rdb, TTERECV);
1632
+ err = true;
1633
+ }
1634
+ if(rbuf != stack) tcfree(rbuf);
1635
+ }
1636
+ } else {
1637
+ tcrdbsetecode(rdb, TTERECV);
1638
+ err = true;
1639
+ }
1640
+ } else {
1641
+ tcrdbsetecode(rdb, code == -1 ? TTERECV : TTENOREC);
1642
+ err = true;
1643
+ }
1644
+ } else {
1645
+ err = true;
1646
+ }
1647
+ pthread_cleanup_pop(1);
1648
+ return !err;
1649
+ }
1650
+
1651
+
1652
+ /* Get the size of the value of a record in a remote database object.
1653
+ `rdb' specifies the remote database object.
1654
+ `kbuf' specifies the pointer to the region of the key.
1655
+ `ksiz' specifies the size of the region of the key.
1656
+ If successful, the return value is the size of the value of the corresponding record, else,
1657
+ it is -1. */
1658
+ static int tcrdbvsizimpl(TCRDB *rdb, const void *kbuf, int ksiz){
1659
+ assert(rdb && kbuf && ksiz >= 0);
1660
+ if(rdb->fd < 0){
1661
+ if(!rdb->host || !(rdb->opts & RDBTRECON)){
1662
+ tcrdbsetecode(rdb, TTEINVALID);
1663
+ return -1;
1664
+ }
1665
+ if(!tcrdbreconnect(rdb)) return -1;
1666
+ }
1667
+ int vsiz = -1;
1668
+ int rsiz = 2 + sizeof(uint32_t) + ksiz;
1669
+ unsigned char stack[TTIOBUFSIZ];
1670
+ unsigned char *buf = (rsiz < TTIOBUFSIZ) ? stack : tcmalloc(rsiz);
1671
+ pthread_cleanup_push(free, (buf == stack) ? NULL : buf);
1672
+ unsigned char *wp = buf;
1673
+ *(wp++) = TTMAGICNUM;
1674
+ *(wp++) = TTCMDVSIZ;
1675
+ uint32_t num;
1676
+ num = TTHTONL((uint32_t)ksiz);
1677
+ memcpy(wp, &num, sizeof(uint32_t));
1678
+ wp += sizeof(uint32_t);
1679
+ memcpy(wp, kbuf, ksiz);
1680
+ wp += ksiz;
1681
+ if(tcrdbsend(rdb, buf, wp - buf)){
1682
+ int code = ttsockgetc(rdb->sock);
1683
+ if(code == 0){
1684
+ vsiz = ttsockgetint32(rdb->sock);
1685
+ if(ttsockcheckend(rdb->sock)){
1686
+ tcrdbsetecode(rdb, TTERECV);
1687
+ vsiz = -1;
1688
+ }
1689
+ } else {
1690
+ tcrdbsetecode(rdb, code == -1 ? TTERECV : TTENOREC);
1691
+ }
1692
+ }
1693
+ pthread_cleanup_pop(1);
1694
+ return vsiz;
1695
+ }
1696
+
1697
+
1698
+ /* Initialize the iterator of a remote database object.
1699
+ `rdb' specifies the remote database object.
1700
+ If successful, the return value is true, else, it is false. */
1701
+ static bool tcrdbiterinitimpl(TCRDB *rdb){
1702
+ assert(rdb);
1703
+ if(rdb->fd < 0){
1704
+ if(!rdb->host || !(rdb->opts & RDBTRECON)){
1705
+ tcrdbsetecode(rdb, TTEINVALID);
1706
+ return false;
1707
+ }
1708
+ if(!tcrdbreconnect(rdb)) return false;
1709
+ }
1710
+ bool err = false;
1711
+ unsigned char buf[TTIOBUFSIZ];
1712
+ unsigned char *wp = buf;
1713
+ *(wp++) = TTMAGICNUM;
1714
+ *(wp++) = TTCMDITERINIT;
1715
+ if(tcrdbsend(rdb, buf, wp - buf)){
1716
+ int code = ttsockgetc(rdb->sock);
1717
+ if(code != 0){
1718
+ tcrdbsetecode(rdb, code == -1 ? TTERECV : TTEMISC);
1719
+ err = true;
1720
+ }
1721
+ } else {
1722
+ err = true;
1723
+ }
1724
+ return !err;
1725
+ }
1726
+
1727
+
1728
+ /* Get the next key of the iterator of a remote database object.
1729
+ `rdb' specifies the remote database object.
1730
+ `sp' specifies the pointer to the variable into which the size of the region of the return
1731
+ value is assigned.
1732
+ If successful, the return value is the pointer to the region of the next key, else, it is
1733
+ `NULL'. */
1734
+ static void *tcrdbiternextimpl(TCRDB *rdb, int *sp){
1735
+ assert(rdb && sp);
1736
+ if(rdb->fd < 0){
1737
+ if(!rdb->host || !(rdb->opts & RDBTRECON)){
1738
+ tcrdbsetecode(rdb, TTEINVALID);
1739
+ return NULL;
1740
+ }
1741
+ if(!tcrdbreconnect(rdb)) return NULL;
1742
+ }
1743
+ char *vbuf = NULL;
1744
+ unsigned char buf[TTIOBUFSIZ];
1745
+ unsigned char *wp = buf;
1746
+ *(wp++) = TTMAGICNUM;
1747
+ *(wp++) = TTCMDITERNEXT;
1748
+ if(tcrdbsend(rdb, buf, wp - buf)){
1749
+ int code = ttsockgetc(rdb->sock);
1750
+ if(code == 0){
1751
+ int vsiz = ttsockgetint32(rdb->sock);
1752
+ if(!ttsockcheckend(rdb->sock) && vsiz >= 0){
1753
+ vbuf = tcmalloc(vsiz + 1);
1754
+ if(ttsockrecv(rdb->sock, vbuf, vsiz)){
1755
+ vbuf[vsiz] = '\0';
1756
+ *sp = vsiz;
1757
+ } else {
1758
+ tcrdbsetecode(rdb, TTERECV);
1759
+ tcfree(vbuf);
1760
+ vbuf = NULL;
1761
+ }
1762
+ } else {
1763
+ tcrdbsetecode(rdb, TTERECV);
1764
+ }
1765
+ } else {
1766
+ tcrdbsetecode(rdb, code == -1 ? TTERECV : TTENOREC);
1767
+ }
1768
+ }
1769
+ return vbuf;
1770
+ }
1771
+
1772
+
1773
+ /* Get forward matching keys in a remote database object.
1774
+ `rdb' specifies the remote database object.
1775
+ `pbuf' specifies the pointer to the region of the prefix.
1776
+ `psiz' specifies the size of the region of the prefix.
1777
+ `max' specifies the maximum number of keys to be fetched.
1778
+ The return value is a list object of the corresponding keys. */
1779
+ static TCLIST *tcrdbfwmkeysimpl(TCRDB *rdb, const void *pbuf, int psiz, int max){
1780
+ assert(rdb && pbuf && psiz >= 0);
1781
+ TCLIST *keys = tclistnew();
1782
+ if(rdb->fd < 0){
1783
+ if(!rdb->host || !(rdb->opts & RDBTRECON)){
1784
+ tcrdbsetecode(rdb, TTEINVALID);
1785
+ return NULL;
1786
+ }
1787
+ if(!tcrdbreconnect(rdb)) return NULL;
1788
+ }
1789
+ int rsiz = 2 + sizeof(uint32_t) * 2 + psiz;
1790
+ if(max < 0) max = INT_MAX;
1791
+ unsigned char stack[TTIOBUFSIZ];
1792
+ unsigned char *buf = (rsiz < TTIOBUFSIZ) ? stack : tcmalloc(rsiz);
1793
+ pthread_cleanup_push(free, (buf == stack) ? NULL : buf);
1794
+ unsigned char *wp = buf;
1795
+ *(wp++) = TTMAGICNUM;
1796
+ *(wp++) = TTCMDFWMKEYS;
1797
+ uint32_t num;
1798
+ num = TTHTONL((uint32_t)psiz);
1799
+ memcpy(wp, &num, sizeof(uint32_t));
1800
+ wp += sizeof(uint32_t);
1801
+ num = TTHTONL((uint32_t)max);
1802
+ memcpy(wp, &num, sizeof(uint32_t));
1803
+ wp += sizeof(uint32_t);
1804
+ memcpy(wp, pbuf, psiz);
1805
+ wp += psiz;
1806
+ if(tcrdbsend(rdb, buf, wp - buf)){
1807
+ int code = ttsockgetc(rdb->sock);
1808
+ if(code == 0){
1809
+ int knum = ttsockgetint32(rdb->sock);
1810
+ if(!ttsockcheckend(rdb->sock) && knum >= 0){
1811
+ for(int i = 0; i < knum; i++){
1812
+ int ksiz = ttsockgetint32(rdb->sock);
1813
+ if(ttsockcheckend(rdb->sock)){
1814
+ tcrdbsetecode(rdb, TTERECV);
1815
+ break;
1816
+ }
1817
+ char *kbuf = (ksiz < TTIOBUFSIZ) ? stack : tcmalloc(ksiz + 1);
1818
+ if(ttsockrecv(rdb->sock, kbuf, ksiz)){
1819
+ tclistpush(keys, kbuf, ksiz);
1820
+ } else {
1821
+ tcrdbsetecode(rdb, TTERECV);
1822
+ }
1823
+ if(kbuf != (char *)stack) tcfree(kbuf);
1824
+ }
1825
+ } else {
1826
+ tcrdbsetecode(rdb, TTERECV);
1827
+ }
1828
+ } else {
1829
+ tcrdbsetecode(rdb, code == -1 ? TTERECV : TTENOREC);
1830
+ }
1831
+ }
1832
+ pthread_cleanup_pop(1);
1833
+ return keys;
1834
+ }
1835
+
1836
+
1837
+ /* Add an integer to a record in a remote database object.
1838
+ `rdb' specifies the remote database object connected as a writer.
1839
+ `kbuf' specifies the pointer to the region of the key.
1840
+ `ksiz' specifies the size of the region of the key.
1841
+ `num' specifies the additional value.
1842
+ If successful, the return value is the summation value, else, it is `INT_MIN'. */
1843
+ static int tcrdbaddintimpl(TCRDB *rdb, const void *kbuf, int ksiz, int num){
1844
+ assert(rdb && kbuf && ksiz >= 0);
1845
+ if(rdb->fd < 0){
1846
+ if(!rdb->host || !(rdb->opts & RDBTRECON)){
1847
+ tcrdbsetecode(rdb, TTEINVALID);
1848
+ return INT_MIN;
1849
+ }
1850
+ if(!tcrdbreconnect(rdb)) return INT_MIN;
1851
+ }
1852
+ int sum = INT_MIN;
1853
+ int rsiz = 2 + sizeof(uint32_t) * 2 + ksiz;
1854
+ unsigned char stack[TTIOBUFSIZ];
1855
+ unsigned char *buf = (rsiz < TTIOBUFSIZ) ? stack : tcmalloc(rsiz);
1856
+ pthread_cleanup_push(free, (buf == stack) ? NULL : buf);
1857
+ unsigned char *wp = buf;
1858
+ *(wp++) = TTMAGICNUM;
1859
+ *(wp++) = TTCMDADDINT;
1860
+ uint32_t lnum;
1861
+ lnum = TTHTONL((uint32_t)ksiz);
1862
+ memcpy(wp, &lnum, sizeof(uint32_t));
1863
+ wp += sizeof(uint32_t);
1864
+ lnum = TTHTONL((uint32_t)num);
1865
+ memcpy(wp, &lnum, sizeof(uint32_t));
1866
+ wp += sizeof(uint32_t);
1867
+ memcpy(wp, kbuf, ksiz);
1868
+ wp += ksiz;
1869
+ if(tcrdbsend(rdb, buf, wp - buf)){
1870
+ int code = ttsockgetc(rdb->sock);
1871
+ if(code == 0){
1872
+ sum = ttsockgetint32(rdb->sock);
1873
+ if(ttsockcheckend(rdb->sock)){
1874
+ tcrdbsetecode(rdb, TTERECV);
1875
+ sum = -1;
1876
+ }
1877
+ } else {
1878
+ tcrdbsetecode(rdb, code == -1 ? TTERECV : TTEKEEP);
1879
+ }
1880
+ }
1881
+ pthread_cleanup_pop(1);
1882
+ return sum;
1883
+ }
1884
+
1885
+
1886
+ /* Add a real number to a record in a remote database object.
1887
+ `rdb' specifies the remote database object connected as a writer.
1888
+ `kbuf' specifies the pointer to the region of the key.
1889
+ `ksiz' specifies the size of the region of the key.
1890
+ `num' specifies the additional value.
1891
+ If successful, the return value is the summation value, else, it is Not-a-Number. */
1892
+ static double tcrdbadddoubleimpl(TCRDB *rdb, const void *kbuf, int ksiz, double num){
1893
+ assert(rdb && kbuf && ksiz >= 0);
1894
+ if(rdb->fd < 0){
1895
+ if(!rdb->host || !(rdb->opts & RDBTRECON)){
1896
+ tcrdbsetecode(rdb, TTEINVALID);
1897
+ return nan("");
1898
+ }
1899
+ if(!tcrdbreconnect(rdb)) return nan("");
1900
+ }
1901
+ double sum = nan("");
1902
+ int rsiz = 2 + sizeof(uint32_t) + sizeof(uint64_t) * 2 + ksiz;
1903
+ unsigned char stack[TTIOBUFSIZ];
1904
+ unsigned char *buf = (rsiz < TTIOBUFSIZ) ? stack : tcmalloc(rsiz);
1905
+ pthread_cleanup_push(free, (buf == stack) ? NULL : buf);
1906
+ unsigned char *wp = buf;
1907
+ *(wp++) = TTMAGICNUM;
1908
+ *(wp++) = TTCMDADDDOUBLE;
1909
+ uint32_t lnum;
1910
+ lnum = TTHTONL((uint32_t)ksiz);
1911
+ memcpy(wp, &lnum, sizeof(uint32_t));
1912
+ wp += sizeof(uint32_t);
1913
+ char dbuf[sizeof(uint64_t)*2];
1914
+ ttpackdouble(num, (char *)wp);
1915
+ wp += sizeof(dbuf);
1916
+ memcpy(wp, kbuf, ksiz);
1917
+ wp += ksiz;
1918
+ if(tcrdbsend(rdb, buf, wp - buf)){
1919
+ int code = ttsockgetc(rdb->sock);
1920
+ if(code == 0){
1921
+ if(ttsockrecv(rdb->sock, dbuf, sizeof(dbuf)) && !ttsockcheckend(rdb->sock)){
1922
+ sum = ttunpackdouble(dbuf);
1923
+ } else {
1924
+ tcrdbsetecode(rdb, TTERECV);
1925
+ }
1926
+ } else {
1927
+ tcrdbsetecode(rdb, code == -1 ? TTERECV : TTEKEEP);
1928
+ }
1929
+ }
1930
+ pthread_cleanup_pop(1);
1931
+ return sum;
1932
+ }
1933
+
1934
+
1935
+ /* Call a function of the scripting language extension.
1936
+ `rdb' specifies the remote database object.
1937
+ `name' specifies the function name.
1938
+ `opts' specifies options by bitwise-or.
1939
+ `kbuf' specifies the pointer to the region of the key.
1940
+ `ksiz' specifies the size of the region of the key.
1941
+ `vbuf' specifies the pointer to the region of the value.
1942
+ `vsiz' specifies the size of the region of the value.
1943
+ `sp' specifies the pointer to the variable into which the size of the region of the return
1944
+ value is assigned.
1945
+ If successful, the return value is the pointer to the region of the value of the response. */
1946
+ static void *tcrdbextimpl(TCRDB *rdb, const char *name, int opts,
1947
+ const void *kbuf, int ksiz, const void *vbuf, int vsiz, int *sp){
1948
+ assert(rdb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
1949
+ if(rdb->fd < 0){
1950
+ if(!rdb->host || !(rdb->opts & RDBTRECON)){
1951
+ tcrdbsetecode(rdb, TTEINVALID);
1952
+ return NULL;
1953
+ }
1954
+ if(!tcrdbreconnect(rdb)) return NULL;
1955
+ }
1956
+ char *xbuf = NULL;
1957
+ int nsiz = strlen(name);
1958
+ int rsiz = 2 + sizeof(uint32_t) * 4 + nsiz + ksiz + vsiz;
1959
+ unsigned char stack[TTIOBUFSIZ];
1960
+ unsigned char *buf = (rsiz < TTIOBUFSIZ) ? stack : tcmalloc(rsiz);
1961
+ pthread_cleanup_push(free, (buf == stack) ? NULL : buf);
1962
+ unsigned char *wp = buf;
1963
+ *(wp++) = TTMAGICNUM;
1964
+ *(wp++) = TTCMDEXT;
1965
+ uint32_t num;
1966
+ num = TTHTONL((uint32_t)nsiz);
1967
+ memcpy(wp, &num, sizeof(uint32_t));
1968
+ wp += sizeof(uint32_t);
1969
+ num = TTHTONL((uint32_t)opts);
1970
+ memcpy(wp, &num, sizeof(uint32_t));
1971
+ wp += sizeof(uint32_t);
1972
+ num = TTHTONL((uint32_t)ksiz);
1973
+ memcpy(wp, &num, sizeof(uint32_t));
1974
+ wp += sizeof(uint32_t);
1975
+ num = TTHTONL((uint32_t)vsiz);
1976
+ memcpy(wp, &num, sizeof(uint32_t));
1977
+ wp += sizeof(uint32_t);
1978
+ memcpy(wp, name, nsiz);
1979
+ wp += nsiz;
1980
+ memcpy(wp, kbuf, ksiz);
1981
+ wp += ksiz;
1982
+ memcpy(wp, vbuf, vsiz);
1983
+ wp += vsiz;
1984
+ if(tcrdbsend(rdb, buf, wp - buf)){
1985
+ int code = ttsockgetc(rdb->sock);
1986
+ if(code == 0){
1987
+ int xsiz = ttsockgetint32(rdb->sock);
1988
+ if(!ttsockcheckend(rdb->sock) && xsiz >= 0){
1989
+ xbuf = tcmalloc(xsiz + 1);
1990
+ if(ttsockrecv(rdb->sock, xbuf, xsiz)){
1991
+ xbuf[xsiz] = '\0';
1992
+ *sp = xsiz;
1993
+ } else {
1994
+ tcrdbsetecode(rdb, TTERECV);
1995
+ tcfree(xbuf);
1996
+ xbuf = NULL;
1997
+ }
1998
+ } else {
1999
+ tcrdbsetecode(rdb, TTERECV);
2000
+ }
2001
+ } else {
2002
+ tcrdbsetecode(rdb, code == -1 ? TTERECV : TTEMISC);
2003
+ }
2004
+ }
2005
+ pthread_cleanup_pop(1);
2006
+ return xbuf;
2007
+ }
2008
+
2009
+
2010
+ /* Synchronize updated contents of a remote database object with the file and the device.
2011
+ `rdb' specifies the remote database object.
2012
+ If successful, the return value is true, else, it is false. */
2013
+ static bool tcrdbsyncimpl(TCRDB *rdb){
2014
+ assert(rdb);
2015
+ if(rdb->fd < 0){
2016
+ if(!rdb->host || !(rdb->opts & RDBTRECON)){
2017
+ tcrdbsetecode(rdb, TTEINVALID);
2018
+ return false;
2019
+ }
2020
+ if(!tcrdbreconnect(rdb)) return false;
2021
+ }
2022
+ bool err = false;
2023
+ unsigned char buf[TTIOBUFSIZ];
2024
+ unsigned char *wp = buf;
2025
+ *(wp++) = TTMAGICNUM;
2026
+ *(wp++) = TTCMDSYNC;
2027
+ if(tcrdbsend(rdb, buf, wp - buf)){
2028
+ int code = ttsockgetc(rdb->sock);
2029
+ if(code != 0){
2030
+ tcrdbsetecode(rdb, code == -1 ? TTERECV : TTEMISC);
2031
+ err = true;
2032
+ }
2033
+ } else {
2034
+ err = true;
2035
+ }
2036
+ return !err;
2037
+ }
2038
+
2039
+ /* Optimize the storage of a remove database object.
2040
+ `rdb' specifies the remote database object.
2041
+ `params' specifies the string of the tuning parameters.
2042
+ If successful, the return value is true, else, it is false. */
2043
+ static bool tcrdboptimizeimpl(TCRDB *rdb, const char *params){
2044
+ assert(rdb);
2045
+ if(rdb->fd < 0){
2046
+ if(!rdb->host || !(rdb->opts & RDBTRECON)){
2047
+ tcrdbsetecode(rdb, TTEINVALID);
2048
+ return false;
2049
+ }
2050
+ if(!tcrdbreconnect(rdb)) return false;
2051
+ }
2052
+ if(!params) params = "";
2053
+ int psiz = strlen(params);
2054
+ bool err = false;
2055
+ int rsiz = 2 + sizeof(uint32_t) + psiz;
2056
+ unsigned char stack[TTIOBUFSIZ];
2057
+ unsigned char *buf = (rsiz < TTIOBUFSIZ) ? stack : tcmalloc(rsiz);
2058
+ pthread_cleanup_push(free, (buf == stack) ? NULL : buf);
2059
+ unsigned char *wp = buf;
2060
+ *(wp++) = TTMAGICNUM;
2061
+ *(wp++) = TTCMDOPTIMIZE;
2062
+ uint32_t num;
2063
+ num = TTHTONL((uint32_t)psiz);
2064
+ memcpy(wp, &num, sizeof(uint32_t));
2065
+ wp += sizeof(uint32_t);
2066
+ memcpy(wp, params, psiz);
2067
+ wp += psiz;
2068
+ if(tcrdbsend(rdb, buf, wp - buf)){
2069
+ int code = ttsockgetc(rdb->sock);
2070
+ if(code != 0){
2071
+ tcrdbsetecode(rdb, code == -1 ? TTERECV : TTEMISC);
2072
+ err = true;
2073
+ }
2074
+ } else {
2075
+ err = true;
2076
+ }
2077
+ pthread_cleanup_pop(1);
2078
+ return !err;
2079
+ }
2080
+
2081
+
2082
+ /* Remove all records of a remote database object.
2083
+ `rdb' specifies the remote database object.
2084
+ If successful, the return value is true, else, it is false. */
2085
+ static bool tcrdbvanishimpl(TCRDB *rdb){
2086
+ assert(rdb);
2087
+ if(rdb->fd < 0){
2088
+ if(!rdb->host || !(rdb->opts & RDBTRECON)){
2089
+ tcrdbsetecode(rdb, TTEINVALID);
2090
+ return false;
2091
+ }
2092
+ if(!tcrdbreconnect(rdb)) return false;
2093
+ }
2094
+ bool err = false;
2095
+ unsigned char buf[TTIOBUFSIZ];
2096
+ unsigned char *wp = buf;
2097
+ *(wp++) = TTMAGICNUM;
2098
+ *(wp++) = TTCMDVANISH;
2099
+ if(tcrdbsend(rdb, buf, wp - buf)){
2100
+ int code = ttsockgetc(rdb->sock);
2101
+ if(code != 0){
2102
+ tcrdbsetecode(rdb, code == -1 ? TTERECV : TTEMISC);
2103
+ err = true;
2104
+ }
2105
+ } else {
2106
+ err = true;
2107
+ }
2108
+ return !err;
2109
+ }
2110
+
2111
+
2112
+ /* Copy the database file of a remote database object.
2113
+ `rdb' specifies the remote database object.
2114
+ `path' specifies the path of the destination file.
2115
+ If successful, the return value is true, else, it is false. */
2116
+ static bool tcrdbcopyimpl(TCRDB *rdb, const char *path){
2117
+ assert(rdb && path);
2118
+ if(rdb->fd < 0){
2119
+ if(!rdb->host || !(rdb->opts & RDBTRECON)){
2120
+ tcrdbsetecode(rdb, TTEINVALID);
2121
+ return false;
2122
+ }
2123
+ if(!tcrdbreconnect(rdb)) return false;
2124
+ }
2125
+ bool err = false;
2126
+ int psiz = strlen(path);
2127
+ int rsiz = 2 + sizeof(uint32_t) + psiz;
2128
+ unsigned char stack[TTIOBUFSIZ];
2129
+ unsigned char *buf = (rsiz < TTIOBUFSIZ) ? stack : tcmalloc(rsiz);
2130
+ pthread_cleanup_push(free, (buf == stack) ? NULL : buf);
2131
+ unsigned char *wp = buf;
2132
+ *(wp++) = TTMAGICNUM;
2133
+ *(wp++) = TTCMDCOPY;
2134
+ uint32_t num;
2135
+ num = TTHTONL((uint32_t)psiz);
2136
+ memcpy(wp, &num, sizeof(uint32_t));
2137
+ wp += sizeof(uint32_t);
2138
+ memcpy(wp, path, psiz);
2139
+ wp += psiz;
2140
+ if(tcrdbsend(rdb, buf, wp - buf)){
2141
+ int code = ttsockgetc(rdb->sock);
2142
+ if(code != 0){
2143
+ tcrdbsetecode(rdb, code == -1 ? TTERECV : TTEMISC);
2144
+ err = true;
2145
+ }
2146
+ } else {
2147
+ err = true;
2148
+ }
2149
+ pthread_cleanup_pop(1);
2150
+ return !err;
2151
+ }
2152
+
2153
+
2154
+ /* Restore the database file of a remote database object from the update log.
2155
+ `rdb' specifies the remote database object.
2156
+ `path' specifies the path of the update log directory.
2157
+ `ts' specifies the beginning timestamp in microseconds.
2158
+ `opts' specifies options by bitwise-or.
2159
+ If successful, the return value is true, else, it is false. */
2160
+ static bool tcrdbrestoreimpl(TCRDB *rdb, const char *path, uint64_t ts, int opts){
2161
+ assert(rdb && path);
2162
+ if(rdb->fd < 0){
2163
+ if(!rdb->host || !(rdb->opts & RDBTRECON)){
2164
+ tcrdbsetecode(rdb, TTEINVALID);
2165
+ return false;
2166
+ }
2167
+ if(!tcrdbreconnect(rdb)) return false;
2168
+ }
2169
+ bool err = false;
2170
+ int psiz = strlen(path);
2171
+ int rsiz = 2 + sizeof(uint32_t) + sizeof(uint64_t) + sizeof(uint32_t) + psiz;
2172
+ unsigned char stack[TTIOBUFSIZ];
2173
+ unsigned char *buf = (rsiz < TTIOBUFSIZ) ? stack : tcmalloc(rsiz);
2174
+ pthread_cleanup_push(free, (buf == stack) ? NULL : buf);
2175
+ unsigned char *wp = buf;
2176
+ *(wp++) = TTMAGICNUM;
2177
+ *(wp++) = TTCMDRESTORE;
2178
+ uint32_t lnum = TTHTONL((uint32_t)psiz);
2179
+ memcpy(wp, &lnum, sizeof(uint32_t));
2180
+ wp += sizeof(uint32_t);
2181
+ uint64_t llnum = TTHTONLL(ts);
2182
+ memcpy(wp, &llnum, sizeof(uint64_t));
2183
+ wp += sizeof(uint64_t);
2184
+ lnum = TTHTONL((uint32_t)opts);
2185
+ memcpy(wp, &lnum, sizeof(uint32_t));
2186
+ wp += sizeof(uint32_t);
2187
+ memcpy(wp, path, psiz);
2188
+ wp += psiz;
2189
+ if(tcrdbsend(rdb, buf, wp - buf)){
2190
+ int code = ttsockgetc(rdb->sock);
2191
+ if(code != 0){
2192
+ tcrdbsetecode(rdb, code == -1 ? TTERECV : TTEMISC);
2193
+ err = true;
2194
+ }
2195
+ } else {
2196
+ err = true;
2197
+ }
2198
+ pthread_cleanup_pop(1);
2199
+ return !err;
2200
+ }
2201
+
2202
+
2203
+ /* Set the replication master of a remote database object.
2204
+ `rdb' specifies the remote database object.
2205
+ `host' specifies the name or the address of the server.
2206
+ `port' specifies the port number.
2207
+ `ts' specifies the beginning timestamp in microseconds.
2208
+ `opts' specifies options by bitwise-or: `RDBROCHKCON' for consistency checking.
2209
+ If successful, the return value is true, else, it is false. */
2210
+ static bool tcrdbsetmstimpl(TCRDB *rdb, const char *host, int port, uint64_t ts, int opts){
2211
+ assert(rdb);
2212
+ if(rdb->fd < 0){
2213
+ if(!rdb->host || !(rdb->opts & RDBTRECON)){
2214
+ tcrdbsetecode(rdb, TTEINVALID);
2215
+ return false;
2216
+ }
2217
+ if(!tcrdbreconnect(rdb)) return false;
2218
+ }
2219
+ if(!host) host = "";
2220
+ if(port < 0) port = 0;
2221
+ bool err = false;
2222
+ int hsiz = strlen(host);
2223
+ int rsiz = 2 + sizeof(uint32_t) * 3 + hsiz;
2224
+ unsigned char stack[TTIOBUFSIZ];
2225
+ unsigned char *buf = (rsiz < TTIOBUFSIZ) ? stack : tcmalloc(rsiz);
2226
+ pthread_cleanup_push(free, (buf == stack) ? NULL : buf);
2227
+ unsigned char *wp = buf;
2228
+ *(wp++) = TTMAGICNUM;
2229
+ *(wp++) = TTCMDSETMST;
2230
+ uint32_t lnum;
2231
+ lnum = TTHTONL((uint32_t)hsiz);
2232
+ memcpy(wp, &lnum, sizeof(uint32_t));
2233
+ wp += sizeof(uint32_t);
2234
+ lnum = TTHTONL((uint32_t)port);
2235
+ memcpy(wp, &lnum, sizeof(uint32_t));
2236
+ wp += sizeof(uint32_t);
2237
+ uint64_t llnum;
2238
+ llnum = TTHTONLL(ts);
2239
+ memcpy(wp, &llnum, sizeof(uint64_t));
2240
+ wp += sizeof(uint64_t);
2241
+ lnum = TTHTONL((uint32_t)opts);
2242
+ memcpy(wp, &lnum, sizeof(uint32_t));
2243
+ wp += sizeof(uint32_t);
2244
+ memcpy(wp, host, hsiz);
2245
+ wp += hsiz;
2246
+ if(tcrdbsend(rdb, buf, wp - buf)){
2247
+ int code = ttsockgetc(rdb->sock);
2248
+ if(code != 0){
2249
+ tcrdbsetecode(rdb, code == -1 ? TTERECV : TTEMISC);
2250
+ err = true;
2251
+ }
2252
+ } else {
2253
+ err = true;
2254
+ }
2255
+ pthread_cleanup_pop(1);
2256
+ return !err;
2257
+ }
2258
+
2259
+
2260
+ /* Get the simple server expression of an abstract database object.
2261
+ `rdb' specifies the remote database object.
2262
+ The return value is the simple server expression or `NULL' if the object does not connect to
2263
+ any database server. */
2264
+ const char *tcrdbexprimpl(TCRDB *rdb){
2265
+ assert(rdb);
2266
+ if(!rdb->host){
2267
+ tcrdbsetecode(rdb, TTEINVALID);
2268
+ return NULL;
2269
+ }
2270
+ return rdb->expr;
2271
+ }
2272
+
2273
+
2274
+ /* Get the number of records of a remote database object.
2275
+ `rdb' specifies the remote database object.
2276
+ The return value is the number of records or 0 if the object does not connect to any database
2277
+ server. */
2278
+ static uint64_t tcrdbrnumimpl(TCRDB *rdb){
2279
+ assert(rdb);
2280
+ if(rdb->fd < 0){
2281
+ if(!rdb->host || !(rdb->opts & RDBTRECON)){
2282
+ tcrdbsetecode(rdb, TTEINVALID);
2283
+ return 0;
2284
+ }
2285
+ if(!tcrdbreconnect(rdb)) return 0;
2286
+ }
2287
+ unsigned char buf[TTIOBUFSIZ];
2288
+ unsigned char *wp = buf;
2289
+ *(wp++) = TTMAGICNUM;
2290
+ *(wp++) = TTCMDRNUM;
2291
+ uint64_t rnum = 0;
2292
+ if(tcrdbsend(rdb, buf, wp - buf)){
2293
+ int code = ttsockgetc(rdb->sock);
2294
+ if(code == 0){
2295
+ rnum = ttsockgetint64(rdb->sock);
2296
+ if(ttsockcheckend(rdb->sock)){
2297
+ rnum = 0;
2298
+ tcrdbsetecode(rdb, TTERECV);
2299
+ }
2300
+ } else {
2301
+ tcrdbsetecode(rdb, code == -1 ? TTERECV : TTEMISC);
2302
+ }
2303
+ }
2304
+ return rnum;
2305
+ }
2306
+
2307
+
2308
+ /* Get the size of the database of a remote database object.
2309
+ `rdb' specifies the remote database object.
2310
+ The return value is the size of the database or 0 if the object does not connect to any
2311
+ database server. */
2312
+ static uint64_t tcrdbsizeimpl(TCRDB *rdb){
2313
+ assert(rdb);
2314
+ if(rdb->fd < 0){
2315
+ if(!rdb->host || !(rdb->opts & RDBTRECON)){
2316
+ tcrdbsetecode(rdb, TTEINVALID);
2317
+ return 0;
2318
+ }
2319
+ if(!tcrdbreconnect(rdb)) return 0;
2320
+ }
2321
+ unsigned char buf[TTIOBUFSIZ];
2322
+ unsigned char *wp = buf;
2323
+ *(wp++) = TTMAGICNUM;
2324
+ *(wp++) = TTCMDSIZE;
2325
+ uint64_t size = 0;
2326
+ if(tcrdbsend(rdb, buf, wp - buf)){
2327
+ int code = ttsockgetc(rdb->sock);
2328
+ if(code == 0){
2329
+ size = ttsockgetint64(rdb->sock);
2330
+ if(ttsockcheckend(rdb->sock)){
2331
+ size = 0;
2332
+ tcrdbsetecode(rdb, TTERECV);
2333
+ }
2334
+ } else {
2335
+ tcrdbsetecode(rdb, code == -1 ? TTERECV : TTEMISC);
2336
+ }
2337
+ }
2338
+ return size;
2339
+ }
2340
+
2341
+
2342
+ /* Get the status string of the database of a remote database object.
2343
+ `rdb' specifies the remote database object.
2344
+ The return value is the status message of the database or `NULL' if the object does not
2345
+ connect to any database server. */
2346
+ static char *tcrdbstatimpl(TCRDB *rdb){
2347
+ assert(rdb);
2348
+ if(rdb->fd < 0){
2349
+ if(!rdb->host || !(rdb->opts & RDBTRECON)){
2350
+ tcrdbsetecode(rdb, TTEINVALID);
2351
+ return NULL;
2352
+ }
2353
+ if(!tcrdbreconnect(rdb)) return NULL;
2354
+ }
2355
+ unsigned char buf[TTIOBUFSIZ];
2356
+ unsigned char *wp = buf;
2357
+ *(wp++) = TTMAGICNUM;
2358
+ *(wp++) = TTCMDSTAT;
2359
+ uint32_t size = 0;
2360
+ if(tcrdbsend(rdb, buf, wp - buf)){
2361
+ int code = ttsockgetc(rdb->sock);
2362
+ if(code == 0){
2363
+ size = ttsockgetint32(rdb->sock);
2364
+ if(ttsockcheckend(rdb->sock) || size >= TTIOBUFSIZ ||
2365
+ !ttsockrecv(rdb->sock, (char *)buf, size)){
2366
+ size = 0;
2367
+ tcrdbsetecode(rdb, TTERECV);
2368
+ }
2369
+ } else {
2370
+ tcrdbsetecode(rdb, code == -1 ? TTERECV : TTEMISC);
2371
+ }
2372
+ }
2373
+ if(size < 1){
2374
+ tcrdbsetecode(rdb, TTEMISC);
2375
+ return NULL;
2376
+ }
2377
+ return tcmemdup(buf, size);
2378
+ }
2379
+
2380
+
2381
+ /* Call a versatile function for miscellaneous operations of a remote database object.
2382
+ `rdb' specifies the remote database object.
2383
+ `name' specifies the name of the function.
2384
+ `opts' specifies options by bitwise-or.
2385
+ `args' specifies a list object containing arguments.
2386
+ If successful, the return value is a list object of the result. */
2387
+ static TCLIST *tcrdbmiscimpl(TCRDB *rdb, const char *name, int opts, const TCLIST *args){
2388
+ assert(rdb && name && args);
2389
+ if(rdb->fd < 0){
2390
+ if(!rdb->host || !(rdb->opts & RDBTRECON)){
2391
+ tcrdbsetecode(rdb, TTEINVALID);
2392
+ return NULL;
2393
+ }
2394
+ if(!tcrdbreconnect(rdb)) return NULL;
2395
+ }
2396
+ bool err = false;
2397
+ TCLIST *res = NULL;
2398
+ TCXSTR *xstr = tcxstrnew();
2399
+ pthread_cleanup_push((void (*)(void *))tcxstrdel, xstr);
2400
+ uint8_t magic[2];
2401
+ magic[0] = TTMAGICNUM;
2402
+ magic[1] = TTCMDMISC;
2403
+ tcxstrcat(xstr, magic, sizeof(magic));
2404
+ int nsiz = strlen(name);
2405
+ uint32_t num;
2406
+ num = TTHTONL((uint32_t)nsiz);
2407
+ tcxstrcat(xstr, &num, sizeof(num));
2408
+ num = TTHTONL((uint32_t)opts);
2409
+ tcxstrcat(xstr, &num, sizeof(num));
2410
+ num = tclistnum(args);
2411
+ num = TTHTONL(num);
2412
+ tcxstrcat(xstr, &num, sizeof(num));
2413
+ tcxstrcat(xstr, name, nsiz);
2414
+ for(int i = 0; i < tclistnum(args); i++){
2415
+ int rsiz;
2416
+ const char *rbuf = tclistval(args, i, &rsiz);
2417
+ num = TTHTONL((uint32_t)rsiz);
2418
+ tcxstrcat(xstr, &num, sizeof(num));
2419
+ tcxstrcat(xstr, rbuf, rsiz);
2420
+ }
2421
+ char stack[TTIOBUFSIZ];
2422
+ if(tcrdbsend(rdb, tcxstrptr(xstr), tcxstrsize(xstr))){
2423
+ int code = ttsockgetc(rdb->sock);
2424
+ int rnum = ttsockgetint32(rdb->sock);
2425
+ if(code == 0){
2426
+ if(!ttsockcheckend(rdb->sock) && rnum >= 0){
2427
+ res = tclistnew2(rnum);
2428
+ for(int i = 0; i < rnum; i++){
2429
+ int esiz = ttsockgetint32(rdb->sock);
2430
+ if(ttsockcheckend(rdb->sock)){
2431
+ tcrdbsetecode(rdb, TTERECV);
2432
+ err = true;
2433
+ break;
2434
+ }
2435
+ char *ebuf = (esiz < TTIOBUFSIZ) ? stack : tcmalloc(esiz + 1);
2436
+ if(ttsockrecv(rdb->sock, ebuf, esiz)){
2437
+ tclistpush(res, ebuf, esiz);
2438
+ } else {
2439
+ tcrdbsetecode(rdb, TTERECV);
2440
+ err = true;
2441
+ }
2442
+ if(ebuf != stack) tcfree(ebuf);
2443
+ }
2444
+ } else {
2445
+ tcrdbsetecode(rdb, TTERECV);
2446
+ err = true;
2447
+ }
2448
+ } else {
2449
+ tcrdbsetecode(rdb, code == -1 ? TTERECV : TTEMISC);
2450
+ err = true;
2451
+ }
2452
+ } else {
2453
+ err = true;
2454
+ }
2455
+ pthread_cleanup_pop(1);
2456
+ if(res && err){
2457
+ tclistdel(res);
2458
+ res = NULL;
2459
+ }
2460
+ return res;
2461
+ }
2462
+
2463
+
2464
+ /* Pop meta data from the result list to the member of the query object.
2465
+ `qry' specifies the query object.
2466
+ `res' specifies the list object of the primary keys. */
2467
+ static void tcrdbqrypopmeta(RDBQRY *qry, TCLIST *res){
2468
+ assert(qry && res);
2469
+ for(int i = tclistnum(res) - 1; i >= 0; i--){
2470
+ int pksiz;
2471
+ const char *pkbuf = tclistval(res, i, &pksiz);
2472
+ if(pksiz >= 11 && pkbuf[0] == '\0' && pkbuf[1] == '\0'){
2473
+ if(!memcmp(pkbuf + 2, "[[HINT]]\n", 9)){
2474
+ int hsiz;
2475
+ char *hbuf = tclistpop(res, &hsiz);
2476
+ tcxstrcat(qry->hint, hbuf + 10, hsiz - 10);
2477
+ tcfree(hbuf);
2478
+ } else {
2479
+ break;
2480
+ }
2481
+ } else {
2482
+ break;
2483
+ }
2484
+ }
2485
+ }
2486
+
2487
+
2488
+ /* Search a server in parallel.
2489
+ `arg' specifies the artument structure of the query and the result.
2490
+ The return value is always `NULL'. */
2491
+ static void *tcrdbparasearchworker(PARASEARCHARG *arg){
2492
+ assert(arg);
2493
+ RDBQRY *qry = arg->qry;
2494
+ TCLIST *args = tclistdup(qry->args);
2495
+ tclistpush2(args, "get");
2496
+ TCXSTR *xstr = tcxstrnew();
2497
+ tcxstrcat2(xstr, "setlimit");
2498
+ tcxstrcat(xstr, "\0", 1);
2499
+ tcxstrprintf(xstr, "%d", arg->max + arg->skip);
2500
+ tcxstrcat(xstr, "\0", 1);
2501
+ tcxstrprintf(xstr, "%d", 0);
2502
+ tclistpush(args, tcxstrptr(xstr), tcxstrsize(xstr));
2503
+ tcxstrdel(xstr);
2504
+ arg->res = tcrdbmisc(qry->rdb, "search", RDBMONOULOG, args);
2505
+ tclistdel(args);
2506
+ return NULL;
2507
+ }
2508
+
2509
+
2510
+ /* Convert a string to a real number.
2511
+ `str' specifies the string.
2512
+ The return value is the real number. */
2513
+ static long double tcrdbatof(const char *str){
2514
+ assert(str);
2515
+ while(*str > '\0' && *str <= ' '){
2516
+ str++;
2517
+ }
2518
+ int sign = 1;
2519
+ if(*str == '-'){
2520
+ str++;
2521
+ sign = -1;
2522
+ } else if(*str == '+'){
2523
+ str++;
2524
+ }
2525
+ if(tcstrifwm(str, "inf")) return HUGE_VALL * sign;
2526
+ if(tcstrifwm(str, "nan")) return nanl("");
2527
+ long double num = 0;
2528
+ int col = 0;
2529
+ while(*str != '\0'){
2530
+ if(*str < '0' || *str > '9') break;
2531
+ num = num * 10 + *str - '0';
2532
+ str++;
2533
+ if(num > 0) col++;
2534
+ }
2535
+ if(*str == '.'){
2536
+ str++;
2537
+ long double fract = 0.0;
2538
+ long double base = 10;
2539
+ while(col < RDBNUMCOLMAX && *str != '\0'){
2540
+ if(*str < '0' || *str > '9') break;
2541
+ fract += (*str - '0') / base;
2542
+ str++;
2543
+ col++;
2544
+ base *= 10;
2545
+ }
2546
+ num += fract;
2547
+ }
2548
+ return num * sign;
2549
+ }
2550
+
2551
+
2552
+ /* Compare two sort records by string ascending.
2553
+ `a' specifies a key.
2554
+ `b' specifies of the other key.
2555
+ The return value is positive if the former is big, negative if the latter is big, 0 if both
2556
+ are equivalent. */
2557
+ static int rdbcmpsortrecstrasc(const RDBSORTREC *a, const RDBSORTREC *b){
2558
+ assert(a && b);
2559
+ if(!a->obuf){
2560
+ if(!b->obuf) return 0;
2561
+ return 1;
2562
+ }
2563
+ if(!b->obuf){
2564
+ if(!a->obuf) return 0;
2565
+ return -1;
2566
+ }
2567
+ return tccmplexical(a->obuf, a->osiz, b->obuf, b->osiz, NULL);
2568
+ }
2569
+
2570
+
2571
+ /* Compare two sort records by string descending.
2572
+ `a' specifies a key.
2573
+ `b' specifies of the other key.
2574
+ The return value is positive if the former is big, negative if the latter is big, 0 if both
2575
+ are equivalent. */
2576
+ static int rdbcmpsortrecstrdesc(const RDBSORTREC *a, const RDBSORTREC *b){
2577
+ assert(a && b);
2578
+ if(!a->obuf){
2579
+ if(!b->obuf) return 0;
2580
+ return 1;
2581
+ }
2582
+ if(!b->obuf){
2583
+ if(!a->obuf) return 0;
2584
+ return -1;
2585
+ }
2586
+ return -tccmplexical(a->obuf, a->osiz, b->obuf, b->osiz, NULL);
2587
+ }
2588
+
2589
+
2590
+ /* Compare two sort records by number ascending.
2591
+ `a' specifies a key.
2592
+ `b' specifies of the other key.
2593
+ The return value is positive if the former is big, negative if the latter is big, 0 if both
2594
+ are equivalent. */
2595
+ static int rdbcmpsortrecnumasc(const RDBSORTREC *a, const RDBSORTREC *b){
2596
+ assert(a && b);
2597
+ if(!a->obuf){
2598
+ if(!b->obuf) return 0;
2599
+ return 1;
2600
+ }
2601
+ if(!b->obuf){
2602
+ if(!a->obuf) return 0;
2603
+ return -1;
2604
+ }
2605
+ long double anum = tcrdbatof(a->obuf);
2606
+ long double bnum = tcrdbatof(b->obuf);
2607
+ if(anum < bnum) return -1;
2608
+ if(anum > bnum) return 1;
2609
+ return 0;
2610
+ }
2611
+
2612
+
2613
+ /* Compare two sort records by number descending.
2614
+ `a' specifies a key.
2615
+ `b' specifies of the other key.
2616
+ The return value is positive if the former is big, negative if the latter is big, 0 if both
2617
+ are equivalent. */
2618
+ static int rdbcmpsortrecnumdesc(const RDBSORTREC *a, const RDBSORTREC *b){
2619
+ assert(a && b);
2620
+ if(!a->obuf){
2621
+ if(!b->obuf) return 0;
2622
+ return 1;
2623
+ }
2624
+ if(!b->obuf){
2625
+ if(!a->obuf) return 0;
2626
+ return -1;
2627
+ }
2628
+ long double anum = tcrdbatof(a->obuf);
2629
+ long double bnum = tcrdbatof(b->obuf);
2630
+ if(anum < bnum) return 1;
2631
+ if(anum > bnum) return -1;
2632
+ return 0;
2633
+ }
2634
+
2635
+
2636
+
2637
+ // END OF FILE