pgpool2.git / summary / log / commit / refs
commit 4a208641709322255d4be3da4b18e155a2f5b25f
Author: Tatsuo Ishii <ishii@postgresql.org>
Date: Wed Aug 06 07:31:11 2014 +0000
Change pgpool_status file format to ASCII.
Changing to ASCII will bring some benefits:
- Easy to check the file contents by using ordinary text tools
- Easy to modify the contents. This is useful if you set longer health check time out.
For example, newly added backend will cause failover and it might take long time
until the procedure finishes. By editing pgpool_status to set the new node
status as down, you could avoid health checking for the node.
Note that the new file reader understands old binary format
pgpool_status for easy migration from older versions of pgpool-II.
doc/pgpool-en.html | 22 +++++++++-
doc/pgpool-ja.html | 21 +++++++++
src/main/pgpool_main.c | 117 ++++++++++++++++++++++++++++++++++++++++++-------
3 files changed, 143 insertions(+), 17 deletions(-)
diff --git a/doc/pgpool-en.html b/doc/pgpool-en.html
index fd60cc149..b61e62403 100644
--- a/doc/pgpool-en.html
+++ b/doc/pgpool-en.html
@@ -3195,7 +3195,27 @@ pgpool [-f config_file][-F pcp_config_file] [-m {s[mart]|f[ast]|i[mmediate]}] st
</table>
<p>
-pgpool records backend status into the [logdir]/pgpool_status file. When pgpool
+pgpool records backend status into the [logdir]/pgpool_status file.
+From pgpool-II 3.4.0 the file format of pgpool_status has been changed: it's an ordinary ASCII file and you can read and edit the contents by using your favorite text editor.
+For example, if you add new backend and restart pgpool-II, you might have wait for long time until pgpool-II detects the new backend and performs failover.
+By editing pgpool_status to set the backend to be down status, you could avoid the situation because pgpool-II's health check skips down nodes.
+Each line in the file corresponding to each backend node status.
+The first backend status is the first line, and and the seconds backend status is the second line and so on.
+The backend status is represented by any of "up", "down", "unused" (case ignored).
+Here is an example of pgpool_status:
+<pre>
+up
+down
+up
+</pre>
+</p>
+
+<p>
+Note that pre-3.4.0 pgpool-II uses binary format pgpool_status. Pgpool-II 3.4.0 or later can read the file as well. However pre-3.4.0 pgpool-II cannot read ASCII format pgpool_status file.
+</p>
+
+<p>
+When pgpool
restarts, it reads this file and restores the backend status. This will prevent
a difference in data among DB nodes which might be caused by following scenario:
</p>
diff --git a/doc/pgpool-ja.html b/doc/pgpool-ja.html
index d1a1a7ad3..c87a8f9af 100644
--- a/doc/pgpool-ja.html
+++ b/doc/pgpool-ja.html
@@ -3295,6 +3295,27 @@ pgpool [-f config_file][-F pcp_config_file] [-m {s[mart]|f[ast]|i[mmediate]}] st
<p id="pool_status_file">
pgpoolが停止すると、[logdir]/pgpool_statusというファイルにバックエンドの状態を書き込みます。
+pgpool-II 3.4.0から、ファイルフォーマットが変更され、ASCIIファイルになりました。
+ですから普通のエディタでこのファイルを参照したり編集ができます。
+たとえば、pgpool.confを編集して新しいバックエンドを追加、再起動した際にpgpool-IIが新しいバックエンドの死活を判定するまで待ちたくない場合、あらかじめそのバックエンドを"down"状態に編集しておくことができます。
+pgpool_statusの各行はそれぞれのバックエンドの状態に対応します。
+1行目は最初のバックエンド、2行目は2番目のバックエンドというような具合です。
+バックエンドの状態は"up", "down", "unused"のどれかです(大文字小文字は無視されます)。
+例を示します。
+<pre>
+up
+down
+up
+</pre>
+</p>
+
+<p>
+なお、pgpool-II 3.4.0より前のpgpool-IIはバイナリ形式のpgpool_status使用します。
+pgpool-II 3.4.0以降では、バイナリ形式のファイルも読むことができます。
+しかしpgpool-II 3.4.0より前のpgpool-IIはASCII形式のpgpool_statusを読むことはできません。
+</p>
+
+<p>
次回pgpoolが起動したときにこのファイルが存在すると、バックエンドの状態をそこから復元します。
これによって、
</p>
diff --git a/src/main/pgpool_main.c b/src/main/pgpool_main.c
index c123ff1ed..b1da9ab59 100644
--- a/src/main/pgpool_main.c
+++ b/src/main/pgpool_main.c
@@ -2423,6 +2423,7 @@ static int read_status_file(bool discard_status)
char fnamebuf[POOLMAXPATHLEN];
int i;
bool someone_wakeup = false;
+ bool is_old_format;
snprintf(fnamebuf, sizeof(fnamebuf), "%s/%s", pool_config->logdir, STATUS_FILE_NAME);
fd = fopen(fnamebuf, "r");
@@ -2452,28 +2453,94 @@ static int read_status_file(bool discard_status)
return 0;
}
- if (fread(&backend_rec, 1, sizeof(backend_rec), fd) != sizeof(backend_rec))
+ /*
+ * Frist try out with old format file.
+ */
+ is_old_format = true;
+
+ if (fread(&backend_rec, 1, sizeof(backend_rec), fd) == sizeof(backend_rec))
{
- pool_error("Could not read backend status file as %s. reason: %s",
- fnamebuf, strerror(errno));
+ /* It's likely old binary format status file */
+ for (i=0;i< pool_config->backend_desc->num_backends;i++)
+ {
+ if (backend_rec.status[i] == CON_DOWN)
+ {
+ BACKEND_INFO(i).backend_status = CON_DOWN;
+ ereport(LOG,
+ (errmsg("read_status_file: %d th backend is set to down status", i)));
+ }
+ else if (BACKEND_INFO(i).backend_status == CON_CONNECT_WAIT ||
+ BACKEND_INFO(i).backend_status == CON_UP)
+ {
+ BACKEND_INFO(i).backend_status = CON_CONNECT_WAIT;
+ someone_wakeup = true;
+ }
+ else
+ {
+ /* It seems it's not an old binary format status file */
+ is_old_format = false;
+ break;
+ }
+ }
fclose(fd);
- return -1;
}
- fclose(fd);
+ else
+ is_old_format = false;
- for (i=0;i< pool_config->backend_desc->num_backends;i++)
+ if (!is_old_format)
{
- if (backend_rec.status[i] == CON_DOWN)
+ /*
+ * Fall back to new ascii format file.
+ * the format looks like(case is ignored):
+ *
+ * up|down|unused
+ * UP|down|unused
+ * :
+ * :
+ */
+#define MAXLINE 10
+ char readbuf[MAXLINE];
+
+ fd = fopen(fnamebuf, "r");
+ if (!fd)
{
- BACKEND_INFO(i).backend_status = CON_DOWN;
ereport(LOG,
- (errmsg("read_status_file: %d th backend is set to down status", i)));
+ (errmsg("Backend status file %s does not exist", fnamebuf)));
+ return -1;
}
- else
+
+ for (i=0;i<MAX_NUM_BACKENDS;i++)
{
- BACKEND_INFO(i).backend_status = CON_CONNECT_WAIT;
- someone_wakeup = true;
+ BACKEND_INFO(i).backend_status = CON_UNUSED;
}
+
+ for (i=0;;i++)
+ {
+ readbuf[MAXLINE-1] = '\0';
+ if (fgets(readbuf, MAXLINE-1, fd) == 0)
+ break;
+
+ if (!strncasecmp("up", readbuf, 2))
+ {
+ BACKEND_INFO(i).backend_status = CON_UP;
+ someone_wakeup = true;
+ }
+ else if (!strncasecmp("down", readbuf, 4))
+ {
+ BACKEND_INFO(i).backend_status = CON_DOWN;
+ ereport(LOG,
+ (errmsg("read_status_file: %d th backend is set to down status", i)));
+ }
+ else if (!strncasecmp("unused", readbuf, 6))
+ {
+ BACKEND_INFO(i).backend_status = CON_UNUSED;
+ }
+ else
+ {
+ pool_error("read_status_file: %d th backend status is invalid (%s). ignored", i, readbuf);
+ }
+ }
+ fclose(fd);
}
/*
@@ -2507,15 +2574,33 @@ static int write_status_file()
return -1;
}
- memset(&backend_rec, 0, sizeof(backend_rec));
if(pool_config)
{
+ char buf[10];
+
for (i=0;i< pool_config->backend_desc->num_backends;i++)
{
- backend_rec.status[i] = BACKEND_INFO(i).backend_status;
- }
+ char* status;
+
+ if (BACKEND_INFO(i).backend_status == CON_UP ||
+ BACKEND_INFO(i).backend_status == CON_CONNECT_WAIT)
+ status = "up";
+ else if (BACKEND_INFO(i).backend_status == CON_DOWN)
+ status = "down";
+ else
+ status = "unused";
+
+ sprintf(buf, "%s\n", status);
+ if (fwrite(buf, 1, strlen(buf), fd) != strlen(buf))
+ {
+ pool_error("Could not write backend status file as %s. reason: %s",
+ fnamebuf, strerror(errno));
+ fclose(fd);
+ return -1;
+ }
+ }
- if (fwrite(&backend_rec, 1, sizeof(backend_rec), fd) != sizeof(backend_rec))
+ if (fflush(fd) != 0)
{
pool_error("Could not write backend status file as %s. reason: %s",
fnamebuf, strerror(errno));
[parent: ded3fa823f59]