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
@@ -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
+ }