PostgreSQL/開発

概要

postgresql-latch-overview.png

定義

変数,エイリアス

マクロ

列挙型

構造体/共用体

Latch

番号データ型フィールド説明
1sig_atomic_tis_setLatchがセットされているか
2boolis_sharedLatchが他のプロセスと共有された状態か。
初期時はこの状態。バックエンドが起動するとバックエンドローカルなLatchに設定される。
参考InitPostmasterChild() - https://git.postgresql.org/gitweb/
3intowner_pidLatchの所有者
4HANDLEevent監視するイベント(WIN32)

関数

InitializeLatchSupport

extern void InitializeLatchSupport(void);

参考InitPostmasterChild() - https://git.postgresql.org/gitweb/

InitLatch

// 引数1:Latchの参照
extern void InitLatch(volatile Latch *latch);

サンプル 独自のLatchを使う(通常はMyLatchがあるのでそれを使う)

volatile Latch OriginalLatch;

void myworker()
{
	InitLatch(&OriginalLatch);

	int rc;

	rc = WaitLatch(&OriginalLatch,
		       WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
		       10 * 1000L,
		       PG_WAIT_EXTENSION);

	ResetLatch(&OriginalLatch);

	if (rc & WL_POSTMASTER_DEATH)
		proc_exit(1);

	/* Do something */
}

InitSharedLatch

// 引数1:Latchの参照
extern void InitSharedLatch(volatile Latch *latch);

参考InitSharedLatch() - https://git.postgresql.org/gitweb/

OwnLatch

// 引数1:Latchの参照
extern void OwnLatch(volatile Latch *latch);

DisownLatch

// 引数1:Latchの参照
extern void DisownLatch(volatile Latch *latch);

SetLatch

// 引数1:Latchの参照
extern void SetLatch(volatile Latch *latch);

参考SetLatch() - https://git.postgresql.org/gitweb/

サンプル シグナルハンドラー内でSetLatchして待ち状態のプロセスをwake upさせる。

static volatile sig_atomic_t got_sighup = false;

static void
myworker_sighup(SIGNAL_ARGS)
{
	int save_errno = errno;

	got_sighup = true;
	SetLatch(MyLatch); // waked up the waiting process

	errno = save_errno;
}


void myworker()
{
	int rc;
	/* Waiting for the latch to be expired */
	rc = WaitLatch(MyLatch,
		       WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
		       10 * 1000L,
		       PG_WAIT_EXTENSION);

	ResetLatch(MyLatch);

	if (rc & WL_POSTMASTER_DEATH)
		proc_exit(1);

	/* Do something */
}

ResetLatch

// 引数1:Latchの参照
extern void ResetLatch(volatile Latch *latch);

CreateWaitEventSet

// 引数1:メモリコンテキスト
// 引数2:イベント数
// 戻り値:待ち受けイベントに関する情報を格納するWaitEventSet構造体のポインタ
extern WaitEventSet *CreateWaitEventSet(MemoryContext context, int nevents);

サンプル

void event_set_sample()
{
	int ret = 0;
	int rc;
	WaitEvent	event;

	/* Allocate memory for WaitEventSet which can keep a maximum of 3 events */
	WaitEventSet *set = CreateWaitEventSet(CurrentMemoryContext, 3);

	/* Add an event for WL_LATCH_SET */
	AddWaitEventToSet(set, WL_LATCH_SET, PGINVALID_SOCKET,
					  MyLatch, NULL);

	/* Wait for a event to occur. */
	rc = WaitEventSetWait(set, 10 * 1000L, &event, 1, PG_WAIT_EXTENSION);

	/* Check event flag */
	if (rc == 0)
		ret |= WL_TIMEOUT;
	else
	{
		ret |= event.events & (WL_LATCH_SET |
				       WL_POSTMASTER_DEATH |
				       WL_SOCKET_MASK);
	}

	/* Free memory */
	FreeWaitEventSet(set);
}

FreeWaitEventSet

// 引数1:イベントセット構造体(WaitEventSet)の参照
extern void FreeWaitEventSet(WaitEventSet *set);

AddWaitEventToSet

// 引数1:イベントセット構造体(WaitEventSet)の参照
// 引数2:追加するイベント
// 引数3:監視するファイルディスクリプタ。
//        WL_LATCH_SETまたはWL_POSTMASTER_DEATHの時は、通常PGINVALID_SOCKETをセットする。
// 引数4:イベントに紐付けられるLatchの参照
// 引数5:イベントに紐付けられる、ユーザー指定可能な任意データ
// 戻り値:
extern int AddWaitEventToSet(WaitEventSet *set, uint32 events, pgsocket fd, Latch *latch, void *user_data);

ModifyWaitEvent

// 引数1:イベントセット構造体(WaitEventSet)の参照
// 引数2:イベントセット内でのイベントのposition(配列のインデックス)
// 引数3:書き換え後のイベント
// 引数4:イベントに紐付けられるLatchの参照
extern void ModifyWaitEvent(WaitEventSet *set, int pos, uint32 events, Latch *latch);

WaitEventSetWait

// 引数1:イベントセット構造体(WaitEventSet)の参照
// 引数2:タイムアウト(msec)
// 引数3:発生したイベント情報を格納するWaitEvent構造体の参照
// 引数4:返される最大イベント数
// 引数5:pgstatにreportする情報
// 戻り値:発生したイベントフラグ
extern int WaitEventSetWait(WaitEventSet *set, long timeout,
				 WaitEvent *occurred_events, int nevents,
				 uint32 wait_event_info);

参考WaitEventSetWait() - https://git.postgresql.org/gitweb/

WaitLatch

// 引数1:監視したいLatchの参照
// 引数2:タイムアウト(msec)
// 引数3:pgstatにreportする情報
// 戻り値:発生したイベントフラグ
extern int WaitLatch(volatile Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info);

WaitLatchOrSocket

// 引数1:監視したいLatchの参照
// 引数2:タイムアウト(msec)
// 引数3:イベント監視するファイルディスクリプタ
// 引数4:pgstatにreportする情報
// 戻り値:発生したイベントフラグ
extern int WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock, long timeout, uint32 wait_event_info);

サンプルプログラム

static volatile sig_atomic_t got_sighup = false;

static void
myworker_sighup(SIGNAL_ARGS)
{
	int save_errno = errno;

	got_sighup = true;
	/* MyLatchでwaitするプロセスをwake upする */
	SetLatch(MyLatch);

	errno = save_errno;
}

void
myworker(Datum main_arg)
{
	int arg = DatumGetInt32(main_arg);

	/* We're now ready to receive signals */
	BackgroundWorkerUnblockSignals();

	for (;;)
	{
		int ret;
		int rc;
		/* MyLatchがSetLatchされる、タイムアウトする、またはpostmasterが死ぬイベントを待つ。10秒でタイムアウト。 */
		rc = WaitLatch(MyLatch,
			       WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
			       10 * 1000L,
			       PG_WAIT_EXTENSION);
		/* MyLatchのsetフラグをクリアする */
		ResetLatch(MyLatch);

		/* Emergency bailout if postmaster has died */
		if (rc & WL_POSTMASTER_DEATH)
			proc_exit(1);

		CHECK_FOR_INTERRUPTS();

		/*
		 * In case of a SIGHUP, just reload the configuration.
		 */
		if (got_sighup)
		{
			got_sighup = false;
			ProcessConfigFile(PGC_SIGHUP);
		}

		/* Do something */

	}

	proc_exit(1);
}

メモ

MyLatch以外のLatchを使うことも可能である。例えば、WaitLatchでMyLatchではないLatchを渡しており、シグナルハンドラでMyLatchにSetLatchするような場合。この場合、myworker_sighup関数でMyLatchがsetされるが、WaitLatchからはWL_LATCH_SETイベントでは戻らない。SetLatchでpipeへの書き込みイベントは起きるが、WaitLatchで渡しているOriginalLatchはsetされていないためである。

static void
myworker_sighup(SIGNAL_ARGS)
{
	int save_errno = errno;

	got_sighup = true;
	/* MyLatchでwaitするプロセスをwake upする */
	SetLatch(MyLatch);

	errno = save_errno;
}

/* MyLatchとは別のLatch */
volatile Latch OriginalLatch;

void
myworker(Datum main_arg)
{
	int arg = DatumGetInt32(main_arg);

	/* We're now ready to receive signals */
	BackgroundWorkerUnblockSignals();

	for (;;)
	{
		int rc;
		/* MyLatchではないLatchでイベントを待つ */
		rc = WaitLatch(&OriginalLatch,
			       WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
			       10 * 1000L,
			       PG_WAIT_EXTENSION);
		/* ResetLatch(&OriginalLatch); */
		/* Do something */
	}
}

参考・関連

 関連

コメント



PR

トップ   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
目次
ダブルクリックで閉じるTOP | 閉じる
GO TO TOP