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
@@ -0,0 +1,1493 @@
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-2011 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
+ * pcp_child.c: PCP 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_FCNTL_H
49
+ #include <fcntl.h>
50
+ #endif
51
+
52
+ #include "pool.h"
53
+ #include "pcp/pcp_stream.h"
54
+ #include "pcp/pcp.h"
55
+ #include "md5.h"
56
+ #include "pool_config.h"
57
+ #include "pool_process_context.h"
58
+ #include "pool_process_reporting.h"
59
+ #include "watchdog/wd_ext.h"
60
+
61
+ #define MAX_FILE_LINE_LEN 512
62
+ #define MAX_USER_PASSWD_LEN 128
63
+
64
+ extern void pcp_set_timeout(long sec);
65
+ volatile sig_atomic_t pcp_exit_request; /* non 0 means SIGTERM(smart shutdown) or SIGINT(fast shutdown) has arrived */
66
+
67
+ static RETSIGTYPE die(int sig);
68
+ static PCP_CONNECTION *pcp_do_accept(int unix_fd, int inet_fd);
69
+ static void unset_nonblock(int fd);
70
+ static int user_authenticate(char *buf, char *passwd_file, char *salt, int salt_len);
71
+ static RETSIGTYPE wakeup_handler(int sig);
72
+ static RETSIGTYPE reload_config_handler(int sig);
73
+ static RETSIGTYPE restart_handler(int sig);
74
+ static int pool_detach_node(int node_id, bool gracefully);
75
+ static int pool_promote_node(int node_id, bool gracefully);
76
+
77
+ extern int myargc;
78
+ extern char **myargv;
79
+
80
+ static volatile sig_atomic_t pcp_got_sighup = 0;
81
+ volatile sig_atomic_t pcp_wakeup_request = 0;
82
+ static volatile sig_atomic_t pcp_restart_request = 0;
83
+
84
+ #define CHECK_RESTART_REQUEST \
85
+ do { \
86
+ if (pcp_restart_request) \
87
+ { \
88
+ pool_log("pcp child process received restart request"); \
89
+ exit(1); \
90
+ } \
91
+ else \
92
+ { \
93
+ pool_initialize_private_backend_status(); \
94
+ } \
95
+ } while (0)
96
+
97
+ void
98
+ pcp_do_child(int unix_fd, int inet_fd, char *pcp_conf_file)
99
+ {
100
+ PCP_CONNECTION *frontend = NULL;
101
+ int authenticated = 0;
102
+ struct timeval uptime;
103
+ char salt[4];
104
+ int random_salt = 0;
105
+ int i;
106
+ char tos;
107
+ int rsize;
108
+ char *buf = NULL;
109
+
110
+ pool_debug("I am PCP %d", getpid());
111
+
112
+ /* Identify myself via ps */
113
+ init_ps_display("", "", "", "");
114
+
115
+ gettimeofday(&uptime, NULL);
116
+ srandom((unsigned int) (getpid() ^ uptime.tv_usec));
117
+
118
+ /* set pcp_read() timeout */
119
+ pcp_set_timeout(pool_config->pcp_timeout);
120
+
121
+ /* set up signal handlers */
122
+ signal(SIGTERM, die);
123
+ signal(SIGINT, die);
124
+ signal(SIGHUP, reload_config_handler);
125
+ signal(SIGQUIT, die);
126
+ signal(SIGCHLD, SIG_DFL);
127
+ signal(SIGUSR1, restart_handler);
128
+ signal(SIGUSR2, wakeup_handler);
129
+ signal(SIGPIPE, SIG_IGN);
130
+ signal(SIGALRM, SIG_IGN);
131
+
132
+ /* Initialize my backend status */
133
+ pool_initialize_private_backend_status();
134
+
135
+ /* Initialize process context */
136
+ pool_init_process_context();
137
+
138
+ for(;;)
139
+ {
140
+ errno = 0;
141
+
142
+ CHECK_RESTART_REQUEST;
143
+
144
+ if (frontend == NULL)
145
+ {
146
+ frontend = pcp_do_accept(unix_fd, inet_fd);
147
+ if (frontend == NULL)
148
+ continue;
149
+
150
+ unset_nonblock(frontend->fd);
151
+ }
152
+
153
+ /* read a PCP packet */
154
+ if (pcp_read(frontend, &tos, 1))
155
+ {
156
+ if (errorcode == TIMEOUTERR)
157
+ {
158
+ pool_debug("pcp_child: pcp_read() has timed out");
159
+ authenticated = 0;
160
+ pcp_close(frontend); frontend = NULL;
161
+ free(buf); buf = NULL;
162
+ continue;
163
+ }
164
+ pool_error("pcp_child: pcp_read() failed. reason: %s", strerror(errno));
165
+ exit(1);
166
+ }
167
+ if (pcp_read(frontend, &rsize, sizeof(int)))
168
+ {
169
+ if (errorcode == TIMEOUTERR)
170
+ {
171
+ pool_debug("pcp_child: pcp_read() has timed out");
172
+ authenticated = 0;
173
+ pcp_close(frontend); frontend = NULL;
174
+ free(buf); buf = NULL;
175
+ continue;
176
+ }
177
+ pool_error("pcp_child: pcp_read() failed. reason: %s", strerror(errno));
178
+ exit(1);
179
+ }
180
+
181
+ rsize = ntohl(rsize);
182
+ if ((rsize - sizeof(int)) > 0)
183
+ {
184
+ buf = (char *)malloc(rsize - sizeof(int));
185
+ if (buf == NULL)
186
+ {
187
+ pool_error("pcp_child: malloc() failed. reason: %s", strerror(errno));
188
+ exit(1);
189
+ }
190
+ if (pcp_read(frontend, buf, rsize - sizeof(int)))
191
+ {
192
+ if (errorcode == TIMEOUTERR)
193
+ {
194
+ pool_debug("pcp_child: pcp_read() has timed out");
195
+ authenticated = 0;
196
+ pcp_close(frontend); frontend = NULL;
197
+ free(buf); buf = NULL;
198
+ continue;
199
+ }
200
+ pool_error("pcp_child: pcp_read() failed. reason: %s", strerror(errno));
201
+ exit(1);
202
+ }
203
+ }
204
+
205
+ /* is this connection authenticated? if not disconnect immediately*/
206
+ if ((! authenticated) && (tos != 'R' && tos != 'M'))
207
+ {
208
+ pool_debug("pcp_child: connection not authorized");
209
+ free(buf);
210
+ buf = NULL;
211
+ pcp_close(frontend);
212
+ frontend = NULL;
213
+ pool_signal(SIGALRM, SIG_IGN);
214
+ continue;
215
+ }
216
+
217
+ /* process a request */
218
+ pool_debug("pcp_child: received PCP packet type of service '%c'", tos);
219
+
220
+ set_ps_display("PCP: processing a request", false);
221
+
222
+ if (tos == 'C' || tos == 'd' || tos == 'D' || tos == 'j' ||
223
+ tos == 'J' || tos == 'O' || tos == 'T')
224
+ {
225
+ if (Req_info->switching)
226
+ {
227
+ int len;
228
+ int wsize;
229
+ char *msg;
230
+
231
+ if (Req_info->kind == NODE_UP_REQUEST)
232
+ msg = "FailbackInProgress";
233
+ else if (Req_info->kind == NODE_DOWN_REQUEST)
234
+ msg = "FailoverInProgress";
235
+ else if (Req_info->kind == PROMOTE_NODE_REQUEST)
236
+ msg = "PromotionInProgress";
237
+ else
238
+ msg = "OperationInProgress";
239
+
240
+ len = strlen(msg) + 1;
241
+ pcp_write(frontend, "e", 1);
242
+ wsize = htonl(sizeof(int) + len);
243
+ pcp_write(frontend, &wsize, sizeof(int));
244
+ pcp_write(frontend, msg, len);
245
+ }
246
+ }
247
+
248
+ switch (tos)
249
+ {
250
+ case 'R': /* authentication */
251
+ {
252
+ int wsize;
253
+
254
+ if (random_salt)
255
+ {
256
+ authenticated = user_authenticate(buf, pcp_conf_file, salt, 4);
257
+ }
258
+ if (!random_salt || !authenticated)
259
+ {
260
+ char code[] = "AuthenticationFailed";
261
+ char mesg[] = "username and/or password do not match";
262
+ pcp_write(frontend, "r", 1);
263
+ wsize = htonl(sizeof(code) + sizeof(mesg) + sizeof(int));
264
+ pcp_write(frontend, &wsize, sizeof(int));
265
+ pcp_write(frontend, code, sizeof(code));
266
+ pcp_write(frontend, mesg, sizeof(mesg));
267
+ if (pcp_flush(frontend) < 0)
268
+ {
269
+ pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
270
+ exit(1);
271
+ }
272
+
273
+ pool_error("pcp_child: authentication failed");
274
+ pcp_close(frontend);
275
+ frontend = NULL;
276
+ random_salt = 0;
277
+ }
278
+ else
279
+ {
280
+ char code[] = "AuthenticationOK";
281
+ pcp_write(frontend, "r", 1);
282
+ wsize = htonl(sizeof(code) + sizeof(int));
283
+ pcp_write(frontend, &wsize, sizeof(int));
284
+ pcp_write(frontend, code, sizeof(code));
285
+ if (pcp_flush(frontend) < 0)
286
+ {
287
+ pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
288
+ exit(1);
289
+ }
290
+ random_salt = 0;
291
+
292
+ pool_debug("pcp_child: authentication OK");
293
+ }
294
+ break;
295
+ }
296
+
297
+ case 'M': /* md5 salt */
298
+ {
299
+ int wsize;
300
+
301
+ pool_random_salt(salt);
302
+ random_salt = 1;
303
+
304
+ pcp_write(frontend, "m", 1);
305
+ wsize = htonl(sizeof(int) + 4);
306
+ pcp_write(frontend, &wsize, sizeof(int));
307
+ pcp_write(frontend, salt, 4);
308
+ if (pcp_flush(frontend) < 0)
309
+ {
310
+ pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
311
+ exit(1);
312
+ }
313
+
314
+ pool_debug("pcp_child: salt sent to the client");
315
+ break;
316
+ }
317
+
318
+ case 'L': /* node count */
319
+ {
320
+ int wsize;
321
+ int node_count = pool_get_node_count();
322
+
323
+ char code[] = "CommandComplete";
324
+ char mesg[16];
325
+
326
+ snprintf(mesg, sizeof(mesg), "%d", node_count);
327
+
328
+ pcp_write(frontend, "l", 1);
329
+ wsize = htonl(sizeof(code) +
330
+ strlen(mesg)+1 +
331
+ sizeof(int));
332
+ pcp_write(frontend, &wsize, sizeof(int));
333
+ pcp_write(frontend, code, sizeof(code));
334
+ pcp_write(frontend, mesg, strlen(mesg)+1);
335
+ if (pcp_flush(frontend) < 0)
336
+ {
337
+ pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
338
+ exit(1);
339
+ }
340
+
341
+ pool_debug("pcp_child: %d node(s) found", node_count);
342
+ break;
343
+ }
344
+ case 'I': /* node info */
345
+ {
346
+ int node_id;
347
+ int wsize;
348
+
349
+ BackendInfo *bi = NULL;
350
+
351
+ node_id = atoi(buf);
352
+ bi = pool_get_node_info(node_id);
353
+
354
+ if (bi == NULL) {
355
+ char code[] = "Invalid Node ID";
356
+
357
+ pcp_write(frontend, "e", 1);
358
+ wsize = htonl(sizeof(code) + sizeof(int));
359
+ pcp_write(frontend, &wsize, sizeof(int));
360
+ pcp_write(frontend, code, sizeof(code));
361
+ if (pcp_flush(frontend) < 0)
362
+ {
363
+ pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
364
+ exit(1);
365
+ }
366
+
367
+ pool_debug("pcp_child: invalid node ID");
368
+ }
369
+ else
370
+ {
371
+ char code[] = "CommandComplete";
372
+ char port_str[6];
373
+ char status[2];
374
+ char weight_str[20];
375
+
376
+ snprintf(port_str, sizeof(port_str), "%d", bi->backend_port);
377
+ snprintf(status, sizeof(status), "%d", bi->backend_status);
378
+ snprintf(weight_str, sizeof(weight_str), "%f", bi->backend_weight);
379
+
380
+ pcp_write(frontend, "i", 1);
381
+ wsize = htonl(sizeof(code) +
382
+ strlen(bi->backend_hostname)+1 +
383
+ strlen(port_str)+1 +
384
+ strlen(status)+1 +
385
+ strlen(weight_str)+1 +
386
+ sizeof(int));
387
+ pcp_write(frontend, &wsize, sizeof(int));
388
+ pcp_write(frontend, code, sizeof(code));
389
+ pcp_write(frontend, bi->backend_hostname, strlen(bi->backend_hostname)+1);
390
+ pcp_write(frontend, port_str, strlen(port_str)+1);
391
+ pcp_write(frontend, status, strlen(status)+1);
392
+ pcp_write(frontend, weight_str, strlen(weight_str)+1);
393
+ if (pcp_flush(frontend) < 0)
394
+ {
395
+ pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
396
+ exit(1);
397
+ }
398
+
399
+ pool_debug("pcp_child: retrieved node information from shared memory");
400
+ }
401
+ break;
402
+ }
403
+
404
+ case 'N': /* process count */
405
+ {
406
+ int wsize;
407
+ int process_count;
408
+ char process_count_str[16];
409
+ int *process_list = NULL;
410
+ char code[] = "CommandComplete";
411
+ char *mesg = NULL;
412
+ int i;
413
+ int total_port_len = 0;
414
+
415
+ process_list = pool_get_process_list(&process_count);
416
+
417
+ mesg = (char *)malloc(6*process_count); /* port# is at most 5 characters long (MAX:65535) */
418
+ if (mesg == NULL)
419
+ {
420
+ pool_error("pcp_child: malloc() failed. reason: %s", strerror(errno));
421
+ exit(1);
422
+ }
423
+
424
+ snprintf(process_count_str, sizeof(process_count_str), "%d", process_count);
425
+
426
+ for (i = 0; i < process_count; i++)
427
+ {
428
+ char port[6];
429
+ snprintf(port, sizeof(port), "%d", process_list[i]);
430
+ snprintf(mesg+total_port_len, strlen(port)+1, "%s", port);
431
+ total_port_len += strlen(port)+1;
432
+ }
433
+
434
+ pcp_write(frontend, "n", 1);
435
+ wsize = htonl(sizeof(code) +
436
+ strlen(process_count_str)+1 +
437
+ total_port_len +
438
+ sizeof(int));
439
+ pcp_write(frontend, &wsize, sizeof(int));
440
+ pcp_write(frontend, code, sizeof(code));
441
+ pcp_write(frontend, process_count_str, strlen(process_count_str)+1);
442
+ pcp_write(frontend, mesg, total_port_len);
443
+ if (pcp_flush(frontend) < 0)
444
+ {
445
+ pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
446
+ exit(1);
447
+ }
448
+
449
+ free(process_list);
450
+ free(mesg);
451
+
452
+ pool_debug("pcp_child: %d process(es) found", process_count);
453
+ break;
454
+ }
455
+
456
+ case 'P': /* process info */
457
+ {
458
+ int proc_id;
459
+ int wsize;
460
+ int num_proc = pool_config->num_init_children;
461
+ int i;
462
+
463
+ proc_id = atoi(buf);
464
+
465
+ if ((proc_id != 0) && (pool_get_process_info(proc_id) == NULL))
466
+ {
467
+ char code[] = "InvalidProcessID";
468
+
469
+ pcp_write(frontend, "e", 1);
470
+ wsize = htonl(sizeof(code) + sizeof(int));
471
+ pcp_write(frontend, &wsize, sizeof(int));
472
+ pcp_write(frontend, code, sizeof(code));
473
+ if (pcp_flush(frontend) < 0)
474
+ {
475
+ pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
476
+ exit(1);
477
+ }
478
+
479
+ pool_debug("pcp_child: invalid process ID");
480
+ }
481
+ else
482
+ {
483
+ /* First, send array size of connection_info */
484
+ char arr_code[] = "ArraySize";
485
+ char con_info_size[16];
486
+ /* Finally, indicate that all data is sent */
487
+ char fin_code[] = "CommandComplete";
488
+
489
+ POOL_REPORT_POOLS *pools = get_pools(&num_proc);
490
+
491
+ if (proc_id == 0)
492
+ {
493
+ snprintf(con_info_size, sizeof(con_info_size), "%d", num_proc);
494
+ }
495
+ else
496
+ {
497
+ snprintf(con_info_size, sizeof(con_info_size), "%d", pool_config->max_pool * NUM_BACKENDS);
498
+ }
499
+
500
+ pcp_write(frontend, "p", 1);
501
+ wsize = htonl(sizeof(arr_code) +
502
+ strlen(con_info_size)+1 +
503
+ sizeof(int));
504
+ pcp_write(frontend, &wsize, sizeof(int));
505
+ pcp_write(frontend, arr_code, sizeof(arr_code));
506
+ pcp_write(frontend, con_info_size, strlen(con_info_size)+1);
507
+ if (pcp_flush(frontend) < 0)
508
+ {
509
+ pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
510
+ free(pools);
511
+ exit(1);
512
+ }
513
+
514
+ /* Second, send process information for all connection_info */
515
+ for (i=0; i<num_proc; i++)
516
+ {
517
+ char code[] = "ProcessInfo";
518
+ char proc_pid[16];
519
+ char proc_start_time[20];
520
+ char proc_create_time[20];
521
+ char majorversion[5];
522
+ char minorversion[5];
523
+ char pool_counter[16];
524
+ char backend_id[16];
525
+ char backend_pid[16];
526
+ char connected[2];
527
+
528
+ if (proc_id != 0 && proc_id != pools[i].pool_pid) continue;
529
+
530
+ snprintf(proc_pid, sizeof(proc_pid), "%d", pools[i].pool_pid);
531
+ snprintf(proc_start_time, sizeof(proc_start_time), "%ld", pools[i].start_time);
532
+ snprintf(proc_create_time, sizeof(proc_create_time), "%ld", pools[i].create_time);
533
+ snprintf(majorversion, sizeof(majorversion), "%d", pools[i].pool_majorversion);
534
+ snprintf(minorversion, sizeof(minorversion), "%d", pools[i].pool_minorversion);
535
+ snprintf(pool_counter, sizeof(pool_counter), "%d", pools[i].pool_counter);
536
+ snprintf(backend_id, sizeof(backend_pid), "%d", pools[i].backend_id);
537
+ snprintf(backend_pid, sizeof(backend_pid), "%d", pools[i].pool_backendpid);
538
+ snprintf(connected, sizeof(connected), "%d", pools[i].pool_connected);
539
+
540
+ pcp_write(frontend, "p", 1);
541
+ wsize = htonl( sizeof(code) +
542
+ strlen(proc_pid)+1 +
543
+ strlen(pools[i].database)+1 +
544
+ strlen(pools[i].username)+1 +
545
+ strlen(proc_start_time)+1 +
546
+ strlen(proc_create_time)+1 +
547
+ strlen(majorversion)+1 +
548
+ strlen(minorversion)+1 +
549
+ strlen(pool_counter)+1 +
550
+ strlen(backend_id)+1 +
551
+ strlen(backend_pid)+1 +
552
+ strlen(connected)+1 +
553
+ sizeof(int));
554
+ pcp_write(frontend, &wsize, sizeof(int));
555
+ pcp_write(frontend, code, sizeof(code));
556
+ pcp_write(frontend, proc_pid, strlen(proc_pid)+1);
557
+ pcp_write(frontend, pools[i].database, strlen(pools[i].database)+1);
558
+ pcp_write(frontend, pools[i].username, strlen(pools[i].username)+1);
559
+ pcp_write(frontend, proc_start_time, strlen(proc_start_time)+1);
560
+ pcp_write(frontend, proc_create_time, strlen(proc_create_time)+1);
561
+ pcp_write(frontend, majorversion, strlen(majorversion)+1);
562
+ pcp_write(frontend, minorversion, strlen(minorversion)+1);
563
+ pcp_write(frontend, pool_counter, strlen(pool_counter)+1);
564
+ pcp_write(frontend, backend_id, strlen(backend_id)+1);
565
+ pcp_write(frontend, backend_pid, strlen(backend_pid)+1);
566
+ pcp_write(frontend, connected, strlen(connected)+1);
567
+ if (pcp_flush(frontend) < 0)
568
+ {
569
+ pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
570
+ free(pools);
571
+ exit(1);
572
+ }
573
+ }
574
+
575
+ pcp_write(frontend, "p", 1);
576
+ wsize = htonl(sizeof(fin_code) +
577
+ sizeof(int));
578
+ pcp_write(frontend, &wsize, sizeof(int));
579
+ pcp_write(frontend, fin_code, sizeof(fin_code));
580
+ if (pcp_flush(frontend) < 0)
581
+ {
582
+ pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
583
+ free(pools);
584
+ exit(1);
585
+ }
586
+
587
+ pool_debug("pcp_child: retrieved process information from shared memory");
588
+ free(pools);
589
+ }
590
+ break;
591
+ }
592
+
593
+ case 'S': /* SystemDB info */
594
+ {
595
+ int wsize;
596
+
597
+ SystemDBInfo *si = NULL;
598
+ si = pool_get_system_db_info();
599
+
600
+ if (si == NULL)
601
+ {
602
+ char code[] = "SystemDBNotDefined";
603
+
604
+ pcp_write(frontend, "e", 1);
605
+ wsize = htonl(sizeof(code) + sizeof(int));
606
+ pcp_write(frontend, &wsize, sizeof(int));
607
+ pcp_write(frontend, code, sizeof(code));
608
+ if (pcp_flush(frontend) < 0)
609
+ {
610
+ pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
611
+ exit(1);
612
+ }
613
+ }
614
+ else
615
+ {
616
+ /* first, send systemDB information */
617
+ char code[] = "SystemDBInfo";
618
+ char port[6];
619
+ char status[2];
620
+ char dist_def_num[16];
621
+ /* finally, indicate that all data is sent */
622
+ char fin_code[] = "CommandComplete";
623
+
624
+ /* since PCP clients can only see SystemDBInfo, set system_db_status from the shared memory */
625
+ si->system_db_status = SYSDB_STATUS;
626
+
627
+ snprintf(port, sizeof(port), "%d", si->port);
628
+ snprintf(status, sizeof(status), "%d", si->system_db_status);
629
+ snprintf(dist_def_num, sizeof(dist_def_num), "%d", si->dist_def_num);
630
+
631
+ pcp_write(frontend, "s", 1);
632
+ wsize = htonl(sizeof(code) +
633
+ strlen(si->hostname)+1 +
634
+ strlen(port)+1 +
635
+ strlen(si->user)+1 +
636
+ strlen(si->password)+1 +
637
+ strlen(si->schema_name)+1 +
638
+ strlen(si->database_name)+1 +
639
+ strlen(dist_def_num)+1 +
640
+ strlen(status)+1 +
641
+ sizeof(int));
642
+ pcp_write(frontend, &wsize, sizeof(int));
643
+ pcp_write(frontend, code, sizeof(code));
644
+ pcp_write(frontend, si->hostname, strlen(si->hostname)+1);
645
+ pcp_write(frontend, port, strlen(port)+1);
646
+ pcp_write(frontend, si->user, strlen(si->user)+1);
647
+ pcp_write(frontend, si->password, strlen(si->password)+1);
648
+ pcp_write(frontend, si->schema_name, strlen(si->schema_name)+1);
649
+ pcp_write(frontend, si->database_name, strlen(si->database_name)+1);
650
+ pcp_write(frontend, dist_def_num, strlen(dist_def_num)+1);
651
+ pcp_write(frontend, status, strlen(status)+1);
652
+ if (pcp_flush(frontend) < 0)
653
+ {
654
+ pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
655
+ exit(1);
656
+ }
657
+
658
+ /* second, send DistDefInfo if any */
659
+ if (si->dist_def_num > 0)
660
+ {
661
+ char dist_code[] = "DistDefInfo";
662
+ char col_num[16];
663
+ int col_list_total_len;
664
+ int type_list_total_len;
665
+ char *col_list = NULL;
666
+ char *type_list = NULL;
667
+ int col_list_offset;
668
+ int type_list_offset;
669
+ DistDefInfo *ddi;
670
+ int i, j;
671
+
672
+ for (i = 0; i < si->dist_def_num; i++)
673
+ {
674
+ ddi = &si->dist_def_slot[i];
675
+ snprintf(col_num, sizeof(col_num), "%d", ddi->col_num);
676
+
677
+ col_list_total_len = type_list_total_len = 0;
678
+ for (j = 0; j < ddi->col_num; j++)
679
+ {
680
+ col_list_total_len += strlen(ddi->col_list[j]) + 1;
681
+ type_list_total_len += strlen(ddi->type_list[j]) + 1;
682
+ }
683
+
684
+ col_list = (char *)malloc(col_list_total_len);
685
+ type_list = (char *)malloc(type_list_total_len);
686
+ if (col_list == NULL || type_list == NULL)
687
+ {
688
+ pool_error("pcp_child: malloc() failed. reason: %s", strerror(errno));
689
+ exit(1);
690
+ }
691
+
692
+ col_list_offset = type_list_offset = 0;
693
+ for (j = 0; j < ddi->col_num; j++)
694
+ {
695
+ snprintf(col_list + col_list_offset, strlen(ddi->col_list[j])+1,
696
+ "%s", ddi->col_list[j]);
697
+ snprintf(type_list + type_list_offset, strlen(ddi->type_list[j])+1,
698
+ "%s", ddi->type_list[j]);
699
+ col_list_offset += strlen(ddi->col_list[j]) + 1;
700
+ type_list_offset += strlen(ddi->type_list[j]) + 1;
701
+ }
702
+
703
+ pcp_write(frontend, "s", 1);
704
+ wsize = htonl(sizeof(dist_code) +
705
+ strlen(ddi->dbname)+1 +
706
+ strlen(ddi->schema_name)+1 +
707
+ strlen(ddi->table_name)+1 +
708
+ strlen(ddi->dist_key_col_name)+1 +
709
+ strlen(col_num)+1 +
710
+ col_list_total_len +
711
+ type_list_total_len +
712
+ strlen(ddi->dist_def_func)+1 +
713
+ sizeof(int));
714
+ pcp_write(frontend, &wsize, sizeof(int));
715
+ pcp_write(frontend, dist_code, sizeof(dist_code));
716
+ pcp_write(frontend, ddi->dbname, strlen(ddi->dbname)+1);
717
+ pcp_write(frontend, ddi->schema_name, strlen(ddi->schema_name)+1);
718
+ pcp_write(frontend, ddi->table_name, strlen(ddi->table_name)+1);
719
+ pcp_write(frontend, ddi->dist_key_col_name, strlen(ddi->dist_key_col_name)+1);
720
+ pcp_write(frontend, col_num, strlen(col_num)+1);
721
+ pcp_write(frontend, col_list, col_list_total_len);
722
+ pcp_write(frontend, type_list, type_list_total_len);
723
+ pcp_write(frontend, ddi->dist_def_func, strlen(ddi->dist_def_func)+1);
724
+ if (pcp_flush(frontend) < 0)
725
+ {
726
+ pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
727
+ exit(1);
728
+ }
729
+
730
+ free(col_list);
731
+ free(type_list);
732
+ }
733
+ }
734
+
735
+ pcp_write(frontend, "s", 1);
736
+ wsize = htonl(sizeof(fin_code) +
737
+ sizeof(int));
738
+ pcp_write(frontend, &wsize, sizeof(int));
739
+ pcp_write(frontend, fin_code, sizeof(fin_code));
740
+ if (pcp_flush(frontend) < 0)
741
+ {
742
+ pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
743
+ exit(1);
744
+ }
745
+
746
+ pool_debug("pcp_child: retrieved SystemDB information from shared memory");
747
+ }
748
+ break;
749
+ }
750
+
751
+ case 'W': /* watchdog info */
752
+ {
753
+ int wd_index;
754
+ int wsize;
755
+
756
+ WdInfo *wi = NULL;
757
+
758
+ if (!pool_config->use_watchdog)
759
+ {
760
+ char code[] = "watchdog not enabled";
761
+
762
+ pcp_write(frontend, "e", 1);
763
+ wsize = htonl(sizeof(code) + sizeof(int));
764
+ pcp_write(frontend, &wsize, sizeof(int));
765
+ pcp_write(frontend, code, sizeof(code));
766
+ if (pcp_flush(frontend) < 0)
767
+ {
768
+ pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
769
+ exit(1);
770
+ }
771
+
772
+ pool_debug("pcp_child: watcdhog not enabled");
773
+ break;
774
+ }
775
+
776
+ wd_index = atoi(buf);
777
+ wi = wd_get_watchdog_info(wd_index);
778
+
779
+ if (wi == NULL) {
780
+ char code[] = "Invalid watchdog index";
781
+
782
+ pcp_write(frontend, "e", 1);
783
+ wsize = htonl(sizeof(code) + sizeof(int));
784
+ pcp_write(frontend, &wsize, sizeof(int));
785
+ pcp_write(frontend, code, sizeof(code));
786
+ if (pcp_flush(frontend) < 0)
787
+ {
788
+ pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
789
+ exit(1);
790
+ }
791
+
792
+ pool_debug("pcp_child: invalid watchdog index");
793
+ }
794
+ else
795
+ {
796
+ char code[] = "CommandComplete";
797
+ char pgpool_port_str[6];
798
+ char wd_port_str[6];
799
+ char status[2];
800
+
801
+ snprintf(pgpool_port_str, sizeof(pgpool_port_str), "%d", wi->pgpool_port);
802
+ snprintf(wd_port_str, sizeof(wd_port_str), "%d", wi->wd_port);
803
+ snprintf(status, sizeof(status), "%d", wi->status);
804
+
805
+ pcp_write(frontend, "w", 1);
806
+ wsize = htonl(sizeof(code) +
807
+ strlen(wi->hostname)+1 +
808
+ strlen(pgpool_port_str)+1 +
809
+ strlen(wd_port_str)+1 +
810
+ strlen(status)+1 +
811
+ sizeof(int));
812
+ pcp_write(frontend, &wsize, sizeof(int));
813
+ pcp_write(frontend, code, sizeof(code));
814
+
815
+ pcp_write(frontend, wi->hostname, strlen(wi->hostname)+1);
816
+ pcp_write(frontend, pgpool_port_str, strlen(pgpool_port_str)+1);
817
+ pcp_write(frontend, wd_port_str, strlen(wd_port_str)+1);
818
+ pcp_write(frontend, status, strlen(status)+1);
819
+ if (pcp_flush(frontend) < 0)
820
+ {
821
+ pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
822
+ exit(1);
823
+ }
824
+
825
+ pool_debug("pcp_child: retrieved node information from shared memory");
826
+ }
827
+ break;
828
+ }
829
+
830
+ case 'D': /* detach node */
831
+ case 'd': /* detach node gracefully */
832
+ {
833
+ int node_id;
834
+ int wsize;
835
+ char code[] = "CommandComplete";
836
+ bool gracefully;
837
+
838
+ if (tos == 'D')
839
+ gracefully = false;
840
+ else
841
+ gracefully = true;
842
+
843
+ node_id = atoi(buf);
844
+ pool_debug("pcp_child: detaching Node ID %d", node_id);
845
+ pool_detach_node(node_id, gracefully);
846
+
847
+ pcp_write(frontend, "d", 1);
848
+ wsize = htonl(sizeof(code) + sizeof(int));
849
+ pcp_write(frontend, &wsize, sizeof(int));
850
+ pcp_write(frontend, code, sizeof(code));
851
+ if (pcp_flush(frontend) < 0)
852
+ {
853
+ pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
854
+ exit(1);
855
+ }
856
+ break;
857
+ }
858
+
859
+ case 'C': /* attach node */
860
+ {
861
+ int node_id;
862
+ int wsize;
863
+ char code[] = "CommandComplete";
864
+
865
+ node_id = atoi(buf);
866
+ pool_debug("pcp_child: attaching Node ID %d", node_id);
867
+ send_failback_request(node_id);
868
+
869
+ pcp_write(frontend, "c", 1);
870
+ wsize = htonl(sizeof(code) + sizeof(int));
871
+ pcp_write(frontend, &wsize, sizeof(int));
872
+ pcp_write(frontend, code, sizeof(code));
873
+ if (pcp_flush(frontend) < 0)
874
+ {
875
+ pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
876
+ exit(1);
877
+ }
878
+ break;
879
+ }
880
+
881
+ case 'T':
882
+ {
883
+ char mode = buf[0];
884
+ pid_t ppid = getppid();
885
+
886
+ if (mode == 's')
887
+ {
888
+ pool_debug("pcp_child: sending SIGTERM to the parent process(%d)", ppid);
889
+ kill(ppid, SIGTERM);
890
+ }
891
+ else if (mode == 'f')
892
+ {
893
+ pool_debug("pcp_child: sending SIGINT to the parent process(%d)", ppid);
894
+ kill(ppid, SIGINT);
895
+ }
896
+ else if (mode == 'i')
897
+ {
898
+ pool_debug("pcp_child: sending SIGQUIT to the parent process(%d)", ppid);
899
+ kill(ppid, SIGQUIT);
900
+ }
901
+ else
902
+ {
903
+ pool_debug("pcp_child: invalid shutdown mode %c", mode);
904
+ }
905
+
906
+ break;
907
+ }
908
+
909
+ case 'O': /* recovery request */
910
+ {
911
+ int node_id;
912
+ int wsize;
913
+ char code[] = "CommandComplete";
914
+ int r;
915
+
916
+ node_id = atoi(buf);
917
+
918
+ if ( (node_id < 0) || (node_id >= pool_config->backend_desc->num_backends) )
919
+ {
920
+ char code[] = "NodeIdOutOfRange";
921
+ pool_error("pcp_child: node id %d is not valid", node_id);
922
+ pcp_write(frontend, "e", 1);
923
+ wsize = htonl(sizeof(code) + sizeof(int));
924
+ pcp_write(frontend, &wsize, sizeof(int));
925
+ pcp_write(frontend, code, sizeof(code));
926
+ if (pcp_flush(frontend) < 0)
927
+ {
928
+ pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
929
+ exit(1);
930
+ }
931
+ exit(1);
932
+ }
933
+
934
+ if ((!REPLICATION &&
935
+ !(MASTER_SLAVE &&
936
+ !strcmp(pool_config->master_slave_sub_mode, MODE_STREAMREP))) ||
937
+ (MASTER_SLAVE &&
938
+ !strcmp(pool_config->master_slave_sub_mode, MODE_STREAMREP) &&
939
+ node_id == PRIMARY_NODE_ID))
940
+ {
941
+ int len;
942
+ char *msg;
943
+
944
+ if (MASTER_SLAVE && !strcmp(pool_config->master_slave_sub_mode, MODE_STREAMREP))
945
+ msg = "primary server cannot be recovered by online recovery.";
946
+ else
947
+ msg = "recovery request is accepted only in replication mode or stereaming replication mode. ";
948
+
949
+ len = strlen(msg)+1;
950
+ pcp_write(frontend, "e", 1);
951
+ wsize = htonl(sizeof(int) + len);
952
+ pcp_write(frontend, &wsize, sizeof(int));
953
+ pcp_write(frontend, msg, len);
954
+ }
955
+ else
956
+ {
957
+ pool_debug("pcp_child: start online recovery");
958
+
959
+ r = start_recovery(node_id);
960
+ finish_recovery();
961
+
962
+ if (r == 0) /* success */
963
+ {
964
+ pcp_write(frontend, "c", 1);
965
+ wsize = htonl(sizeof(code) + sizeof(int));
966
+ pcp_write(frontend, &wsize, sizeof(int));
967
+ pcp_write(frontend, code, sizeof(code));
968
+ }
969
+ else
970
+ {
971
+ int len = strlen("recovery failed") + 1;
972
+ pcp_write(frontend, "e", 1);
973
+ wsize = htonl(sizeof(int) + len);
974
+ pcp_write(frontend, &wsize, sizeof(int));
975
+ pcp_write(frontend, "recovery failed", len);
976
+ }
977
+ }
978
+ if (pcp_flush(frontend) < 0)
979
+ {
980
+ pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
981
+ exit(1);
982
+ }
983
+ }
984
+ break;
985
+
986
+ case 'B': /* status request*/
987
+ {
988
+ int nrows = 0;
989
+ POOL_REPORT_CONFIG *status = get_config(&nrows);
990
+ int len = 0;
991
+ /* First, send array size of connection_info */
992
+ char arr_code[] = "ArraySize";
993
+ char code[] = "ProcessConfig";
994
+ /* Finally, indicate that all data is sent */
995
+ char fin_code[] = "CommandComplete";
996
+
997
+ pcp_write(frontend, "b", 1);
998
+ len = htonl(sizeof(arr_code) + sizeof(int) + sizeof(int));
999
+ pcp_write(frontend, &len, sizeof(int));
1000
+ pcp_write(frontend, arr_code, sizeof(arr_code));
1001
+ len = htonl(nrows);
1002
+ pcp_write(frontend, &len, sizeof(int));
1003
+
1004
+ if (pcp_flush(frontend) < 0)
1005
+ {
1006
+ pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
1007
+ exit(1);
1008
+ }
1009
+
1010
+ for (i = 0; i < nrows; i++)
1011
+ {
1012
+ pcp_write(frontend, "b", 1);
1013
+ len = htonl(sizeof(int)
1014
+ + sizeof(code)
1015
+ + strlen(status[i].name) + 1
1016
+ + strlen(status[i].value) + 1
1017
+ + strlen(status[i].desc) + 1
1018
+ );
1019
+
1020
+ pcp_write(frontend, &len, sizeof(int));
1021
+ pcp_write(frontend, code, sizeof(code));
1022
+ pcp_write(frontend, status[i].name, strlen(status[i].name)+1);
1023
+ pcp_write(frontend, status[i].value, strlen(status[i].value)+1);
1024
+ pcp_write(frontend, status[i].desc, strlen(status[i].desc)+1);
1025
+ }
1026
+
1027
+ pcp_write(frontend, "b", 1);
1028
+ len = htonl(sizeof(fin_code) + sizeof(int));
1029
+ pcp_write(frontend, &len, sizeof(int));
1030
+ pcp_write(frontend, fin_code, sizeof(fin_code));
1031
+ if (pcp_flush(frontend) < 0)
1032
+ {
1033
+ pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
1034
+ exit(1);
1035
+ }
1036
+
1037
+ free(status);
1038
+
1039
+ pool_debug("pcp_child: retrieved status information");
1040
+ break;
1041
+ }
1042
+
1043
+ case 'J': /* promote node */
1044
+ case 'j': /* promote node gracefully */
1045
+ {
1046
+ int node_id;
1047
+ int wsize;
1048
+ char code[] = "CommandComplete";
1049
+ bool gracefully;
1050
+
1051
+ if (tos == 'J')
1052
+ gracefully = false;
1053
+ else
1054
+ gracefully = true;
1055
+
1056
+ node_id = atoi(buf);
1057
+ if ( (node_id < 0) || (node_id >= pool_config->backend_desc->num_backends) )
1058
+ {
1059
+ char code[] = "NodeIdOutOfRange";
1060
+ pool_error("pcp_child: node id %d is not valid", node_id);
1061
+ pcp_write(frontend, "e", 1);
1062
+ wsize = htonl(sizeof(code) + sizeof(int));
1063
+ pcp_write(frontend, &wsize, sizeof(int));
1064
+ pcp_write(frontend, code, sizeof(code));
1065
+ if (pcp_flush(frontend) < 0)
1066
+ {
1067
+ pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
1068
+ exit(1);
1069
+ }
1070
+ exit(1);
1071
+ }
1072
+ /* promoting node is reserved to Streaming Replication */
1073
+ if (!MASTER_SLAVE || (strcmp(pool_config->master_slave_sub_mode, MODE_STREAMREP) != 0))
1074
+ {
1075
+ char code[] = "NotInStreamingReplication";
1076
+ pool_error("pcp_child: not in streaming replication mode, can't promote node id %d", node_id);
1077
+ pcp_write(frontend, "e", 1);
1078
+ wsize = htonl(sizeof(code) + sizeof(int));
1079
+ pcp_write(frontend, &wsize, sizeof(int));
1080
+ pcp_write(frontend, code, sizeof(code));
1081
+ if (pcp_flush(frontend) < 0)
1082
+ {
1083
+ pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
1084
+ exit(1);
1085
+ }
1086
+ exit(1);
1087
+ }
1088
+
1089
+ if (node_id == PRIMARY_NODE_ID)
1090
+ {
1091
+ char code[] = "NodeIdAlreadyPrimary";
1092
+ pool_error("pcp_child: specified node is already primary node, can't promote node id %d", node_id);
1093
+ pcp_write(frontend, "e", 1);
1094
+ wsize = htonl(sizeof(code) + sizeof(int));
1095
+ pcp_write(frontend, &wsize, sizeof(int));
1096
+ pcp_write(frontend, code, sizeof(code));
1097
+ if (pcp_flush(frontend) < 0)
1098
+ {
1099
+ pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
1100
+ exit(1);
1101
+ }
1102
+ exit(1);
1103
+ }
1104
+
1105
+ pool_debug("pcp_child: promoting Node ID %d", node_id);
1106
+ pool_promote_node(node_id, gracefully);
1107
+
1108
+ pcp_write(frontend, "d", 1);
1109
+ wsize = htonl(sizeof(code) + sizeof(int));
1110
+ pcp_write(frontend, &wsize, sizeof(int));
1111
+ pcp_write(frontend, code, sizeof(code));
1112
+ if (pcp_flush(frontend) < 0)
1113
+ {
1114
+ pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
1115
+ exit(1);
1116
+ }
1117
+ break;
1118
+ }
1119
+
1120
+ case 'F':
1121
+ pool_debug("pcp_child: stop online recovery");
1122
+ break;
1123
+
1124
+ case 'X': /* disconnect */
1125
+ pool_debug("pcp_child: client disconnecting. close connection");
1126
+ authenticated = 0;
1127
+ pcp_close(frontend);
1128
+ frontend = NULL;
1129
+ break;
1130
+
1131
+ default:
1132
+ pool_error("pcp_child: unknown packet type %c received", tos);
1133
+ exit(1);
1134
+ }
1135
+
1136
+ free(buf);
1137
+ buf = NULL;
1138
+
1139
+ /* seems ok. cancel idle check timer */
1140
+ pool_signal(SIGALRM, SIG_IGN);
1141
+ }
1142
+
1143
+ exit(0);
1144
+ }
1145
+
1146
+ static RETSIGTYPE
1147
+ die(int sig)
1148
+ {
1149
+ pcp_exit_request = 1;
1150
+
1151
+ pool_debug("PCP child receives shutdown request signal %d", sig);
1152
+
1153
+ switch (sig)
1154
+ {
1155
+ case SIGTERM: /* smart shutdown */
1156
+ case SIGINT: /* fast shutdown */
1157
+ case SIGQUIT: /* immediate shutdown */
1158
+ exit(0);
1159
+ break;
1160
+ default:
1161
+ break;
1162
+ }
1163
+
1164
+ /* send_frontend_exits(); */
1165
+
1166
+ exit(0);
1167
+ }
1168
+
1169
+ static RETSIGTYPE
1170
+ wakeup_handler(int sig)
1171
+ {
1172
+ pcp_wakeup_request = 1;
1173
+ }
1174
+
1175
+ static RETSIGTYPE
1176
+ restart_handler(int sig)
1177
+ {
1178
+ pcp_restart_request = 1;
1179
+ }
1180
+
1181
+ static PCP_CONNECTION *
1182
+ pcp_do_accept(int unix_fd, int inet_fd)
1183
+ {
1184
+ PCP_CONNECTION *pc = NULL;
1185
+
1186
+ fd_set readmask;
1187
+ int fds;
1188
+
1189
+ struct sockaddr addr;
1190
+ socklen_t addrlen;
1191
+ int fd = 0;
1192
+ int afd;
1193
+ int inet = 0;
1194
+
1195
+ set_ps_display("PCP: wait for connection request", false);
1196
+
1197
+ FD_ZERO(&readmask);
1198
+ FD_SET(unix_fd, &readmask);
1199
+ if (inet_fd)
1200
+ FD_SET(inet_fd, &readmask);
1201
+
1202
+ fds = select(Max(unix_fd, inet_fd)+1, &readmask, NULL, NULL, NULL);
1203
+
1204
+ if (fds == -1)
1205
+ {
1206
+ if (errno == EAGAIN || errno == EINTR)
1207
+ return NULL;
1208
+
1209
+ pool_error("pcp_child: select() failed. reason: %s", strerror(errno));
1210
+ return NULL;
1211
+ }
1212
+
1213
+ if (FD_ISSET(unix_fd, &readmask))
1214
+ {
1215
+ fd = unix_fd;
1216
+ }
1217
+
1218
+ if (FD_ISSET(inet_fd, &readmask))
1219
+ {
1220
+ fd = inet_fd;
1221
+ inet++;
1222
+ }
1223
+
1224
+ addrlen = sizeof(addr);
1225
+
1226
+ afd = accept(fd, &addr, &addrlen);
1227
+ if (afd < 0)
1228
+ {
1229
+ /*
1230
+ * "Resource temporarily unavailable" (EAGAIN or EWOULDBLOCK)
1231
+ * can be silently ignored.
1232
+ */
1233
+ if (errno != EAGAIN && errno != EWOULDBLOCK)
1234
+ pool_error("pcp_child: accept() failed. reason: %s", strerror(errno));
1235
+ return NULL;
1236
+ }
1237
+
1238
+ if (pcp_got_sighup)
1239
+ {
1240
+ pool_get_config(get_config_file_name(), RELOAD_CONFIG);
1241
+ pcp_got_sighup = 0;
1242
+ }
1243
+
1244
+ pool_debug("I am PCP %d accept fd %d", getpid(), afd);
1245
+
1246
+ if (inet)
1247
+ {
1248
+ int on = 1;
1249
+
1250
+ if (setsockopt(afd, IPPROTO_TCP, TCP_NODELAY,
1251
+ (char *) &on,
1252
+ sizeof(on)) < 0)
1253
+ {
1254
+ pool_error("pcp_child: setsockopt() failed: %s", strerror(errno));
1255
+ close(afd);
1256
+ return NULL;
1257
+ }
1258
+ if (setsockopt(afd, SOL_SOCKET, SO_KEEPALIVE,
1259
+ (char *) &on,
1260
+ sizeof(on)) < 0)
1261
+ {
1262
+ pool_error("pcp_child: setsockopt() failed: %s", strerror(errno));
1263
+ close(afd);
1264
+ return NULL;
1265
+ }
1266
+ }
1267
+
1268
+ if ((pc = pcp_open(afd)) == NULL)
1269
+ {
1270
+ close(afd);
1271
+ return NULL;
1272
+ }
1273
+ return pc;
1274
+ }
1275
+
1276
+ /*
1277
+ * unset non-block flag
1278
+ */
1279
+ static void
1280
+ unset_nonblock(int fd)
1281
+ {
1282
+ int var;
1283
+
1284
+ /* set fd to non-blocking */
1285
+ var = fcntl(fd, F_GETFL, 0);
1286
+ if (var == -1)
1287
+ {
1288
+ pool_error("pcp_child: fcntl failed. %s", strerror(errno));
1289
+ exit(1);
1290
+ }
1291
+ if (fcntl(fd, F_SETFL, var & ~O_NONBLOCK) == -1)
1292
+ {
1293
+ pool_error("pcp_child: fcntl failed. %s", strerror(errno));
1294
+ exit(1);
1295
+ }
1296
+ }
1297
+
1298
+ /*
1299
+ * see if received username and password matches with one in the file
1300
+ */
1301
+ static int
1302
+ user_authenticate(char *buf, char *passwd_file, char *salt, int salt_len)
1303
+ {
1304
+ FILE *fp = NULL;
1305
+ char packet_username[MAX_USER_PASSWD_LEN+1];
1306
+ char packet_password[MAX_USER_PASSWD_LEN+1];
1307
+ char encrypt_buf[(MD5_PASSWD_LEN+1)*2];
1308
+ char file_username[MAX_USER_PASSWD_LEN+1];
1309
+ char file_password[MAX_USER_PASSWD_LEN+1];
1310
+ char *index = NULL;
1311
+ static char line[MAX_FILE_LINE_LEN+1];
1312
+ int i, len;
1313
+
1314
+ /* strcpy() should be OK, but use strncpy() to be extra careful */
1315
+ strncpy(packet_username, buf, MAX_USER_PASSWD_LEN);
1316
+ index = (char *) memchr(buf, '\0', MAX_USER_PASSWD_LEN) + 1;
1317
+ if (index == NULL)
1318
+ {
1319
+ pool_debug("pcp_child: error while reading authentication packet");
1320
+ return 0;
1321
+ }
1322
+ strncpy(packet_password, index, MAX_USER_PASSWD_LEN);
1323
+
1324
+ fp = fopen(passwd_file, "r");
1325
+ if (fp == NULL)
1326
+ {
1327
+ pool_error("pcp_child: could not open %s. reason: %s", passwd_file, strerror(errno));
1328
+ return 0;
1329
+ }
1330
+
1331
+ /* for now, I don't care if duplicate username exists in the config file */
1332
+ while ((fgets(line, MAX_FILE_LINE_LEN, fp)) != NULL)
1333
+ {
1334
+ i = 0;
1335
+ len = 0;
1336
+
1337
+ if (line[0] == '\n')
1338
+ continue;
1339
+ if (line[0] == '#')
1340
+ continue;
1341
+
1342
+ while (line[i] != ':')
1343
+ {
1344
+ len++;
1345
+ if (++i > MAX_USER_PASSWD_LEN)
1346
+ {
1347
+ pool_error("pcp_child: user name in %s exceeds %d", passwd_file, MAX_USER_PASSWD_LEN);
1348
+ fclose(fp);
1349
+ return 0;
1350
+ }
1351
+ }
1352
+ memcpy(file_username, line, len);
1353
+ file_username[len] = '\0';
1354
+
1355
+ if (strcmp(packet_username, file_username) != 0)
1356
+ continue;
1357
+
1358
+ i++;
1359
+ len = 0;
1360
+ while (line[i] != '\n' && line[i] != '\0')
1361
+ {
1362
+ len++;
1363
+ if (++i > MAX_USER_PASSWD_LEN)
1364
+ {
1365
+ pool_error("pcp_child: password in %s exceeds %d", passwd_file, MAX_USER_PASSWD_LEN);
1366
+ fclose(fp);
1367
+ return 0;
1368
+ }
1369
+ }
1370
+
1371
+ memcpy(file_password, line+strlen(file_username)+1, len);
1372
+ file_password[len] = '\0';
1373
+
1374
+ pool_md5_encrypt(file_password, file_username, strlen(file_username),
1375
+ encrypt_buf + MD5_PASSWD_LEN + 1);
1376
+ encrypt_buf[(MD5_PASSWD_LEN+1)*2-1] = '\0';
1377
+
1378
+ pool_md5_encrypt(encrypt_buf+MD5_PASSWD_LEN+1, salt, salt_len,
1379
+ encrypt_buf);
1380
+ encrypt_buf[MD5_PASSWD_LEN] = '\0';
1381
+
1382
+ if (strcmp(encrypt_buf, packet_password) == 0)
1383
+ {
1384
+ fclose(fp);
1385
+ return 1;
1386
+ }
1387
+ }
1388
+
1389
+ fclose(fp);
1390
+ return 0;
1391
+ }
1392
+
1393
+ /* SIGHUP handler */
1394
+ static RETSIGTYPE reload_config_handler(int sig)
1395
+ {
1396
+ pcp_got_sighup = 1;
1397
+ }
1398
+
1399
+ /* Dedatch a node */
1400
+ static int pool_detach_node(int node_id, bool gracefully)
1401
+ {
1402
+ if (!gracefully)
1403
+ {
1404
+ notice_backend_error(node_id); /* send failover request */
1405
+ return 0;
1406
+ }
1407
+
1408
+ /*
1409
+ * Wait until all frontends exit
1410
+ */
1411
+ *InRecovery = RECOVERY_DETACH; /* This wiil ensure that new incoming
1412
+ * connection requests are blocked */
1413
+
1414
+ if (wait_connection_closed())
1415
+ {
1416
+ /* wait timed out */
1417
+ finish_recovery();
1418
+ return -1;
1419
+ }
1420
+
1421
+ /*
1422
+ * Now all frontends have gone. Let's do failover.
1423
+ */
1424
+ notice_backend_error(node_id); /* send failover request */
1425
+
1426
+ /*
1427
+ * Wait for failover completed.
1428
+ */
1429
+ pcp_wakeup_request = 0;
1430
+
1431
+ while (!pcp_wakeup_request)
1432
+ {
1433
+ struct timeval t = {1, 0};
1434
+ select(0, NULL, NULL, NULL, &t);
1435
+ }
1436
+ pcp_wakeup_request = 0;
1437
+
1438
+ /*
1439
+ * Start to accept incoming connections and send SIGUSR2 to pgpool
1440
+ * parent to distribute SIGUSR2 all pgpool children.
1441
+ */
1442
+ finish_recovery();
1443
+
1444
+ return 0;
1445
+ }
1446
+
1447
+ /* Promote a node */
1448
+ static int pool_promote_node(int node_id, bool gracefully)
1449
+ {
1450
+ if (!gracefully)
1451
+ {
1452
+ promote_backend(node_id); /* send promote request */
1453
+ return 0;
1454
+ }
1455
+
1456
+ /*
1457
+ * Wait until all frontends exit
1458
+ */
1459
+ *InRecovery = RECOVERY_PROMOTE; /* This wiil ensure that new incoming
1460
+ * connection requests are blocked */
1461
+
1462
+ if (wait_connection_closed())
1463
+ {
1464
+ /* wait timed out */
1465
+ finish_recovery();
1466
+ return -1;
1467
+ }
1468
+
1469
+ /*
1470
+ * Now all frontends have gone. Let's do failover.
1471
+ */
1472
+ promote_backend(node_id); /* send promote request */
1473
+
1474
+ /*
1475
+ * Wait for failover completed.
1476
+ */
1477
+ pcp_wakeup_request = 0;
1478
+
1479
+ while (!pcp_wakeup_request)
1480
+ {
1481
+ struct timeval t = {1, 0};
1482
+ select(0, NULL, NULL, NULL, &t);
1483
+ }
1484
+ pcp_wakeup_request = 0;
1485
+
1486
+ /*
1487
+ * Start to accept incoming connections and send SIGUSR2 to pgpool
1488
+ * parent to distribute SIGUSR2 all pgpool children.
1489
+ */
1490
+ finish_recovery();
1491
+
1492
+ return 0;
1493
+ }