prestogres 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (393) hide show
  1. data/.gitignore +4 -0
  2. data/Gemfile +2 -0
  3. data/Gemfile.lock +20 -0
  4. data/LICENSE +202 -0
  5. data/NOTICE +22 -0
  6. data/README.md +217 -0
  7. data/Rakefile +13 -0
  8. data/VERSION +1 -0
  9. data/bin/prestogres +254 -0
  10. data/config/pcp.conf.sample +28 -0
  11. data/config/pgpool.conf +678 -0
  12. data/config/pool_hba.conf +84 -0
  13. data/config/pool_passwd +0 -0
  14. data/config/postgresql.conf +2 -0
  15. data/ext/.gitignore +6 -0
  16. data/ext/depend +26 -0
  17. data/ext/extconf.rb +4 -0
  18. data/ext/prestogres_config.c +12 -0
  19. data/pgpool2/.gitignore +36 -0
  20. data/pgpool2/AUTHORS +4 -0
  21. data/pgpool2/COPYING +12 -0
  22. data/pgpool2/ChangeLog +1 -0
  23. data/pgpool2/INSTALL +1 -0
  24. data/pgpool2/Makefile.am +159 -0
  25. data/pgpool2/Makefile.in +1187 -0
  26. data/pgpool2/NEWS +4960 -0
  27. data/pgpool2/README +1 -0
  28. data/pgpool2/README.euc_jp +1 -0
  29. data/pgpool2/README.online-recovery +62 -0
  30. data/pgpool2/TODO +103 -0
  31. data/pgpool2/ac_func_accept_argtypes.m4 +85 -0
  32. data/pgpool2/aclocal.m4 +1088 -0
  33. data/pgpool2/c-compiler.m4 +134 -0
  34. data/pgpool2/c-library.m4 +325 -0
  35. data/pgpool2/child.c +2097 -0
  36. data/pgpool2/config.guess +1532 -0
  37. data/pgpool2/config.h.in +332 -0
  38. data/pgpool2/config.sub +1640 -0
  39. data/pgpool2/configure +15752 -0
  40. data/pgpool2/configure.in +392 -0
  41. data/pgpool2/depcomp +522 -0
  42. data/pgpool2/doc/basebackup.sh +17 -0
  43. data/pgpool2/doc/pgpool-de.html +4220 -0
  44. data/pgpool2/doc/pgpool-en.html +5738 -0
  45. data/pgpool2/doc/pgpool-fr.html +4118 -0
  46. data/pgpool2/doc/pgpool-ja.css +198 -0
  47. data/pgpool2/doc/pgpool-ja.html +11279 -0
  48. data/pgpool2/doc/pgpool-zh_cn.html +4445 -0
  49. data/pgpool2/doc/pgpool.css +280 -0
  50. data/pgpool2/doc/pgpool_remote_start +13 -0
  51. data/pgpool2/doc/recovery.conf.sample +117 -0
  52. data/pgpool2/doc/tutorial-en.html +707 -0
  53. data/pgpool2/doc/tutorial-ja.html +422 -0
  54. data/pgpool2/doc/tutorial-memqcache-en.html +325 -0
  55. data/pgpool2/doc/tutorial-memqcache-ja.html +370 -0
  56. data/pgpool2/doc/tutorial-memqcache-zh_cn.html +322 -0
  57. data/pgpool2/doc/tutorial-watchdog-en.html +306 -0
  58. data/pgpool2/doc/tutorial-watchdog-ja.html +343 -0
  59. data/pgpool2/doc/tutorial-watchdog-zh_cn.html +301 -0
  60. data/pgpool2/doc/tutorial-zh_cn.html +537 -0
  61. data/pgpool2/doc/watchdog.png +0 -0
  62. data/pgpool2/doc/wd-en.html +236 -0
  63. data/pgpool2/doc/wd-en.jpg +0 -0
  64. data/pgpool2/doc/wd-ja.html +219 -0
  65. data/pgpool2/doc/wd-ja.jpg +0 -0
  66. data/pgpool2/doc/wd-zh_cn.html +201 -0
  67. data/pgpool2/doc/where_to_send_queries.odg +0 -0
  68. data/pgpool2/doc/where_to_send_queries.pdf +0 -0
  69. data/pgpool2/general.m4 +166 -0
  70. data/pgpool2/getopt_long.c +200 -0
  71. data/pgpool2/getopt_long.h +44 -0
  72. data/pgpool2/install-sh +251 -0
  73. data/pgpool2/ltmain.sh +8406 -0
  74. data/pgpool2/m4/libtool.m4 +7360 -0
  75. data/pgpool2/m4/ltoptions.m4 +368 -0
  76. data/pgpool2/m4/ltsugar.m4 +123 -0
  77. data/pgpool2/m4/ltversion.m4 +23 -0
  78. data/pgpool2/m4/lt~obsolete.m4 +92 -0
  79. data/pgpool2/main.c +2971 -0
  80. data/pgpool2/md5.c +444 -0
  81. data/pgpool2/md5.h +28 -0
  82. data/pgpool2/missing +360 -0
  83. data/pgpool2/mkinstalldirs +40 -0
  84. data/pgpool2/parser/Makefile.am +50 -0
  85. data/pgpool2/parser/Makefile.in +559 -0
  86. data/pgpool2/parser/copyfuncs.c +3310 -0
  87. data/pgpool2/parser/gram.c +39100 -0
  88. data/pgpool2/parser/gram.h +940 -0
  89. data/pgpool2/parser/gram.y +13408 -0
  90. data/pgpool2/parser/gramparse.h +74 -0
  91. data/pgpool2/parser/keywords.c +32 -0
  92. data/pgpool2/parser/keywords.h +39 -0
  93. data/pgpool2/parser/kwlist.h +425 -0
  94. data/pgpool2/parser/kwlookup.c +88 -0
  95. data/pgpool2/parser/list.c +1156 -0
  96. data/pgpool2/parser/makefuncs.c +518 -0
  97. data/pgpool2/parser/makefuncs.h +83 -0
  98. data/pgpool2/parser/memnodes.h +79 -0
  99. data/pgpool2/parser/nodes.c +29 -0
  100. data/pgpool2/parser/nodes.h +609 -0
  101. data/pgpool2/parser/outfuncs.c +5790 -0
  102. data/pgpool2/parser/parsenodes.h +2615 -0
  103. data/pgpool2/parser/parser.c +262 -0
  104. data/pgpool2/parser/parser.h +46 -0
  105. data/pgpool2/parser/pg_class.h +158 -0
  106. data/pgpool2/parser/pg_config_manual.h +273 -0
  107. data/pgpool2/parser/pg_list.h +352 -0
  108. data/pgpool2/parser/pg_trigger.h +147 -0
  109. data/pgpool2/parser/pg_wchar.h +492 -0
  110. data/pgpool2/parser/pool_memory.c +342 -0
  111. data/pgpool2/parser/pool_memory.h +77 -0
  112. data/pgpool2/parser/pool_parser.h +222 -0
  113. data/pgpool2/parser/pool_string.c +121 -0
  114. data/pgpool2/parser/pool_string.h +37 -0
  115. data/pgpool2/parser/primnodes.h +1280 -0
  116. data/pgpool2/parser/scan.c +4094 -0
  117. data/pgpool2/parser/scan.l +1451 -0
  118. data/pgpool2/parser/scanner.h +120 -0
  119. data/pgpool2/parser/scansup.c +221 -0
  120. data/pgpool2/parser/scansup.h +28 -0
  121. data/pgpool2/parser/snprintf.c +1102 -0
  122. data/pgpool2/parser/stringinfo.c +294 -0
  123. data/pgpool2/parser/stringinfo.h +178 -0
  124. data/pgpool2/parser/value.c +78 -0
  125. data/pgpool2/parser/value.h +62 -0
  126. data/pgpool2/parser/wchar.c +2048 -0
  127. data/pgpool2/pcp.conf.sample +28 -0
  128. data/pgpool2/pcp/Makefile.am +40 -0
  129. data/pgpool2/pcp/Makefile.in +771 -0
  130. data/pgpool2/pcp/libpcp_ext.h +250 -0
  131. data/pgpool2/pcp/md5.c +444 -0
  132. data/pgpool2/pcp/md5.h +28 -0
  133. data/pgpool2/pcp/pcp.c +1652 -0
  134. data/pgpool2/pcp/pcp.h +61 -0
  135. data/pgpool2/pcp/pcp_attach_node.c +172 -0
  136. data/pgpool2/pcp/pcp_detach_node.c +185 -0
  137. data/pgpool2/pcp/pcp_error.c +87 -0
  138. data/pgpool2/pcp/pcp_node_count.c +160 -0
  139. data/pgpool2/pcp/pcp_node_info.c +198 -0
  140. data/pgpool2/pcp/pcp_pool_status.c +166 -0
  141. data/pgpool2/pcp/pcp_proc_count.c +166 -0
  142. data/pgpool2/pcp/pcp_proc_info.c +261 -0
  143. data/pgpool2/pcp/pcp_promote_node.c +185 -0
  144. data/pgpool2/pcp/pcp_recovery_node.c +172 -0
  145. data/pgpool2/pcp/pcp_stop_pgpool.c +179 -0
  146. data/pgpool2/pcp/pcp_stream.c +385 -0
  147. data/pgpool2/pcp/pcp_stream.h +52 -0
  148. data/pgpool2/pcp/pcp_systemdb_info.c +194 -0
  149. data/pgpool2/pcp/pcp_watchdog_info.c +211 -0
  150. data/pgpool2/pcp_child.c +1493 -0
  151. data/pgpool2/pg_md5.c +305 -0
  152. data/pgpool2/pgpool.8.in +121 -0
  153. data/pgpool2/pgpool.conf +553 -0
  154. data/pgpool2/pgpool.conf.sample +666 -0
  155. data/pgpool2/pgpool.conf.sample-master-slave +665 -0
  156. data/pgpool2/pgpool.conf.sample-replication +664 -0
  157. data/pgpool2/pgpool.conf.sample-stream +664 -0
  158. data/pgpool2/pgpool.spec +264 -0
  159. data/pgpool2/pgpool_adm/TODO +7 -0
  160. data/pgpool2/pgpool_adm/pgpool_adm--1.0.sql +85 -0
  161. data/pgpool2/pgpool_adm/pgpool_adm.c +558 -0
  162. data/pgpool2/pgpool_adm/pgpool_adm.control +5 -0
  163. data/pgpool2/pgpool_adm/pgpool_adm.h +46 -0
  164. data/pgpool2/pgpool_adm/pgpool_adm.sql.in +85 -0
  165. data/pgpool2/pool.h +655 -0
  166. data/pgpool2/pool_auth.c +1390 -0
  167. data/pgpool2/pool_config.c +5007 -0
  168. data/pgpool2/pool_config.h +284 -0
  169. data/pgpool2/pool_config.l +3281 -0
  170. data/pgpool2/pool_config_md5.c +29 -0
  171. data/pgpool2/pool_connection_pool.c +812 -0
  172. data/pgpool2/pool_error.c +242 -0
  173. data/pgpool2/pool_globals.c +27 -0
  174. data/pgpool2/pool_hba.c +1723 -0
  175. data/pgpool2/pool_hba.conf.sample +67 -0
  176. data/pgpool2/pool_ip.c +567 -0
  177. data/pgpool2/pool_ip.h +65 -0
  178. data/pgpool2/pool_ipc.h +38 -0
  179. data/pgpool2/pool_lobj.c +242 -0
  180. data/pgpool2/pool_lobj.h +32 -0
  181. data/pgpool2/pool_memqcache.c +3818 -0
  182. data/pgpool2/pool_memqcache.h +268 -0
  183. data/pgpool2/pool_params.c +163 -0
  184. data/pgpool2/pool_passwd.c +249 -0
  185. data/pgpool2/pool_passwd.h +41 -0
  186. data/pgpool2/pool_path.c +193 -0
  187. data/pgpool2/pool_path.h +81 -0
  188. data/pgpool2/pool_process_context.c +247 -0
  189. data/pgpool2/pool_process_context.h +62 -0
  190. data/pgpool2/pool_process_query.c +5001 -0
  191. data/pgpool2/pool_process_reporting.c +1671 -0
  192. data/pgpool2/pool_process_reporting.h +44 -0
  193. data/pgpool2/pool_proto2.c +671 -0
  194. data/pgpool2/pool_proto_modules.c +3524 -0
  195. data/pgpool2/pool_proto_modules.h +185 -0
  196. data/pgpool2/pool_query_cache.c +1020 -0
  197. data/pgpool2/pool_query_context.c +1871 -0
  198. data/pgpool2/pool_query_context.h +105 -0
  199. data/pgpool2/pool_relcache.c +284 -0
  200. data/pgpool2/pool_relcache.h +78 -0
  201. data/pgpool2/pool_rewrite_outfuncs.c +9060 -0
  202. data/pgpool2/pool_rewrite_query.c +715 -0
  203. data/pgpool2/pool_rewrite_query.h +192 -0
  204. data/pgpool2/pool_select_walker.c +1150 -0
  205. data/pgpool2/pool_select_walker.h +68 -0
  206. data/pgpool2/pool_sema.c +161 -0
  207. data/pgpool2/pool_session_context.c +952 -0
  208. data/pgpool2/pool_session_context.h +203 -0
  209. data/pgpool2/pool_shmem.c +185 -0
  210. data/pgpool2/pool_signal.c +158 -0
  211. data/pgpool2/pool_signal.h +61 -0
  212. data/pgpool2/pool_ssl.c +339 -0
  213. data/pgpool2/pool_stream.c +962 -0
  214. data/pgpool2/pool_stream.h +61 -0
  215. data/pgpool2/pool_system.c +659 -0
  216. data/pgpool2/pool_timestamp.c +1215 -0
  217. data/pgpool2/pool_timestamp.h +38 -0
  218. data/pgpool2/pool_type.h +171 -0
  219. data/pgpool2/pool_worker_child.c +384 -0
  220. data/pgpool2/ps_status.c +404 -0
  221. data/pgpool2/recovery.c +435 -0
  222. data/pgpool2/redhat/pgpool.conf.sample.patch +52 -0
  223. data/pgpool2/redhat/pgpool.init +201 -0
  224. data/pgpool2/redhat/pgpool.sysconfig +7 -0
  225. data/pgpool2/redhat/rpm_installer/basebackup-replication.sh +53 -0
  226. data/pgpool2/redhat/rpm_installer/basebackup-stream.sh +55 -0
  227. data/pgpool2/redhat/rpm_installer/config_for_script +17 -0
  228. data/pgpool2/redhat/rpm_installer/failover.sh +64 -0
  229. data/pgpool2/redhat/rpm_installer/getsources.sh +141 -0
  230. data/pgpool2/redhat/rpm_installer/install.sh +1363 -0
  231. data/pgpool2/redhat/rpm_installer/pgpool_recovery_pitr +47 -0
  232. data/pgpool2/redhat/rpm_installer/pgpool_remote_start +15 -0
  233. data/pgpool2/redhat/rpm_installer/recovery.conf +4 -0
  234. data/pgpool2/redhat/rpm_installer/uninstall.sh +57 -0
  235. data/pgpool2/sample/dist_def_pgbench.sql +73 -0
  236. data/pgpool2/sample/pgpool.pam +3 -0
  237. data/pgpool2/sample/pgpool_recovery +20 -0
  238. data/pgpool2/sample/pgpool_recovery_pitr +19 -0
  239. data/pgpool2/sample/pgpool_remote_start +13 -0
  240. data/pgpool2/sample/replicate_def_pgbench.sql +18 -0
  241. data/pgpool2/sql/insert_lock.sql +15 -0
  242. data/pgpool2/sql/pgpool-recovery/pgpool-recovery.c +280 -0
  243. data/pgpool2/sql/pgpool-recovery/pgpool-recovery.sql.in +19 -0
  244. data/pgpool2/sql/pgpool-recovery/pgpool_recovery--1.0.sql +24 -0
  245. data/pgpool2/sql/pgpool-recovery/pgpool_recovery.control +5 -0
  246. data/pgpool2/sql/pgpool-recovery/uninstall_pgpool-recovery.sql +3 -0
  247. data/pgpool2/sql/pgpool-regclass/pgpool-regclass.c +206 -0
  248. data/pgpool2/sql/pgpool-regclass/pgpool-regclass.sql.in +4 -0
  249. data/pgpool2/sql/pgpool-regclass/pgpool_regclass--1.0.sql +7 -0
  250. data/pgpool2/sql/pgpool-regclass/pgpool_regclass.control +5 -0
  251. data/pgpool2/sql/pgpool-regclass/uninstall_pgpool-regclass.sql +1 -0
  252. data/pgpool2/sql/system_db.sql +38 -0
  253. data/pgpool2/strlcpy.c +85 -0
  254. data/pgpool2/test/C/test_extended.c +98 -0
  255. data/pgpool2/test/jdbc/.cvsignore +2 -0
  256. data/pgpool2/test/jdbc/AutoCommitTest.java +45 -0
  257. data/pgpool2/test/jdbc/BatchTest.java +55 -0
  258. data/pgpool2/test/jdbc/ColumnTest.java +60 -0
  259. data/pgpool2/test/jdbc/CreateTempTableTest.java +48 -0
  260. data/pgpool2/test/jdbc/InsertTest.java +34 -0
  261. data/pgpool2/test/jdbc/LockTest.java +36 -0
  262. data/pgpool2/test/jdbc/PgpoolTest.java +75 -0
  263. data/pgpool2/test/jdbc/README.euc_jp +73 -0
  264. data/pgpool2/test/jdbc/RunTest.java +83 -0
  265. data/pgpool2/test/jdbc/SelectTest.java +37 -0
  266. data/pgpool2/test/jdbc/UpdateTest.java +32 -0
  267. data/pgpool2/test/jdbc/expected/CreateTempTable +1 -0
  268. data/pgpool2/test/jdbc/expected/autocommit +10 -0
  269. data/pgpool2/test/jdbc/expected/batch +1 -0
  270. data/pgpool2/test/jdbc/expected/column +100 -0
  271. data/pgpool2/test/jdbc/expected/insert +1 -0
  272. data/pgpool2/test/jdbc/expected/lock +100 -0
  273. data/pgpool2/test/jdbc/expected/select +2 -0
  274. data/pgpool2/test/jdbc/expected/update +1 -0
  275. data/pgpool2/test/jdbc/pgpool.properties +7 -0
  276. data/pgpool2/test/jdbc/prepare.sql +54 -0
  277. data/pgpool2/test/jdbc/run.sh +6 -0
  278. data/pgpool2/test/parser/.cvsignore +6 -0
  279. data/pgpool2/test/parser/README +32 -0
  280. data/pgpool2/test/parser/expected/copy.out +17 -0
  281. data/pgpool2/test/parser/expected/create.out +64 -0
  282. data/pgpool2/test/parser/expected/cursor.out +37 -0
  283. data/pgpool2/test/parser/expected/delete.out +10 -0
  284. data/pgpool2/test/parser/expected/drop.out +12 -0
  285. data/pgpool2/test/parser/expected/insert.out +13 -0
  286. data/pgpool2/test/parser/expected/misc.out +28 -0
  287. data/pgpool2/test/parser/expected/prepare.out +4 -0
  288. data/pgpool2/test/parser/expected/privileges.out +31 -0
  289. data/pgpool2/test/parser/expected/scanner.out +30 -0
  290. data/pgpool2/test/parser/expected/select.out +89 -0
  291. data/pgpool2/test/parser/expected/transaction.out +38 -0
  292. data/pgpool2/test/parser/expected/update.out +11 -0
  293. data/pgpool2/test/parser/expected/v84.out +37 -0
  294. data/pgpool2/test/parser/expected/v90.out +25 -0
  295. data/pgpool2/test/parser/expected/var.out +22 -0
  296. data/pgpool2/test/parser/input/alter.sql +2 -0
  297. data/pgpool2/test/parser/input/copy.sql +17 -0
  298. data/pgpool2/test/parser/input/create.sql +64 -0
  299. data/pgpool2/test/parser/input/cursor.sql +37 -0
  300. data/pgpool2/test/parser/input/delete.sql +10 -0
  301. data/pgpool2/test/parser/input/drop.sql +12 -0
  302. data/pgpool2/test/parser/input/insert.sql +13 -0
  303. data/pgpool2/test/parser/input/misc.sql +28 -0
  304. data/pgpool2/test/parser/input/prepare.sql +4 -0
  305. data/pgpool2/test/parser/input/privileges.sql +31 -0
  306. data/pgpool2/test/parser/input/scanner.sql +34 -0
  307. data/pgpool2/test/parser/input/select.sql +89 -0
  308. data/pgpool2/test/parser/input/transaction.sql +38 -0
  309. data/pgpool2/test/parser/input/update.sql +11 -0
  310. data/pgpool2/test/parser/input/v84.sql +37 -0
  311. data/pgpool2/test/parser/input/v90.sql +38 -0
  312. data/pgpool2/test/parser/input/var.sql +22 -0
  313. data/pgpool2/test/parser/main.c +96 -0
  314. data/pgpool2/test/parser/parse_schedule +16 -0
  315. data/pgpool2/test/parser/pool.h +13 -0
  316. data/pgpool2/test/parser/run-test +62 -0
  317. data/pgpool2/test/pdo-test/README.euc_jp +58 -0
  318. data/pgpool2/test/pdo-test/SQLlist/test1.sql +3 -0
  319. data/pgpool2/test/pdo-test/SQLlist/test2.sql +3 -0
  320. data/pgpool2/test/pdo-test/collections.inc +11 -0
  321. data/pgpool2/test/pdo-test/def.inc +7 -0
  322. data/pgpool2/test/pdo-test/log.txt +0 -0
  323. data/pgpool2/test/pdo-test/mod/database.inc +36 -0
  324. data/pgpool2/test/pdo-test/mod/def.inc +0 -0
  325. data/pgpool2/test/pdo-test/mod/errorhandler.inc +27 -0
  326. data/pgpool2/test/pdo-test/pdotest.php +11 -0
  327. data/pgpool2/test/pdo-test/regsql.inc +56 -0
  328. data/pgpool2/test/pgpool_setup +898 -0
  329. data/pgpool2/test/regression/README +39 -0
  330. data/pgpool2/test/regression/clean.sh +21 -0
  331. data/pgpool2/test/regression/libs.sh +16 -0
  332. data/pgpool2/test/regression/regress.sh +166 -0
  333. data/pgpool2/test/regression/tests/001.load_balance/test.sh +128 -0
  334. data/pgpool2/test/regression/tests/002.native_replication/PgTester.java +47 -0
  335. data/pgpool2/test/regression/tests/002.native_replication/create.sql +6 -0
  336. data/pgpool2/test/regression/tests/002.native_replication/test.sh +71 -0
  337. data/pgpool2/test/regression/tests/003.failover/expected.r +6 -0
  338. data/pgpool2/test/regression/tests/003.failover/expected.s +6 -0
  339. data/pgpool2/test/regression/tests/003.failover/test.sh +45 -0
  340. data/pgpool2/test/regression/tests/004.watchdog/master.conf +12 -0
  341. data/pgpool2/test/regression/tests/004.watchdog/standby.conf +19 -0
  342. data/pgpool2/test/regression/tests/004.watchdog/test.sh +52 -0
  343. data/pgpool2/test/regression/tests/050.bug58/test.sh +50 -0
  344. data/pgpool2/test/regression/tests/051.bug60/bug.sql +12 -0
  345. data/pgpool2/test/regression/tests/051.bug60/database-clean.sql +6 -0
  346. data/pgpool2/test/regression/tests/051.bug60/database-setup.sql +28 -0
  347. data/pgpool2/test/regression/tests/051.bug60/test.sh +79 -0
  348. data/pgpool2/test/regression/tests/052.do_query/test.sh +44 -0
  349. data/pgpool2/test/regression/tests/053.insert_lock_hangs/test.sh +81 -0
  350. data/pgpool2/test/regression/tests/054.postgres_fdw/test.sh +67 -0
  351. data/pgpool2/test/regression/tests/055.backend_all_down/test.sh +52 -0
  352. data/pgpool2/test/regression/tests/056.bug63/jdbctest2.java +66 -0
  353. data/pgpool2/test/regression/tests/056.bug63/test.sh +47 -0
  354. data/pgpool2/test/regression/tests/057.bug61/test.sh +40 -0
  355. data/pgpool2/test/regression/tests/058.bug68/jdbctest3.java +45 -0
  356. data/pgpool2/test/regression/tests/058.bug68/test.sh +47 -0
  357. data/pgpool2/test/timestamp/expected/insert.out +16 -0
  358. data/pgpool2/test/timestamp/expected/misc.out +3 -0
  359. data/pgpool2/test/timestamp/expected/update.out +6 -0
  360. data/pgpool2/test/timestamp/input/insert.sql +16 -0
  361. data/pgpool2/test/timestamp/input/misc.sql +3 -0
  362. data/pgpool2/test/timestamp/input/update.sql +6 -0
  363. data/pgpool2/test/timestamp/main.c +129 -0
  364. data/pgpool2/test/timestamp/parse_schedule +3 -0
  365. data/pgpool2/test/timestamp/run-test +69 -0
  366. data/pgpool2/version.h +1 -0
  367. data/pgpool2/watchdog/Makefile.am +17 -0
  368. data/pgpool2/watchdog/Makefile.in +505 -0
  369. data/pgpool2/watchdog/test/stab.c +266 -0
  370. data/pgpool2/watchdog/test/test.c +85 -0
  371. data/pgpool2/watchdog/test/wd_child_t.c +87 -0
  372. data/pgpool2/watchdog/test/wd_lifecheck_t.c +87 -0
  373. data/pgpool2/watchdog/test/wd_packet_t.c +87 -0
  374. data/pgpool2/watchdog/test/wd_ping_t.c +20 -0
  375. data/pgpool2/watchdog/watchdog.c +408 -0
  376. data/pgpool2/watchdog/watchdog.h +209 -0
  377. data/pgpool2/watchdog/wd_child.c +444 -0
  378. data/pgpool2/watchdog/wd_ext.h +123 -0
  379. data/pgpool2/watchdog/wd_heartbeat.c +577 -0
  380. data/pgpool2/watchdog/wd_if.c +216 -0
  381. data/pgpool2/watchdog/wd_init.c +126 -0
  382. data/pgpool2/watchdog/wd_interlock.c +347 -0
  383. data/pgpool2/watchdog/wd_lifecheck.c +512 -0
  384. data/pgpool2/watchdog/wd_list.c +429 -0
  385. data/pgpool2/watchdog/wd_packet.c +1159 -0
  386. data/pgpool2/watchdog/wd_ping.c +330 -0
  387. data/pgpool2/ylwrap +223 -0
  388. data/pgsql/presto_client.py +346 -0
  389. data/pgsql/prestogres.py +156 -0
  390. data/pgsql/setup_functions.sql +21 -0
  391. data/pgsql/setup_language.sql +3 -0
  392. data/prestogres.gemspec +23 -0
  393. metadata +496 -0
data/pgpool2/child.c ADDED
@@ -0,0 +1,2097 @@
1
+ /* -*-pgsql-c-*- */
2
+ /*
3
+ * $Header$
4
+ *
5
+ * pgpool: a language independent connection pool server for PostgreSQL
6
+ * written by Tatsuo Ishii
7
+ *
8
+ * Copyright (c) 2003-2013 PgPool Global Development Group
9
+ *
10
+ * Permission to use, copy, modify, and distribute this software and
11
+ * its documentation for any purpose and without fee is hereby
12
+ * granted, provided that the above copyright notice appear in all
13
+ * copies and that both that copyright notice and this permission
14
+ * notice appear in supporting documentation, and that the name of the
15
+ * author not be used in advertising or publicity pertaining to
16
+ * distribution of the software without specific, written prior
17
+ * permission. The author makes no representations about the
18
+ * suitability of this software for any purpose. It is provided "as
19
+ * is" without express or implied warranty.
20
+ *
21
+ * child.c: child process main
22
+ *
23
+ */
24
+ #include "config.h"
25
+
26
+ #include <sys/types.h>
27
+ #include <sys/socket.h>
28
+ #include <netinet/in.h>
29
+ #include <sys/un.h>
30
+ #include <arpa/inet.h>
31
+ #include <netdb.h>
32
+ #ifdef HAVE_NETINET_TCP_H
33
+ #include <netinet/tcp.h>
34
+ #endif
35
+ #ifdef HAVE_SYS_SELECT_H
36
+ #include <sys/select.h>
37
+ #endif
38
+
39
+ #include <signal.h>
40
+
41
+ #include <stdio.h>
42
+ #include <errno.h>
43
+ #include <string.h>
44
+ #include <unistd.h>
45
+ #include <stdlib.h>
46
+ #include <sys/time.h>
47
+
48
+ #ifdef HAVE_CRYPT_H
49
+ #include <crypt.h>
50
+ #endif
51
+
52
+ #include "pool.h"
53
+ #include "pool_process_context.h"
54
+ #include "pool_session_context.h"
55
+ #include "pool_config.h"
56
+ #include "pool_ip.h"
57
+ #include "md5.h"
58
+ #include "pool_stream.h"
59
+ #include "pool_passwd.h"
60
+
61
+ static POOL_CONNECTION *do_accept(int unix_fd, int inet_fd, struct timeval *timeout);
62
+ static StartupPacket *read_startup_packet(POOL_CONNECTION *cp);
63
+ static POOL_CONNECTION_POOL *connect_backend(StartupPacket *sp, POOL_CONNECTION *frontend);
64
+ static RETSIGTYPE die(int sig);
65
+ static RETSIGTYPE close_idle_connection(int sig);
66
+ static RETSIGTYPE wakeup_handler(int sig);
67
+ static RETSIGTYPE reload_config_handler(int sig);
68
+ static RETSIGTYPE authentication_timeout(int sig);
69
+ static int send_params(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend);
70
+ static void send_frontend_exits(void);
71
+ static int s_do_auth(POOL_CONNECTION_POOL_SLOT *cp, char *password);
72
+ static void connection_count_up(void);
73
+ static void connection_count_down(void);
74
+ static void init_system_db_connection(void);
75
+ static bool connect_using_existing_connection(POOL_CONNECTION *frontend,
76
+ POOL_CONNECTION_POOL *backend,
77
+ StartupPacket *sp);
78
+ static void free_persisten_db_connection_memory(POOL_CONNECTION_POOL_SLOT *cp);
79
+
80
+ /*
81
+ * non 0 means SIGTERM(smart shutdown) or SIGINT(fast shutdown) has arrived
82
+ */
83
+ volatile sig_atomic_t exit_request = 0;
84
+
85
+ static int idle; /* non 0 means this child is in idle state */
86
+ static int accepted = 0;
87
+
88
+ extern int myargc;
89
+ extern char **myargv;
90
+
91
+ char remote_ps_data[NI_MAXHOST]; /* used for set_ps_display */
92
+
93
+ volatile sig_atomic_t got_sighup = 0;
94
+
95
+ char remote_host[NI_MAXHOST]; /* client host */
96
+ char remote_port[NI_MAXSERV]; /* client port */
97
+
98
+ /*
99
+ * child main loop
100
+ */
101
+ void do_child(int unix_fd, int inet_fd)
102
+ {
103
+ POOL_CONNECTION *frontend;
104
+ POOL_CONNECTION_POOL *backend;
105
+ struct timeval now;
106
+ struct timezone tz;
107
+ struct timeval timeout;
108
+ static int connected; /* non 0 if has been accepted connections from frontend */
109
+ int connections_count = 0; /* used if child_max_connections > 0 */
110
+ int found;
111
+ char psbuf[NI_MAXHOST + 128];
112
+
113
+ pool_debug("I am %d", getpid());
114
+
115
+ /* Identify myself via ps */
116
+ init_ps_display("", "", "", "");
117
+
118
+ /* set up signal handlers */
119
+ signal(SIGALRM, SIG_DFL);
120
+ signal(SIGTERM, die);
121
+ signal(SIGINT, die);
122
+ signal(SIGHUP, reload_config_handler);
123
+ signal(SIGQUIT, die);
124
+ signal(SIGCHLD, SIG_DFL);
125
+ signal(SIGUSR1, close_idle_connection);
126
+ signal(SIGUSR2, wakeup_handler);
127
+ signal(SIGPIPE, SIG_IGN);
128
+
129
+ #ifdef NONE_BLOCK
130
+ /* set listen fds to none-blocking */
131
+ pool_set_nonblock(unix_fd);
132
+ if (inet_fd)
133
+ {
134
+ pool_set_nonblock(inet_fd);
135
+ }
136
+ #endif
137
+
138
+ /* Initialize my backend status */
139
+ pool_initialize_private_backend_status();
140
+
141
+ /* Initialize per process context */
142
+ pool_init_process_context();
143
+
144
+ /* initialize random seed */
145
+ gettimeofday(&now, &tz);
146
+ #if defined(sun) || defined(__sun)
147
+ srand((unsigned int) now.tv_usec);
148
+ #else
149
+ srandom((unsigned int) now.tv_usec);
150
+ #endif
151
+
152
+ /* initialize system db connection */
153
+ init_system_db_connection();
154
+
155
+ /* initialize connection pool */
156
+ if (pool_init_cp())
157
+ {
158
+ child_exit(1);
159
+ }
160
+
161
+ /*
162
+ * Open pool_passwd in child process. This is necessary to avoid the
163
+ * file descriptor race condition reported in [pgpool-general: 1141].
164
+ */
165
+ if (strcmp("", pool_config->pool_passwd))
166
+ {
167
+ pool_reopen_passwd_file();
168
+ }
169
+
170
+ timeout.tv_sec = pool_config->child_life_time;
171
+ timeout.tv_usec = 0;
172
+
173
+ for (;;)
174
+ {
175
+ StartupPacket *sp;
176
+
177
+ idle = 1;
178
+
179
+ /* pgpool stop request already sent? */
180
+ check_stop_request();
181
+
182
+ /* Check if restart request is set because of failback event
183
+ * happend. If so, exit myself with exit code 1 to be
184
+ * restarted by pgpool parent.
185
+ */
186
+ if (pool_get_my_process_info()->need_to_restart)
187
+ {
188
+ pool_log("do_child: failback event found. restart myself.");
189
+ pool_get_my_process_info()->need_to_restart = 0;
190
+ child_exit(1);
191
+ }
192
+
193
+ accepted = 0;
194
+
195
+ /* perform accept() */
196
+ frontend = do_accept(unix_fd, inet_fd, &timeout);
197
+
198
+ if (frontend == NULL) /* connection request from frontend timed out */
199
+ {
200
+ /* check select() timeout */
201
+ if (connected && pool_config->child_life_time > 0 &&
202
+ timeout.tv_sec == 0 && timeout.tv_usec == 0)
203
+ {
204
+ pool_debug("child life %d seconds expired", pool_config->child_life_time);
205
+ /*
206
+ * Doesn't need to call this. child_exit() calls it.
207
+ * send_frontend_exits();
208
+ */
209
+ child_exit(2);
210
+ }
211
+ continue;
212
+ }
213
+
214
+ /* set frontend fd to blocking */
215
+ pool_unset_nonblock(frontend->fd);
216
+
217
+ /* reset busy flag */
218
+ idle = 0;
219
+
220
+ /* check backend timer is expired */
221
+ if (backend_timer_expired)
222
+ {
223
+ pool_backend_timer();
224
+ backend_timer_expired = 0;
225
+ }
226
+
227
+ /* read the startup packet */
228
+ retry_startup:
229
+ sp = read_startup_packet(frontend);
230
+ if (sp == NULL)
231
+ {
232
+ /* failed to read the startup packet. return to the accept() loop */
233
+ pool_close(frontend);
234
+ connection_count_down();
235
+ continue;
236
+ }
237
+
238
+ /* cancel request? */
239
+ if (sp->major == 1234 && sp->minor == 5678)
240
+ {
241
+ cancel_request((CancelPacket *)sp->startup_packet);
242
+
243
+ pool_close(frontend);
244
+ pool_free_startup_packet(sp);
245
+ connection_count_down();
246
+ continue;
247
+ }
248
+
249
+ /* SSL? */
250
+ if (sp->major == 1234 && sp->minor == 5679 && !frontend->ssl_active)
251
+ {
252
+ pool_debug("SSLRequest from client");
253
+ pool_ssl_negotiate_serverclient(frontend);
254
+ pool_free_startup_packet(sp);
255
+ goto retry_startup;
256
+ }
257
+
258
+ if (pool_config->enable_pool_hba)
259
+ {
260
+ /*
261
+ * do client authentication.
262
+ * Note that ClientAuthentication does not return if frontend
263
+ * was rejected; it simply terminates this process.
264
+ */
265
+ frontend->protoVersion = sp->major;
266
+ frontend->database = strdup(sp->database);
267
+ if (frontend->database == NULL)
268
+ {
269
+ pool_error("do_child: strdup failed: %s\n", strerror(errno));
270
+ child_exit(1);
271
+ }
272
+ frontend->username = strdup(sp->user);
273
+ if (frontend->username == NULL)
274
+ {
275
+ pool_error("do_child: strdup failed: %s\n", strerror(errno));
276
+ child_exit(1);
277
+ }
278
+ ClientAuthentication(frontend);
279
+ }
280
+
281
+ /* this should run after ClientAuthentication */
282
+ pool_prestogres_init_session(frontend);
283
+
284
+ /*
285
+ * Ok, negotiation with frontend has been done. Let's go to the
286
+ * next step. Connect to backend if there's no existing
287
+ * connection which can be reused by this frontend.
288
+ * Authentication is also done in this step.
289
+ */
290
+
291
+ /* Check if restart request is set because of failback event
292
+ * happend. If so, close idle connections to backend and make
293
+ * a new copy of backend status.
294
+ */
295
+ if (pool_get_my_process_info()->need_to_restart)
296
+ {
297
+ pool_log("do_child: failback event found. discard existing connections");
298
+ pool_get_my_process_info()->need_to_restart = 0;
299
+ close_idle_connection(0);
300
+ pool_initialize_private_backend_status();
301
+ }
302
+
303
+ /*
304
+ * if there's no connection associated with user and database,
305
+ * we need to connect to the backend and send the startup packet.
306
+ */
307
+
308
+ /* look for existing connection */
309
+ found = 0;
310
+ backend = pool_get_cp(sp->user, sp->database, sp->major, 1);
311
+
312
+ if (backend != NULL)
313
+ {
314
+ found = 1;
315
+
316
+ /* existing connection associated with same user/database/major found.
317
+ * however we should make sure that the startup packet contents are identical.
318
+ * OPTION data and others might be different.
319
+ */
320
+ if (sp->len != MASTER_CONNECTION(backend)->sp->len)
321
+ {
322
+ pool_debug("do_child: connection exists but startup packet length is not identical");
323
+ found = 0;
324
+ }
325
+ else if(memcmp(sp->startup_packet, MASTER_CONNECTION(backend)->sp->startup_packet, sp->len) != 0)
326
+ {
327
+ pool_debug("do_child: connection exists but startup packet contents is not identical");
328
+ found = 0;
329
+ }
330
+
331
+ if (found == 0)
332
+ {
333
+ /* we need to discard existing connection since startup packet is different */
334
+ pool_discard_cp(sp->user, sp->database, sp->major);
335
+ backend = NULL;
336
+ }
337
+ }
338
+
339
+ if (backend == NULL)
340
+ {
341
+ /* create a new connection to backend */
342
+ if ((backend = connect_backend(sp, frontend)) == NULL)
343
+ {
344
+ connection_count_down();
345
+ continue;
346
+ }
347
+ }
348
+
349
+ else
350
+ {
351
+ /* reuse existing connection */
352
+ if (!connect_using_existing_connection(frontend, backend, sp))
353
+ continue;
354
+ }
355
+
356
+ connected = 1;
357
+
358
+ /* show ps status */
359
+ sp = MASTER_CONNECTION(backend)->sp;
360
+ snprintf(psbuf, sizeof(psbuf), "%s %s %s idle",
361
+ sp->user, sp->database, remote_ps_data);
362
+ set_ps_display(psbuf, false);
363
+
364
+ /*
365
+ * Initialize per session context
366
+ */
367
+ pool_init_session_context(frontend, backend);
368
+
369
+ /* Mark this connection pool is connected from frontend */
370
+ pool_coninfo_set_frontend_connected(pool_get_process_context()->proc_id, pool_pool_index());
371
+
372
+ /* query process loop */
373
+ for (;;)
374
+ {
375
+ POOL_STATUS status;
376
+
377
+ status = pool_process_query(frontend, backend, 0);
378
+
379
+ sp = MASTER_CONNECTION(backend)->sp;
380
+
381
+ switch (status)
382
+ {
383
+ /* client exits */
384
+ case POOL_END:
385
+ /*
386
+ * do not cache connection if:
387
+ * pool_config->connection_cahe == 0 or
388
+ * database name is template0, template1, postgres or regression
389
+ */
390
+ if (pool_config->connection_cache == 0 ||
391
+ !strcmp(sp->database, "template0") ||
392
+ !strcmp(sp->database, "template1") ||
393
+ !strcmp(sp->database, "postgres") ||
394
+ !strcmp(sp->database, "regression"))
395
+ {
396
+ reset_connection();
397
+ pool_close(frontend);
398
+ pool_send_frontend_exits(backend);
399
+ pool_discard_cp(sp->user, sp->database, sp->major);
400
+ }
401
+ else
402
+ {
403
+ POOL_STATUS status1;
404
+
405
+ /* send reset request to backend */
406
+ status1 = pool_process_query(frontend, backend, 1);
407
+ pool_close(frontend);
408
+
409
+ /* if we detect errors on resetting connection, we need to discard
410
+ * this connection since it might be in unknown status
411
+ */
412
+ if (status1 != POOL_CONTINUE)
413
+ {
414
+ pool_debug("error in resetting connections. discarding connection pools...");
415
+ pool_send_frontend_exits(backend);
416
+ pool_discard_cp(sp->user, sp->database, sp->major);
417
+ }
418
+ else
419
+ pool_connection_pool_timer(backend);
420
+ }
421
+ break;
422
+
423
+ /* error occurred. discard backend connection pool
424
+ and disconnect connection to the frontend */
425
+ case POOL_ERROR:
426
+ pool_log("do_child: exits with status 1 due to error");
427
+ child_exit(1);
428
+ break;
429
+
430
+ /* fatal error occurred. just exit myself... */
431
+ case POOL_FATAL:
432
+ notice_backend_error(1);
433
+ child_exit(1);
434
+ break;
435
+
436
+ /* not implemented yet */
437
+ case POOL_IDLE:
438
+ do_accept(unix_fd, inet_fd, &timeout);
439
+ pool_debug("accept while idle");
440
+ break;
441
+
442
+ default:
443
+ break;
444
+ }
445
+
446
+ if (status != POOL_CONTINUE)
447
+ break;
448
+ }
449
+
450
+ /* Destroy session context */
451
+ pool_session_context_destroy();
452
+
453
+ /* Mark this connection pool is not connected from frontend */
454
+ pool_coninfo_unset_frontend_connected(pool_get_process_context()->proc_id, pool_pool_index());
455
+
456
+ accepted = 0;
457
+ connection_count_down();
458
+
459
+ timeout.tv_sec = pool_config->child_life_time;
460
+ timeout.tv_usec = 0;
461
+
462
+ /* increment queries counter if necessary */
463
+ if ( pool_config->child_max_connections > 0 )
464
+ connections_count++;
465
+
466
+ /* check if maximum connections count for this child reached */
467
+ if ( ( pool_config->child_max_connections > 0 ) &&
468
+ ( connections_count >= pool_config->child_max_connections ) )
469
+ {
470
+ pool_log("child exiting, %d connections reached", pool_config->child_max_connections);
471
+ send_frontend_exits();
472
+ child_exit(2);
473
+ }
474
+ }
475
+ child_exit(0);
476
+ }
477
+
478
+ /* -------------------------------------------------------------------
479
+ * private functions
480
+ * -------------------------------------------------------------------
481
+ */
482
+
483
+ /*
484
+ * perform accept() and return new fd
485
+ */
486
+ static POOL_CONNECTION *do_accept(int unix_fd, int inet_fd, struct timeval *timeout)
487
+ {
488
+ fd_set readmask;
489
+ int fds;
490
+ int save_errno;
491
+
492
+ SockAddr saddr;
493
+ int fd = 0;
494
+ int afd;
495
+ int inet = 0;
496
+ POOL_CONNECTION *cp;
497
+ #ifdef ACCEPT_PERFORMANCE
498
+ struct timeval now1, now2;
499
+ static long atime;
500
+ static int cnt;
501
+ #endif
502
+ struct timeval *timeoutval;
503
+ struct timeval tv1, tv2, tmback = {0, 0};
504
+
505
+ set_ps_display("wait for connection request", false);
506
+
507
+ /* Destroy session context for just in case... */
508
+ pool_session_context_destroy();
509
+
510
+ FD_ZERO(&readmask);
511
+ FD_SET(unix_fd, &readmask);
512
+ if (inet_fd)
513
+ FD_SET(inet_fd, &readmask);
514
+
515
+ if (timeout->tv_sec == 0 && timeout->tv_usec == 0)
516
+ timeoutval = NULL;
517
+ else
518
+ {
519
+ timeoutval = timeout;
520
+ tmback.tv_sec = timeout->tv_sec;
521
+ tmback.tv_usec = timeout->tv_usec;
522
+ gettimeofday(&tv1, NULL);
523
+
524
+ #ifdef DEBUG
525
+ pool_log("before select = {%d, %d}", timeoutval->tv_sec, timeoutval->tv_usec);
526
+ pool_log("g:before select = {%d, %d}", tv1.tv_sec, tv1.tv_usec);
527
+ #endif
528
+ }
529
+
530
+ fds = select(Max(unix_fd, inet_fd)+1, &readmask, NULL, NULL, timeoutval);
531
+
532
+ save_errno = errno;
533
+ /* check backend timer is expired */
534
+ if (backend_timer_expired)
535
+ {
536
+ pool_backend_timer();
537
+ backend_timer_expired = 0;
538
+ }
539
+
540
+ /*
541
+ * following code fragment computes remaining timeout val in a
542
+ * portable way. Linux does this automatically but other platforms do not.
543
+ */
544
+ if (timeoutval)
545
+ {
546
+ gettimeofday(&tv2, NULL);
547
+
548
+ tmback.tv_usec -= tv2.tv_usec - tv1.tv_usec;
549
+ tmback.tv_sec -= tv2.tv_sec - tv1.tv_sec;
550
+
551
+ if (tmback.tv_usec < 0)
552
+ {
553
+ tmback.tv_sec--;
554
+ if (tmback.tv_sec < 0)
555
+ {
556
+ timeout->tv_sec = 0;
557
+ timeout->tv_usec = 0;
558
+ }
559
+ else
560
+ {
561
+ tmback.tv_usec += 1000000;
562
+ timeout->tv_sec = tmback.tv_sec;
563
+ timeout->tv_usec = tmback.tv_usec;
564
+ }
565
+ }
566
+ #ifdef DEBUG
567
+ pool_log("g:after select = {%d, %d}", tv2.tv_sec, tv2.tv_usec);
568
+ pool_log("after select = {%d, %d}", timeout->tv_sec, timeout->tv_usec);
569
+ #endif
570
+ }
571
+
572
+ errno = save_errno;
573
+
574
+ if (fds == -1)
575
+ {
576
+ if (errno == EAGAIN || errno == EINTR)
577
+ return NULL;
578
+
579
+ pool_error("select() failed. reason %s", strerror(errno));
580
+ return NULL;
581
+ }
582
+
583
+ /* timeout */
584
+ if (fds == 0)
585
+ {
586
+ return NULL;
587
+ }
588
+
589
+ if (FD_ISSET(unix_fd, &readmask))
590
+ {
591
+ fd = unix_fd;
592
+ }
593
+
594
+ if (FD_ISSET(inet_fd, &readmask))
595
+ {
596
+ fd = inet_fd;
597
+ inet++;
598
+ }
599
+
600
+ /*
601
+ * Note that some SysV systems do not work here. For those
602
+ * systems, we need some locking mechanism for the fd.
603
+ */
604
+ memset(&saddr, 0, sizeof(saddr));
605
+ saddr.salen = sizeof(saddr.addr);
606
+
607
+ #ifdef ACCEPT_PERFORMANCE
608
+ gettimeofday(&now1,0);
609
+ #endif
610
+
611
+ retry_accept:
612
+
613
+ /* wait if recovery is started */
614
+ while (*InRecovery == 1)
615
+ {
616
+ pause();
617
+ }
618
+
619
+ afd = accept(fd, (struct sockaddr *)&saddr.addr, &saddr.salen);
620
+
621
+ save_errno = errno;
622
+ /* check backend timer is expired */
623
+ if (backend_timer_expired)
624
+ {
625
+ pool_backend_timer();
626
+ backend_timer_expired = 0;
627
+ }
628
+ errno = save_errno;
629
+ if (afd < 0)
630
+ {
631
+ if (errno == EINTR && *InRecovery)
632
+ goto retry_accept;
633
+
634
+ /*
635
+ * "Resource temporarily unavailable" (EAGAIN or EWOULDBLOCK)
636
+ * can be silently ignored. And EINTR can be ignored.
637
+ */
638
+ if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
639
+ pool_error("accept() failed. reason: %s", strerror(errno));
640
+ return NULL;
641
+ }
642
+ #ifdef ACCEPT_PERFORMANCE
643
+ gettimeofday(&now2,0);
644
+ atime += (now2.tv_sec - now1.tv_sec)*1000000 + (now2.tv_usec - now1.tv_usec);
645
+ cnt++;
646
+ if (cnt % 100 == 0)
647
+ {
648
+ pool_log("cnt: %d atime: %ld", cnt, atime);
649
+ }
650
+ #endif
651
+
652
+ /* reload config file */
653
+ if (got_sighup)
654
+ {
655
+ pool_get_config(get_config_file_name(), RELOAD_CONFIG);
656
+ if (pool_config->enable_pool_hba)
657
+ {
658
+ load_hba(get_hba_file_name());
659
+ if (strcmp("", pool_config->pool_passwd))
660
+ pool_reopen_passwd_file();
661
+ }
662
+ if (pool_config->parallel_mode)
663
+ pool_memset_system_db_info(system_db_info->info);
664
+ got_sighup = 0;
665
+ }
666
+
667
+ connection_count_up();
668
+ accepted = 1;
669
+
670
+ if (pool_config->parallel_mode)
671
+ {
672
+ /*
673
+ * do not accept new connection if any of DB node or SystemDB is down when operating in
674
+ * parallel mode
675
+ */
676
+ int i;
677
+
678
+ for (i=0;i<NUM_BACKENDS;i++)
679
+ {
680
+ if (BACKEND_INFO(i).backend_status == CON_DOWN || SYSDB_STATUS == CON_DOWN)
681
+ {
682
+ StartupPacket *sp;
683
+ char *msg = "pgpool is not available in parallel query mode";
684
+
685
+ if (SYSDB_STATUS == CON_DOWN)
686
+ pool_log("Cannot accept() new connection. SystemDB is down");
687
+ else
688
+ pool_log("Cannot accept() new connection. %d th backend is down", i);
689
+
690
+ if ((cp = pool_open(afd)) == NULL)
691
+ {
692
+ close(afd);
693
+ child_exit(1);
694
+ }
695
+
696
+ sp = read_startup_packet(cp);
697
+ if (sp == NULL)
698
+ {
699
+ /* failed to read the startup packet. return to the accept() loop */
700
+ pool_close(cp);
701
+ child_exit(1);
702
+ }
703
+
704
+ pool_debug("do_accept: send error message to frontend");
705
+
706
+ if (sp->major == PROTO_MAJOR_V3)
707
+ {
708
+ char buf[256];
709
+
710
+ if (SYSDB_STATUS == CON_DOWN)
711
+ snprintf(buf, sizeof(buf), "SystemDB is down");
712
+ else
713
+ snprintf(buf, sizeof(buf), "%d th backend is down", i);
714
+
715
+ pool_send_error_message(cp, sp->major, "08S01",
716
+ msg,
717
+ buf,
718
+ ((SYSDB_STATUS == CON_DOWN) ? "repair the SystemDB and restart pgpool"
719
+ : "repair the backend and restart pgpool"),
720
+ __FILE__,
721
+ __LINE__);
722
+ }
723
+ else
724
+ {
725
+ pool_send_error_message(cp, sp->major,
726
+ 0,
727
+ msg,
728
+ "",
729
+ "",
730
+ "",
731
+ 0);
732
+ }
733
+ pool_close(cp);
734
+ child_exit(1);
735
+ }
736
+ }
737
+ }
738
+ else
739
+ {
740
+ /*
741
+ * do not accept new connection if all DB nodes are down when operating in
742
+ * non parallel mode
743
+ */
744
+ int i;
745
+ int found = 0;
746
+
747
+ for (i=0;i<NUM_BACKENDS;i++)
748
+ {
749
+ if (VALID_BACKEND(i))
750
+ {
751
+ found = 1;
752
+ }
753
+ }
754
+ if (found == 0)
755
+ {
756
+ pool_log("Cannot accept() new connection. all backends are down");
757
+ child_exit(1);
758
+ }
759
+ }
760
+
761
+ pool_debug("I am %d accept fd %d", getpid(), afd);
762
+
763
+ pool_getnameinfo_all(&saddr, remote_host, remote_port);
764
+ snprintf(remote_ps_data, sizeof(remote_ps_data),
765
+ remote_port[0] == '\0' ? "%s" : "%s(%s)",
766
+ remote_host, remote_port);
767
+
768
+ set_ps_display("accept connection", false);
769
+
770
+ /* log who is connecting */
771
+ if (pool_config->log_connections)
772
+ {
773
+ pool_log("connection received: host=%s%s%s",
774
+ remote_host, remote_port[0] ? " port=" : "", remote_port);
775
+ }
776
+
777
+ /* set NODELAY and KEEPALIVE options if INET connection */
778
+ if (inet)
779
+ {
780
+ int on = 1;
781
+
782
+ if (setsockopt(afd, IPPROTO_TCP, TCP_NODELAY,
783
+ (char *) &on,
784
+ sizeof(on)) < 0)
785
+ {
786
+ pool_error("do_accept: setsockopt() failed: %s", strerror(errno));
787
+ close(afd);
788
+ return NULL;
789
+ }
790
+ if (setsockopt(afd, SOL_SOCKET, SO_KEEPALIVE,
791
+ (char *) &on,
792
+ sizeof(on)) < 0)
793
+ {
794
+ pool_error("do_accept: setsockopt() failed: %s", strerror(errno));
795
+ close(afd);
796
+ return NULL;
797
+ }
798
+ }
799
+
800
+ if ((cp = pool_open(afd)) == NULL)
801
+ {
802
+ close(afd);
803
+ return NULL;
804
+ }
805
+
806
+ /* save ip address for hba */
807
+ memcpy(&cp->raddr, &saddr, sizeof(SockAddr));
808
+ if (cp->raddr.addr.ss_family == 0)
809
+ cp->raddr.addr.ss_family = AF_UNIX;
810
+
811
+ return cp;
812
+ }
813
+
814
+ /*
815
+ * Read startup packet
816
+ *
817
+ * Read the startup packet and parse the contents.
818
+ */
819
+ static StartupPacket *read_startup_packet(POOL_CONNECTION *cp)
820
+ {
821
+ StartupPacket *sp;
822
+ StartupPacket_v2 *sp2;
823
+ int protov;
824
+ int len;
825
+ char *p;
826
+
827
+ sp = (StartupPacket *)calloc(sizeof(*sp), 1);
828
+ if (!sp)
829
+ {
830
+ pool_error("read_startup_packet: out of memory");
831
+ return NULL;
832
+ }
833
+
834
+ if (pool_config->authentication_timeout > 0)
835
+ {
836
+ pool_signal(SIGALRM, authentication_timeout);
837
+ alarm(pool_config->authentication_timeout);
838
+ }
839
+
840
+ /* read startup packet length */
841
+ if (pool_read(cp, &len, sizeof(len)))
842
+ {
843
+ pool_error("read_startup_packet: incorrect packet length (%d)", len);
844
+ pool_free_startup_packet(sp);
845
+ alarm(0);
846
+ pool_signal(SIGALRM, SIG_IGN);
847
+ return NULL;
848
+ }
849
+ len = ntohl(len);
850
+ len -= sizeof(len);
851
+
852
+ if (len <= 0 || len >= MAX_STARTUP_PACKET_LENGTH)
853
+ {
854
+ pool_error("read_startup_packet: incorrect packet length (%d)", len);
855
+ pool_free_startup_packet(sp);
856
+ alarm(0);
857
+ pool_signal(SIGALRM, SIG_IGN);
858
+ return NULL;
859
+ }
860
+
861
+ sp->startup_packet = calloc(len, 1);
862
+ if (!sp->startup_packet)
863
+ {
864
+ pool_error("read_startup_packet: out of memory");
865
+ pool_free_startup_packet(sp);
866
+ alarm(0);
867
+ pool_signal(SIGALRM, SIG_IGN);
868
+ return NULL;
869
+ }
870
+
871
+ /* read startup packet */
872
+ if (pool_read(cp, sp->startup_packet, len))
873
+ {
874
+ pool_free_startup_packet(sp);
875
+ alarm(0);
876
+ pool_signal(SIGALRM, SIG_IGN);
877
+ return NULL;
878
+ }
879
+
880
+ sp->len = len;
881
+ memcpy(&protov, sp->startup_packet, sizeof(protov));
882
+ sp->major = ntohl(protov)>>16;
883
+ sp->minor = ntohl(protov) & 0x0000ffff;
884
+ p = sp->startup_packet;
885
+
886
+ switch(sp->major)
887
+ {
888
+ case PROTO_MAJOR_V2: /* V2 */
889
+ sp2 = (StartupPacket_v2 *)(sp->startup_packet);
890
+
891
+ sp->database = calloc(SM_DATABASE+1, 1);
892
+ if (!sp->database)
893
+ {
894
+ pool_error("read_startup_packet: out of memory");
895
+ pool_free_startup_packet(sp);
896
+ alarm(0);
897
+ pool_signal(SIGALRM, SIG_IGN);
898
+ return NULL;
899
+ }
900
+ strncpy(sp->database, sp2->database, SM_DATABASE);
901
+
902
+ sp->user = calloc(SM_USER+1, 1);
903
+ if (!sp->user)
904
+ {
905
+ pool_error("read_startup_packet: out of memory");
906
+ pool_free_startup_packet(sp);
907
+ alarm(0);
908
+ pool_signal(SIGALRM, SIG_IGN);
909
+ return NULL;
910
+ }
911
+ strncpy(sp->user, sp2->user, SM_USER);
912
+
913
+ break;
914
+
915
+ case PROTO_MAJOR_V3: /* V3 */
916
+ p += sizeof(int); /* skip protocol version info */
917
+
918
+ while(*p)
919
+ {
920
+ if (!strcmp("user", p))
921
+ {
922
+ p += (strlen(p) + 1);
923
+ sp->user = strdup(p);
924
+ if (!sp->user)
925
+ {
926
+ pool_error("read_startup_packet: out of memory");
927
+ pool_free_startup_packet(sp);
928
+ alarm(0);
929
+ pool_signal(SIGALRM, SIG_IGN);
930
+ return NULL;
931
+ }
932
+ }
933
+ else if (!strcmp("database", p))
934
+ {
935
+ p += (strlen(p) + 1);
936
+ sp->database = strdup(p);
937
+ if (!sp->database)
938
+ {
939
+ pool_error("read_startup_packet: out of memory");
940
+ pool_free_startup_packet(sp);
941
+ alarm(0);
942
+ pool_signal(SIGALRM, SIG_IGN);
943
+ return NULL;
944
+ }
945
+ }
946
+
947
+ /*
948
+ * From 9.0, the start up packet may include
949
+ * application name. After receiving such that packet,
950
+ * backend sends parameter status of application_name.
951
+ * Upon reusing connection to backend, we need to
952
+ * emulate this behavior of backend. So we remember
953
+ * this and send parameter status packet to frontend
954
+ * instead of backend in
955
+ * connect_using_existing_connection().
956
+ */
957
+ else if (!strcmp("application_name", p))
958
+ {
959
+ p += (strlen(p) + 1);
960
+ sp->application_name = p;
961
+ pool_debug("read_startup_packet: application_name: %s", p);
962
+ }
963
+
964
+ p += (strlen(p) + 1);
965
+ }
966
+ break;
967
+
968
+ case 1234: /* cancel or SSL request */
969
+ /* set dummy database, user info */
970
+ sp->database = calloc(1, 1);
971
+ if (!sp->database)
972
+ {
973
+ pool_error("read_startup_packet: out of memory");
974
+ pool_free_startup_packet(sp);
975
+ alarm(0);
976
+ pool_signal(SIGALRM, SIG_IGN);
977
+ return NULL;
978
+ }
979
+ sp->user = calloc(1, 1);
980
+ if (!sp->user)
981
+ {
982
+ pool_error("read_startup_packet: out of memory");
983
+ pool_free_startup_packet(sp);
984
+ alarm(0);
985
+ pool_signal(SIGALRM, SIG_IGN);
986
+ return NULL;
987
+ }
988
+ break;
989
+
990
+ default:
991
+ pool_error("read_startup_packet: invalid major no: %d", sp->major);
992
+ pool_free_startup_packet(sp);
993
+ alarm(0);
994
+ pool_signal(SIGALRM, SIG_IGN);
995
+ return NULL;
996
+ }
997
+
998
+ /* Check a user name was given. */
999
+ if (sp->major != 1234 &&
1000
+ (sp->user == NULL || sp->user[0] == '\0'))
1001
+ {
1002
+ pool_send_fatal_message(cp, sp->major, "28000",
1003
+ "no PostgreSQL user name specified in startup packet",
1004
+ "",
1005
+ "",
1006
+ __FILE__, __LINE__);
1007
+ pool_error("read_startup_packet: no PostgreSQL user name specified in startup packet");
1008
+ pool_free_startup_packet(sp);
1009
+ alarm(0);
1010
+ pool_signal(SIGALRM, SIG_IGN);
1011
+ return NULL;
1012
+ }
1013
+
1014
+ /* The database defaults to ther user name. */
1015
+ if (sp->database == NULL || sp->database[0] == '\0')
1016
+ {
1017
+ sp->database = strdup(sp->user);
1018
+ }
1019
+
1020
+ pool_debug("Protocol Major: %d Minor: %d database: %s user: %s",
1021
+ sp->major, sp->minor, sp->database, sp->user);
1022
+ alarm(0);
1023
+ pool_signal(SIGALRM, SIG_IGN);
1024
+ return sp;
1025
+ }
1026
+
1027
+ /*
1028
+ * send startup packet
1029
+ */
1030
+ int send_startup_packet(POOL_CONNECTION_POOL_SLOT *cp)
1031
+ {
1032
+ int len;
1033
+
1034
+ len = htonl(cp->sp->len + sizeof(len));
1035
+ pool_write(cp->con, &len, sizeof(len));
1036
+ return pool_write_and_flush(cp->con, cp->sp->startup_packet, cp->sp->len);
1037
+ }
1038
+
1039
+ /*
1040
+ * Reuse existing connection
1041
+ */
1042
+ static bool connect_using_existing_connection(POOL_CONNECTION *frontend,
1043
+ POOL_CONNECTION_POOL *backend,
1044
+ StartupPacket *sp)
1045
+ {
1046
+ int i, freed = 0;
1047
+ /*
1048
+ * Save startup packet info
1049
+ */
1050
+ for (i = 0; i < NUM_BACKENDS; i++)
1051
+ {
1052
+ if (VALID_BACKEND(i))
1053
+ {
1054
+ if (!freed)
1055
+ {
1056
+ pool_free_startup_packet(backend->slots[i]->sp);
1057
+ freed = 1;
1058
+ }
1059
+ backend->slots[i]->sp = sp;
1060
+ }
1061
+ }
1062
+
1063
+ /* Reuse existing connection to backend */
1064
+
1065
+ if (pool_do_reauth(frontend, backend))
1066
+ {
1067
+ pool_close(frontend);
1068
+ connection_count_down();
1069
+ return false;
1070
+ }
1071
+
1072
+ if (MAJOR(backend) == 3)
1073
+ {
1074
+ char command_buf[1024];
1075
+
1076
+ /* If we have received application_name in the start up
1077
+ * packet, we send SET command to backend. Also we add or
1078
+ * replace existing application_name data.
1079
+ */
1080
+ if (sp->application_name)
1081
+ {
1082
+ snprintf(command_buf, sizeof(command_buf), "SET application_name TO '%s'", sp->application_name);
1083
+
1084
+ for (i=0;i<NUM_BACKENDS;i++)
1085
+ {
1086
+ if (VALID_BACKEND(i))
1087
+ if (do_command(frontend, CONNECTION(backend, i),
1088
+ command_buf, MAJOR(backend),
1089
+ MASTER_CONNECTION(backend)->pid,
1090
+ MASTER_CONNECTION(backend)->key, 0) != POOL_CONTINUE)
1091
+ {
1092
+ pool_error("connect_using_existing_connection: do_command failed. command: %s", command_buf);
1093
+ return false;
1094
+ }
1095
+ }
1096
+
1097
+ pool_add_param(&MASTER(backend)->params, "application_name", sp->application_name);
1098
+ }
1099
+
1100
+ if (send_params(frontend, backend))
1101
+ {
1102
+ pool_close(frontend);
1103
+ connection_count_down();
1104
+ return false;
1105
+ }
1106
+ }
1107
+
1108
+ /* Send ReadyForQuery to frontend */
1109
+ pool_write(frontend, "Z", 1);
1110
+
1111
+ if (MAJOR(backend) == 3)
1112
+ {
1113
+ int len;
1114
+ char tstate;
1115
+
1116
+ len = htonl(5);
1117
+ pool_write(frontend, &len, sizeof(len));
1118
+ tstate = TSTATE(backend, MASTER_NODE_ID);
1119
+ pool_write(frontend, &tstate, 1);
1120
+ }
1121
+
1122
+ if (pool_flush(frontend) < 0)
1123
+ {
1124
+ pool_close(frontend);
1125
+ connection_count_down();
1126
+ return false;
1127
+ }
1128
+ return true;
1129
+ }
1130
+
1131
+ /*
1132
+ * process cancel request
1133
+ */
1134
+ void cancel_request(CancelPacket *sp)
1135
+ {
1136
+ int len;
1137
+ int fd;
1138
+ POOL_CONNECTION *con;
1139
+ int i,j,k;
1140
+ ConnectionInfo *c = NULL;
1141
+ CancelPacket cp;
1142
+ bool found = false;
1143
+
1144
+ pool_debug("Cancel request received");
1145
+
1146
+ /* look for cancel key from shmem info */
1147
+ for (i=0;i<pool_config->num_init_children;i++)
1148
+ {
1149
+ for (j=0;j<pool_config->max_pool;j++)
1150
+ {
1151
+ for (k=0;k<NUM_BACKENDS;k++)
1152
+ {
1153
+ c = pool_coninfo(i, j, k);
1154
+ pool_debug("con_info: address:%p database:%s user:%s pid:%d key:%d i:%d",
1155
+ c, c->database, c->user, ntohl(c->pid), ntohl(c->key),i);
1156
+
1157
+ if (c->pid == sp->pid && c->key == sp->key)
1158
+ {
1159
+ pool_debug("found pid:%d key:%d i:%d",ntohl(c->pid), ntohl(c->key),i);
1160
+ c = pool_coninfo(i, j, 0);
1161
+ found = true;
1162
+ goto found;
1163
+ }
1164
+ }
1165
+ }
1166
+ }
1167
+
1168
+ found:
1169
+ if (!found)
1170
+ {
1171
+ pool_error("cancel_request: invalid cancel key: pid:%d key:%d",ntohl(sp->pid), ntohl(sp->key));
1172
+ return; /* invalid key */
1173
+ }
1174
+
1175
+ for (i=0;i<NUM_BACKENDS;i++,c++)
1176
+ {
1177
+ if (!VALID_BACKEND(i))
1178
+ continue;
1179
+
1180
+ if (*(BACKEND_INFO(i).backend_hostname) == '/')
1181
+ fd = connect_unix_domain_socket(i, TRUE);
1182
+ else
1183
+ fd = connect_inet_domain_socket(i, TRUE);
1184
+
1185
+ if (fd < 0)
1186
+ {
1187
+ pool_error("Could not create socket for sending cancel request for backend %d", i);
1188
+ return;
1189
+ }
1190
+
1191
+ con = pool_open(fd);
1192
+ if (con == NULL)
1193
+ return;
1194
+
1195
+ len = htonl(sizeof(len) + sizeof(CancelPacket));
1196
+ pool_write(con, &len, sizeof(len));
1197
+
1198
+ cp.protoVersion = sp->protoVersion;
1199
+ cp.pid = c->pid;
1200
+ cp.key = c->key;
1201
+
1202
+ pool_log("cancel_request: canceling backend pid:%d key: %d", ntohl(cp.pid),ntohl(cp.key));
1203
+
1204
+ if (pool_write_and_flush(con, &cp, sizeof(CancelPacket)) < 0)
1205
+ pool_error("Could not send cancel request packet for backend %d", i);
1206
+
1207
+ pool_close(con);
1208
+
1209
+ /*
1210
+ * this is needed to ensure that the next DB node executes the
1211
+ * query supposed to be canceled.
1212
+ */
1213
+ sleep(1);
1214
+ }
1215
+ }
1216
+
1217
+ static POOL_CONNECTION_POOL *connect_backend(StartupPacket *sp, POOL_CONNECTION *frontend)
1218
+ {
1219
+ POOL_CONNECTION_POOL *backend;
1220
+ int i;
1221
+
1222
+ /* connect to the backend */
1223
+ backend = pool_create_cp();
1224
+ if (backend == NULL)
1225
+ {
1226
+ pool_send_error_message(frontend, sp->major, "XX000", "connection cache is full", "",
1227
+ "increase max_pool", __FILE__, __LINE__);
1228
+ pool_close(frontend);
1229
+ pool_free_startup_packet(sp);
1230
+ return NULL;
1231
+ }
1232
+
1233
+ for (i=0;i<NUM_BACKENDS;i++)
1234
+ {
1235
+ if (VALID_BACKEND(i))
1236
+ {
1237
+ /* set DB node id */
1238
+ CONNECTION(backend, i)->db_node_id = i;
1239
+
1240
+ /* mark this is a backend connection */
1241
+ CONNECTION(backend, i)->isbackend = 1;
1242
+ pool_ssl_negotiate_clientserver(CONNECTION(backend, i));
1243
+
1244
+ /*
1245
+ * save startup packet info
1246
+ */
1247
+ CONNECTION_SLOT(backend, i)->sp = sp;
1248
+
1249
+ /* send startup packet */
1250
+ if (send_startup_packet(CONNECTION_SLOT(backend, i)) < 0)
1251
+ {
1252
+ pool_error("do_child: fails to send startup packet to the %d th backend", i);
1253
+ pool_discard_cp(sp->user, sp->database, sp->major);
1254
+ pool_close(frontend);
1255
+ return NULL;
1256
+ }
1257
+ }
1258
+ }
1259
+
1260
+ /*
1261
+ * do authentication stuff
1262
+ */
1263
+ if (pool_do_auth(frontend, backend))
1264
+ {
1265
+ pool_close(frontend);
1266
+ pool_discard_cp(sp->user, sp->database, sp->major);
1267
+ return NULL;
1268
+ }
1269
+
1270
+ return backend;
1271
+ }
1272
+
1273
+ /*
1274
+ * signal handler for SIGTERM, SIGINT and SIGQUUT
1275
+ */
1276
+ static RETSIGTYPE die(int sig)
1277
+ {
1278
+ pool_debug("child received shutdown request signal %d", sig);
1279
+
1280
+ exit_request = sig;
1281
+
1282
+ switch (sig)
1283
+ {
1284
+ case SIGTERM: /* smart shutdown */
1285
+ if (idle == 0)
1286
+ {
1287
+ pool_debug("child receives smart shutdown request but it's not in idle state");
1288
+ }
1289
+ break;
1290
+
1291
+ case SIGINT: /* fast shutdown */
1292
+ case SIGQUIT: /* immediate shutdown */
1293
+ child_exit(0);
1294
+ break;
1295
+ default:
1296
+ pool_error("die() received unknown signal: %d", sig);
1297
+ break;
1298
+ }
1299
+ }
1300
+
1301
+ /*
1302
+ * signal handler for SIGUSR1
1303
+ * close all idle connections
1304
+ */
1305
+ static RETSIGTYPE close_idle_connection(int sig)
1306
+ {
1307
+ int i, j;
1308
+ POOL_CONNECTION_POOL *p = pool_connection_pool;
1309
+ ConnectionInfo *info;
1310
+
1311
+ pool_debug("child receives close connection request");
1312
+
1313
+ for (j=0;j<pool_config->max_pool;j++, p++)
1314
+ {
1315
+ if (!MASTER_CONNECTION(p))
1316
+ continue;
1317
+ if (!MASTER_CONNECTION(p)->sp)
1318
+ continue;
1319
+ if (MASTER_CONNECTION(p)->sp->user == NULL)
1320
+ continue;
1321
+
1322
+ if (MASTER_CONNECTION(p)->closetime > 0) /* idle connection? */
1323
+ {
1324
+ pool_debug("close_idle_connection: close idle connection: user %s database %s", MASTER_CONNECTION(p)->sp->user, MASTER_CONNECTION(p)->sp->database);
1325
+ pool_send_frontend_exits(p);
1326
+
1327
+ for (i=0;i<NUM_BACKENDS;i++)
1328
+ {
1329
+ if (!VALID_BACKEND(i))
1330
+ continue;
1331
+
1332
+ if (i == 0)
1333
+ {
1334
+ /* only first backend allocated the memory for the start up packet */
1335
+ pool_free_startup_packet(CONNECTION_SLOT(p, i)->sp);
1336
+ }
1337
+ pool_close(CONNECTION(p, i));
1338
+ }
1339
+ info = p->info;
1340
+ memset(p, 0, sizeof(POOL_CONNECTION_POOL));
1341
+ p->info = info;
1342
+ memset(p->info, 0, sizeof(ConnectionInfo));
1343
+ }
1344
+ }
1345
+ }
1346
+
1347
+ /*
1348
+ * signal handler for SIGALRM
1349
+ *
1350
+ */
1351
+ static RETSIGTYPE authentication_timeout(int sig)
1352
+ {
1353
+ pool_log("authentication is timeout");
1354
+ child_exit(1);
1355
+ }
1356
+
1357
+ /*
1358
+ * send frontend exiting messages to all connections. this is called
1359
+ * in any case when child process exits, for example failover, child
1360
+ * life time expires or child max connections expires.
1361
+ */
1362
+ static void send_frontend_exits(void)
1363
+ {
1364
+ int i;
1365
+ POOL_CONNECTION_POOL *p = pool_connection_pool;
1366
+
1367
+ #ifdef HAVE_SIGPROCMASK
1368
+ sigset_t oldmask;
1369
+ #else
1370
+ int oldmask;
1371
+ #endif
1372
+
1373
+ POOL_SETMASK2(&BlockSig, &oldmask);
1374
+
1375
+ for (i=0;i<pool_config->max_pool;i++, p++)
1376
+ {
1377
+ if (!MASTER_CONNECTION(p))
1378
+ continue;
1379
+ if (!MASTER_CONNECTION(p)->sp)
1380
+ continue;
1381
+ if (MASTER_CONNECTION(p)->sp->user == NULL)
1382
+ continue;
1383
+ pool_send_frontend_exits(p);
1384
+ }
1385
+
1386
+ POOL_SETMASK(&oldmask);
1387
+ }
1388
+
1389
+ static int send_params(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend)
1390
+ {
1391
+ int index;
1392
+ char *name, *value;
1393
+ int len, sendlen;
1394
+
1395
+ index = 0;
1396
+ while (pool_get_param(&MASTER(backend)->params, index++, &name, &value) == 0)
1397
+ {
1398
+ pool_write(frontend, "S", 1);
1399
+ len = sizeof(sendlen) + strlen(name) + 1 + strlen(value) + 1;
1400
+ sendlen = htonl(len);
1401
+ pool_write(frontend, &sendlen, sizeof(sendlen));
1402
+ pool_write(frontend, name, strlen(name) + 1);
1403
+ pool_write(frontend, value, strlen(value) + 1);
1404
+ }
1405
+
1406
+ if (pool_flush(frontend))
1407
+ {
1408
+ pool_error("pool_send_params: pool_flush() failed");
1409
+ return -1;
1410
+ }
1411
+ return 0;
1412
+ }
1413
+
1414
+ void pool_free_startup_packet(StartupPacket *sp)
1415
+ {
1416
+ if (sp)
1417
+ {
1418
+ if (sp->startup_packet)
1419
+ free(sp->startup_packet);
1420
+ if (sp->database)
1421
+ free(sp->database);
1422
+ if (sp->user)
1423
+ free(sp->user);
1424
+ free(sp);
1425
+ }
1426
+ sp = NULL;
1427
+ }
1428
+
1429
+ /*
1430
+ * Do house keeping works when pgpool child process exits
1431
+ */
1432
+ void child_exit(int code)
1433
+ {
1434
+ if (getpid() == mypid)
1435
+ {
1436
+ pool_log("child_exit: called from pgpool main. ignored.");
1437
+ return;
1438
+ }
1439
+
1440
+ /* count down global connection counter */
1441
+ if (accepted)
1442
+ connection_count_down();
1443
+
1444
+ /* prepare to shutdown connections to system db */
1445
+ if(pool_config->parallel_mode || pool_config->enable_query_cache)
1446
+ {
1447
+ if (system_db_info->pgconn)
1448
+ pool_close_libpq_connection();
1449
+ if (pool_system_db_connection())
1450
+ pool_close(pool_system_db_connection()->con);
1451
+ }
1452
+
1453
+ if (pool_config->memory_cache_enabled && !pool_is_shmem_cache())
1454
+ {
1455
+ memcached_disconnect();
1456
+ }
1457
+
1458
+ /* let backend know now we are exiting */
1459
+ if (pool_connection_pool)
1460
+ send_frontend_exits();
1461
+
1462
+ exit(code);
1463
+ }
1464
+
1465
+ /*
1466
+ * create a persistent connection
1467
+ */
1468
+ POOL_CONNECTION_POOL_SLOT *make_persistent_db_connection(
1469
+ char *hostname, int port, char *dbname, char *user, char *password, bool retry)
1470
+ {
1471
+ POOL_CONNECTION_POOL_SLOT *cp;
1472
+ int fd;
1473
+
1474
+ #define MAX_USER_AND_DATABASE 1024
1475
+
1476
+ /* V3 startup packet */
1477
+ typedef struct {
1478
+ int protoVersion;
1479
+ char data[MAX_USER_AND_DATABASE];
1480
+ } StartupPacket_v3;
1481
+
1482
+ static StartupPacket_v3 *startup_packet;
1483
+ int len, len1;
1484
+ int status;
1485
+
1486
+ cp = malloc(sizeof(POOL_CONNECTION_POOL_SLOT));
1487
+ if (cp == NULL)
1488
+ {
1489
+ pool_error("make_persistent_db_connection: could not allocate memory");
1490
+ return NULL;
1491
+ }
1492
+ memset(cp, 0, sizeof(POOL_CONNECTION_POOL_SLOT));
1493
+
1494
+ startup_packet = malloc(sizeof(*startup_packet));
1495
+ if (startup_packet == NULL)
1496
+ {
1497
+ pool_error("make_persistent_db_connection: could not allocate memory");
1498
+ free_persisten_db_connection_memory(cp);
1499
+ return NULL;
1500
+ }
1501
+ memset(startup_packet, 0, sizeof(*startup_packet));
1502
+ startup_packet->protoVersion = htonl(0x00030000); /* set V3 proto major/minor */
1503
+
1504
+ /*
1505
+ * create socket
1506
+ */
1507
+ if (*hostname == '/')
1508
+ {
1509
+ fd = connect_unix_domain_socket_by_port(port, hostname, retry);
1510
+ }
1511
+ else
1512
+ {
1513
+ fd = connect_inet_domain_socket_by_port(hostname, port, retry);
1514
+ }
1515
+
1516
+ if (fd < 0)
1517
+ {
1518
+ pool_error("make_persistent_db_connection: connection to %s(%d) failed", hostname, port);
1519
+ free_persisten_db_connection_memory(cp);
1520
+ free(startup_packet);
1521
+ return NULL;
1522
+ }
1523
+
1524
+ cp->con = pool_open(fd);
1525
+ cp->closetime = 0;
1526
+ cp->con->isbackend = 1;
1527
+ pool_ssl_negotiate_clientserver(cp->con);
1528
+
1529
+ /*
1530
+ * build V3 startup packet
1531
+ */
1532
+ len = snprintf(startup_packet->data, sizeof(startup_packet->data), "user") + 1;
1533
+ len1 = snprintf(&startup_packet->data[len], sizeof(startup_packet->data)-len, "%s", user) + 1;
1534
+ if (len1 >= (sizeof(startup_packet->data)-len))
1535
+ {
1536
+ pool_error("make_persistent_db_connection: too long user name");
1537
+ pool_close(cp->con);
1538
+ free_persisten_db_connection_memory(cp);
1539
+ free(startup_packet);
1540
+ return NULL;
1541
+ }
1542
+
1543
+ len += len1;
1544
+ len1 = snprintf(&startup_packet->data[len], sizeof(startup_packet->data)-len, "database") + 1;
1545
+ if (len1 >= (sizeof(startup_packet->data)-len))
1546
+ {
1547
+ pool_error("make_persistent_db_connection: too long user name");
1548
+ pool_close(cp->con);
1549
+ free_persisten_db_connection_memory(cp);
1550
+ free(startup_packet);
1551
+ return NULL;
1552
+ }
1553
+
1554
+ len += len1;
1555
+ len1 = snprintf(&startup_packet->data[len], sizeof(startup_packet->data)-len, "%s", dbname) + 1;
1556
+ if (len1 >= (sizeof(startup_packet->data)-len))
1557
+ {
1558
+ pool_error("make_persistent_db_connection: too long database name");
1559
+ pool_close(cp->con);
1560
+ free_persisten_db_connection_memory(cp);
1561
+ free(startup_packet);
1562
+ return NULL;
1563
+ }
1564
+ len += len1;
1565
+ startup_packet->data[len++] = '\0';
1566
+
1567
+ cp->sp = malloc(sizeof(StartupPacket));
1568
+ if (cp->sp == NULL)
1569
+ {
1570
+ pool_error("make_persistent_db_connection: could not allocate memory");
1571
+ pool_close(cp->con);
1572
+ free_persisten_db_connection_memory(cp);
1573
+ free(startup_packet);
1574
+ return NULL;
1575
+ }
1576
+
1577
+ cp->sp->startup_packet = (char *)startup_packet;
1578
+ cp->sp->len = len + 4;
1579
+ cp->sp->major = 3;
1580
+ cp->sp->minor = 0;
1581
+ cp->sp->database = strdup(dbname);
1582
+ if (cp->sp->database == NULL)
1583
+ {
1584
+ pool_error("make_persistent_db_connection: could not allocate memory");
1585
+ pool_close(cp->con);
1586
+ free_persisten_db_connection_memory(cp);
1587
+ return NULL;
1588
+ }
1589
+ cp->sp->user = strdup(user);
1590
+ if (cp->sp->user == NULL)
1591
+ {
1592
+ pool_error("make_persistent_db_connection: could not allocate memory");
1593
+ pool_close(cp->con);
1594
+ free_persisten_db_connection_memory(cp);
1595
+ return NULL;
1596
+ }
1597
+
1598
+ /*
1599
+ * send startup packet
1600
+ */
1601
+ status = send_startup_packet(cp);
1602
+ if (status)
1603
+ {
1604
+ pool_error("make_persistent_db_connection: send_startup_packet failed");
1605
+ pool_close(cp->con);
1606
+ free_persisten_db_connection_memory(cp);
1607
+ return NULL;
1608
+ }
1609
+
1610
+ /*
1611
+ * do authentication
1612
+ */
1613
+ if (s_do_auth(cp, password))
1614
+ {
1615
+ pool_error("make_persistent_db_connection: s_do_auth failed");
1616
+ pool_close(cp->con);
1617
+ free_persisten_db_connection_memory(cp);
1618
+ return NULL;
1619
+ }
1620
+
1621
+ return cp;
1622
+ }
1623
+
1624
+ /*
1625
+ * Free memory of POOL_CONNECTION_POOL_SLOT. Should only be used in
1626
+ * make_persistent_db_connection and discard_persistent_db_connection.
1627
+ */
1628
+ void free_persisten_db_connection_memory(POOL_CONNECTION_POOL_SLOT *cp)
1629
+ {
1630
+ if (!cp)
1631
+ return;
1632
+ if (!cp->sp)
1633
+ {
1634
+ free(cp);
1635
+ return;
1636
+ }
1637
+ if (cp->sp->startup_packet)
1638
+ free(cp->sp->startup_packet);
1639
+ if (cp->sp->database)
1640
+ free(cp->sp->database);
1641
+ if (cp->sp->user)
1642
+ free(cp->sp->user);
1643
+ free(cp->sp);
1644
+ free(cp);
1645
+ }
1646
+
1647
+ /*
1648
+ * Discard connection and memory allocated by
1649
+ * make_persistent_db_connection().
1650
+ */
1651
+ void discard_persistent_db_connection(POOL_CONNECTION_POOL_SLOT *cp)
1652
+ {
1653
+ int len;
1654
+
1655
+ if(cp == NULL)
1656
+ return;
1657
+
1658
+ pool_write(cp->con, "X", 1);
1659
+ len = htonl(4);
1660
+ pool_write(cp->con, &len, sizeof(len));
1661
+
1662
+ /*
1663
+ * XXX we cannot call pool_flush() here since backend may already
1664
+ * close the socket and pool_flush() automatically invokes fail
1665
+ * over handler. This could happen in copy command (remember the
1666
+ * famous "lost synchronization with server, resetting
1667
+ * connection" message)
1668
+ */
1669
+ pool_set_nonblock(cp->con->fd);
1670
+ pool_flush_it(cp->con);
1671
+ pool_unset_nonblock(cp->con->fd);
1672
+
1673
+ pool_close(cp->con);
1674
+ free_persisten_db_connection_memory(cp);
1675
+ }
1676
+
1677
+ /*
1678
+ * Do authentication. Assuming the only caller is
1679
+ * *make_persistent_db_connection().
1680
+ */
1681
+ static int s_do_auth(POOL_CONNECTION_POOL_SLOT *cp, char *password)
1682
+ {
1683
+ char kind;
1684
+ int status;
1685
+ int length;
1686
+ int auth_kind;
1687
+ char state;
1688
+ char *p;
1689
+ int pid, key;
1690
+ bool keydata_done;
1691
+
1692
+ /*
1693
+ * read kind expecting 'R' packet (authentication response)
1694
+ */
1695
+ status = pool_read(cp->con, &kind, sizeof(kind));
1696
+ if (status < 0)
1697
+ {
1698
+ pool_error("s_do_auth: error while reading message kind");
1699
+ return -1;
1700
+ }
1701
+
1702
+ if (kind != 'R')
1703
+ {
1704
+ pool_error("s_do_auth: expecting R got %c", kind);
1705
+ return -1;
1706
+ }
1707
+
1708
+ /* read message length */
1709
+ status = pool_read(cp->con, &length, sizeof(length));
1710
+ if (status < 0)
1711
+ {
1712
+ pool_error("s_do_auth: error while reading message length");
1713
+ return -1;
1714
+ }
1715
+ length = ntohl(length);
1716
+
1717
+ /* read auth kind */
1718
+ status = pool_read(cp->con, &auth_kind, sizeof(auth_kind));
1719
+ if (status < 0)
1720
+ {
1721
+ pool_error("s_do_auth: error while reading auth kind");
1722
+ return -1;
1723
+ }
1724
+ auth_kind = ntohl(auth_kind);
1725
+ pool_debug("s_do_auth: auth kind: %d", auth_kind);
1726
+
1727
+ if (auth_kind == 0) /* trust authentication? */
1728
+ {
1729
+ cp->con->auth_kind = 0;
1730
+ }
1731
+ else if (auth_kind == 3) /* clear text password? */
1732
+ {
1733
+ int size = htonl(strlen(password) + 5);
1734
+
1735
+ pool_write(cp->con, "p", 1);
1736
+ pool_write(cp->con, &size, sizeof(size));
1737
+ pool_write_and_flush(cp->con, password, strlen(password) + 1);
1738
+ status = pool_flush(cp->con);
1739
+ if (status > 0)
1740
+ {
1741
+ pool_error("s_do_auth: error while sending clear text password");
1742
+ return -1;
1743
+ }
1744
+ return s_do_auth(cp, password);
1745
+ }
1746
+ else if (auth_kind == 4) /* crypt password? */
1747
+ {
1748
+ int size;
1749
+ char salt[3];
1750
+ char *crypt_password;
1751
+
1752
+ status = pool_read(cp->con, &salt, 2);
1753
+ if (status > 0)
1754
+ {
1755
+ pool_error("s_do_auth: error while reading crypt salt");
1756
+ return -1;
1757
+ }
1758
+ salt[2] = '\0';
1759
+
1760
+ crypt_password = crypt(password, salt);
1761
+ size = htonl(strlen(crypt_password) + 5);
1762
+ pool_write(cp->con, "p", 1);
1763
+ pool_write(cp->con, &size, sizeof(size));
1764
+ pool_write_and_flush(cp->con, crypt_password, strlen(crypt_password) + 1);
1765
+ status = pool_flush(cp->con);
1766
+ if (status > 0)
1767
+ {
1768
+ pool_error("s_do_auth: error while sending crypt password");
1769
+ return -1;
1770
+ }
1771
+ return s_do_auth(cp, password);
1772
+ }
1773
+ else if (auth_kind == 5) /* md5 password? */
1774
+ {
1775
+ char salt[4];
1776
+ char *buf, *buf1;
1777
+ int size;
1778
+
1779
+ status = pool_read(cp->con, &salt, 4);
1780
+ if (status > 0)
1781
+ {
1782
+ pool_error("s_do_auth: error while reading md5 salt");
1783
+ return -1;
1784
+ }
1785
+
1786
+ buf = malloc(2 * (MD5_PASSWD_LEN + 4)); /* hash + "md5" + '\0' */
1787
+ if (buf == NULL)
1788
+ {
1789
+ pool_error("s_do_auth(): malloc failed: %s", strerror(errno));
1790
+ return -1;
1791
+ }
1792
+ memset(buf, 0, 2 * (MD5_PASSWD_LEN + 4));
1793
+
1794
+ /* build md5 password */
1795
+ buf1 = buf + MD5_PASSWD_LEN + 4;
1796
+ pool_md5_encrypt(password, cp->sp->user, strlen(cp->sp->user), buf1);
1797
+ pool_md5_encrypt(buf1, salt, 4, buf + 3);
1798
+ memcpy(buf, "md5", 3);
1799
+
1800
+ size = htonl(strlen(buf) + 5);
1801
+ pool_write(cp->con, "p", 1);
1802
+ pool_write(cp->con, &size, sizeof(size));
1803
+ pool_write_and_flush(cp->con, buf, strlen(buf) + 1);
1804
+ status = pool_flush(cp->con);
1805
+ if (status > 0)
1806
+ {
1807
+ pool_error("s_do_auth: error while sending md5 password");
1808
+ return -1;
1809
+ }
1810
+
1811
+ status = s_do_auth(cp, password);
1812
+ free(buf);
1813
+ return status;
1814
+ }
1815
+ else
1816
+ {
1817
+ pool_error("s_do_auth: auth kind %d not supported yet", auth_kind);
1818
+ return -1;
1819
+ }
1820
+
1821
+ /*
1822
+ * Read backend key data and wait until Ready for query arriving or
1823
+ * error happens.
1824
+ */
1825
+
1826
+ keydata_done = false;
1827
+
1828
+ for (;;)
1829
+ {
1830
+ status = pool_read(cp->con, &kind, sizeof(kind));
1831
+ if (status < 0)
1832
+ {
1833
+ pool_error("s_do_auth: error while reading message kind");
1834
+ return -1;
1835
+ }
1836
+
1837
+ switch (kind)
1838
+ {
1839
+ case 'K': /* backend key data */
1840
+ keydata_done = true;
1841
+ pool_debug("s_do_auth: backend key data received");
1842
+
1843
+ /* read message length */
1844
+ status = pool_read(cp->con, &length, sizeof(length));
1845
+ if (status < 0)
1846
+ {
1847
+ pool_error("s_do_auth: error while reading message length");
1848
+ return -1;
1849
+ }
1850
+ if (ntohl(length) != 12)
1851
+ {
1852
+ pool_error("s_do_auth: backend key data length is not 12 (%d)", ntohl(length));
1853
+ }
1854
+
1855
+ /* read pid */
1856
+ if (pool_read(cp->con, &pid, sizeof(pid)) < 0)
1857
+ {
1858
+ pool_error("s_do_auth: failed to read pid");
1859
+ return -1;
1860
+ }
1861
+ cp->pid = pid;
1862
+
1863
+ /* read key */
1864
+ if (pool_read(cp->con, &key, sizeof(key)) < 0)
1865
+ {
1866
+ pool_error("s_do_auth: failed to read key");
1867
+ return -1;
1868
+ }
1869
+ cp->key = key;
1870
+ break;
1871
+
1872
+ case 'Z': /* Ready for query */
1873
+ /* read message length */
1874
+ status = pool_read(cp->con, &length, sizeof(length));
1875
+ if (status < 0)
1876
+ {
1877
+ pool_error("s_do_auth: error while reading message length");
1878
+ return -1;
1879
+ }
1880
+ length = ntohl(length);
1881
+
1882
+ /* read transaction state */
1883
+ status = pool_read(cp->con, &state, sizeof(state));
1884
+ if (status < 0)
1885
+ {
1886
+ pool_error("s_do_auth: error while reading transaction state");
1887
+ return -1;
1888
+ }
1889
+
1890
+ pool_debug("s_do_auth: transaction state: %c", state);
1891
+ cp->con->tstate = state;
1892
+
1893
+ if (!keydata_done)
1894
+ {
1895
+ pool_error("s_do_auth: ready for query arrived before receiving keydata");
1896
+ }
1897
+ return 0;
1898
+ break;
1899
+
1900
+ case 'S': /* parameter status */
1901
+ case 'N': /* notice response */
1902
+ case 'E': /* error response */
1903
+ /* Just throw away data */
1904
+ status = pool_read(cp->con, &length, sizeof(length));
1905
+ if (status < 0)
1906
+ {
1907
+ pool_error("s_do_auth: error while reading message length. kind:%c", kind);
1908
+ return -1;
1909
+ }
1910
+
1911
+ length = ntohl(length);
1912
+ length -= 4;
1913
+
1914
+ p = pool_read2(cp->con, length);
1915
+ if (p == NULL)
1916
+ return -1;
1917
+ break;
1918
+
1919
+ default:
1920
+ pool_error("s_do_auth: unknown response \"%c\" while processing BackendKeyData",
1921
+ kind);
1922
+ break;
1923
+ }
1924
+ }
1925
+ return -1;
1926
+ }
1927
+
1928
+ /*
1929
+ * Count up connection counter (from frontend to pgpool)
1930
+ * in shared memory
1931
+ */
1932
+ static void connection_count_up(void)
1933
+ {
1934
+ #ifdef HAVE_SIGPROCMASK
1935
+ sigset_t oldmask;
1936
+ #else
1937
+ int oldmask;
1938
+ #endif
1939
+
1940
+ POOL_SETMASK2(&BlockSig, &oldmask);
1941
+ pool_semaphore_lock(CONN_COUNTER_SEM);
1942
+ Req_info->conn_counter++;
1943
+ pool_semaphore_unlock(CONN_COUNTER_SEM);
1944
+ POOL_SETMASK(&oldmask);
1945
+ }
1946
+
1947
+ /*
1948
+ * Count down connection counter (from frontend to pgpool)
1949
+ * in shared memory
1950
+ */
1951
+ static void connection_count_down(void)
1952
+ {
1953
+ #ifdef HAVE_SIGPROCMASK
1954
+ sigset_t oldmask;
1955
+ #else
1956
+ int oldmask;
1957
+ #endif
1958
+
1959
+ POOL_SETMASK2(&BlockSig, &oldmask);
1960
+ pool_semaphore_lock(CONN_COUNTER_SEM);
1961
+ /*
1962
+ * Make sure that we do not decrement too much. If failed to read
1963
+ * a start up packet, or receive cancel request etc.,
1964
+ * connection_count_down() is called and goes back to the
1965
+ * connection accept loop. Problem is, at the very beginning of
1966
+ * the connection accept loop, if we have received a signal, we
1967
+ * call child_exit() which calls connection_count_down() again.
1968
+ */
1969
+ if (Req_info->conn_counter > 0)
1970
+ Req_info->conn_counter--;
1971
+ pool_semaphore_unlock(CONN_COUNTER_SEM);
1972
+ POOL_SETMASK(&oldmask);
1973
+ }
1974
+
1975
+ /*
1976
+ * handle SIGUSR2
1977
+ * Wakeup all process
1978
+ */
1979
+ static RETSIGTYPE wakeup_handler(int sig)
1980
+ {
1981
+ }
1982
+
1983
+
1984
+ /*
1985
+ * Select load balancing node
1986
+ */
1987
+ int select_load_balancing_node(void)
1988
+ {
1989
+ int selected_slot;
1990
+ double total_weight,r;
1991
+ int i;
1992
+
1993
+ /* choose a backend in random manner with weight */
1994
+ selected_slot = MASTER_NODE_ID;
1995
+ total_weight = 0.0;
1996
+
1997
+ for (i=0;i<NUM_BACKENDS;i++)
1998
+ {
1999
+ if (VALID_BACKEND(i))
2000
+ {
2001
+ total_weight += BACKEND_INFO(i).backend_weight;
2002
+ }
2003
+ }
2004
+
2005
+ #if defined(sun) || defined(__sun)
2006
+ r = (((double)rand())/RAND_MAX) * total_weight;
2007
+ #else
2008
+ r = (((double)random())/RAND_MAX) * total_weight;
2009
+ #endif
2010
+
2011
+ total_weight = 0.0;
2012
+ for (i=0;i<NUM_BACKENDS;i++)
2013
+ {
2014
+ if (VALID_BACKEND(i) && BACKEND_INFO(i).backend_weight > 0.0)
2015
+ {
2016
+ if(r >= total_weight)
2017
+ selected_slot = i;
2018
+ else
2019
+ break;
2020
+ total_weight += BACKEND_INFO(i).backend_weight;
2021
+ }
2022
+ }
2023
+
2024
+ pool_debug("select_load_balancing_node: selected backend id is %d", selected_slot);
2025
+ return selected_slot;
2026
+ }
2027
+
2028
+ /* SIGHUP handler */
2029
+ static RETSIGTYPE reload_config_handler(int sig)
2030
+ {
2031
+ got_sighup = 1;
2032
+ }
2033
+
2034
+ /*
2035
+ * Exit myself if SIGTERM, SIGINT or SIGQUIT has been sent
2036
+ */
2037
+ void check_stop_request(void)
2038
+ {
2039
+ /*
2040
+ * If smart shutdown was requested but we are not in idle state,
2041
+ * do not exit
2042
+ */
2043
+ if (exit_request == SIGTERM && idle == 0)
2044
+ return;
2045
+
2046
+ if (exit_request)
2047
+ {
2048
+ reset_variables();
2049
+ child_exit(0);
2050
+ }
2051
+ }
2052
+
2053
+ /*
2054
+ * Initialize system DB connection
2055
+ */
2056
+ static void init_system_db_connection(void)
2057
+ {
2058
+ if (pool_config->parallel_mode || pool_config->enable_query_cache)
2059
+ {
2060
+ system_db_connect();
2061
+ if (PQstatus(system_db_info->pgconn) != CONNECTION_OK)
2062
+ {
2063
+ pool_error("Could not make persistent libpq system DB connection");
2064
+ }
2065
+
2066
+ system_db_info->connection = make_persistent_db_connection(pool_config->system_db_hostname,
2067
+ pool_config->system_db_port,
2068
+ pool_config->system_db_dbname,
2069
+ pool_config->system_db_user,
2070
+ pool_config->system_db_password, false);
2071
+ if (system_db_info->connection == NULL)
2072
+ {
2073
+ pool_error("Could not make persistent system DB connection");
2074
+ }
2075
+ }
2076
+ }
2077
+
2078
+ /*
2079
+ * Initialize my backend status and master node id.
2080
+ * We copy the backend status to private area so that
2081
+ * they are not changed while I am alive.
2082
+ */
2083
+ void pool_initialize_private_backend_status(void)
2084
+ {
2085
+ int i;
2086
+
2087
+ pool_debug("pool_initialize_private_backend_status: initialize backend status");
2088
+
2089
+ for (i=0;i<MAX_NUM_BACKENDS;i++)
2090
+ {
2091
+ private_backend_status[i] = BACKEND_INFO(i).backend_status;
2092
+ /* my_backend_status is referred to by VALID_BACKEND macro. */
2093
+ my_backend_status[i] = &private_backend_status[i];
2094
+ }
2095
+
2096
+ my_master_node_id = REAL_MASTER_NODE_ID;
2097
+ }