prestogres 0.1.0

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