cdbfts.c 4.4 KB
Newer Older
1 2 3 4 5
/*-------------------------------------------------------------------------
 *
 * cdbfts.c
 *	  Provides fault tolerance service routines for mpp.
 *
6 7 8 9 10 11
 * Portions Copyright (c) 2003-2008, Greenplum inc
 * Portions Copyright (c) 2012-Present Pivotal Software, Inc.
 *
 *
 * IDENTIFICATION
 *	    src/backend/cdb/cdbfts.c
12 13 14 15 16 17 18
 *
 *-------------------------------------------------------------------------
 */

#include "postgres.h"

#include "miscadmin.h"
19 20
#include "libpq-fe.h"
#include "libpq-int.h"
21 22 23 24
#include "utils/memutils.h"
#include "cdb/cdbvars.h"
#include "cdb/cdbconn.h"
#include "cdb/cdbutil.h"
25
#include "cdb/cdbdisp_query.h"
26 27 28 29 30
#include "access/xact.h"
#include "cdb/cdbfts.h"
#include "cdb/cdbtm.h"
#include "libpq/libpq-be.h"
#include "commands/dbcommands.h"
31
#include "storage/pmsignal.h"
32 33 34 35 36 37 38 39 40 41 42 43 44
#include "storage/proc.h"

#include "executor/spi.h"

#include "postmaster/fts.h"
#include "utils/faultinjection.h"

#include "utils/fmgroids.h"
#include "catalog/pg_authid.h"

/* segment id for the master */
#define MASTER_SEGMENT_ID -1

45 46
volatile FtsProbeInfo *ftsProbeInfo = NULL;	/* Probe process updates this structure */

A
Ashwin Agrawal 已提交
47
static LWLockId ftsControlLock;
48

A
Ashwin Agrawal 已提交
49 50
static volatile bool *ftsReadOnlyFlag;
static volatile bool *ftsAdminRequestedRO;
51 52 53 54 55 56 57 58

/*
 * get fts share memory size
 */
int
FtsShmemSize(void)
{
	/*
A
Ashwin Agrawal 已提交
59
	 * this shared memory block doesn't even need to *exist* on the QEs!
60 61 62 63 64 65 66 67 68 69 70 71 72
	 */
	if ((Gp_role != GP_ROLE_DISPATCH) && (Gp_role != GP_ROLE_UTILITY))
		return 0;

	return MAXALIGN(sizeof(FtsControlBlock));
}

void
FtsShmemInit(void)
{
	bool		found;
	FtsControlBlock *shared;

A
Ashwin Agrawal 已提交
73
	shared = (FtsControlBlock *) ShmemInitStruct("Fault Tolerance manager", FtsShmemSize(), &found);
74 75 76 77 78 79 80 81 82
	if (!shared)
		elog(FATAL, "FTS: could not initialize fault tolerance manager share memory");

	/* Initialize locks and shared memory area */

	ftsControlLock = shared->ControlLock;

	ftsReadOnlyFlag = &shared->ftsReadOnlyFlag; /* global RO state */

A
Ashwin Agrawal 已提交
83 84 85
	ftsAdminRequestedRO = &shared->ftsAdminRequestedRO; /* Admin request --
														 * guc-controlled RO
														 * state */
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116

	ftsProbeInfo = &shared->fts_probe_info;

	if (!IsUnderPostmaster)
	{
		shared->ControlLock = LWLockAssign();
		ftsControlLock = shared->ControlLock;

		/* initialize */
		shared->ftsReadOnlyFlag = gp_set_read_only;
		shared->ftsAdminRequestedRO = gp_set_read_only;

		shared->fts_probe_info.fts_statusVersion = 0;
	}
}

void
ftsLock(void)
{
	LWLockAcquire(ftsControlLock, LW_EXCLUSIVE);
}

void
ftsUnlock(void)
{
	LWLockRelease(ftsControlLock);
}

void
FtsNotifyProber(void)
{
117
	Assert(Gp_role == GP_ROLE_DISPATCH);
118
	uint8 probeTick = ftsProbeInfo->probeTick;
119 120

	/* signal fts-probe */
121
	SendPostmasterSignal(PMSIGNAL_WAKEN_FTS);
122 123

	/* sit and spin */
124
	while (probeTick == ftsProbeInfo->probeTick)
125
	{
126
		pg_usleep(50000);
127 128 129 130 131 132 133 134 135
		CHECK_FOR_INTERRUPTS();
	}
}

/*
 * Test-Connection: This is called from the threaded context inside the
 * dispatcher: ONLY CALL THREADSAFE FUNCTIONS -- elog() is NOT threadsafe.
 */
bool
A
Ashwin Agrawal 已提交
136
FtsIsSegmentUp(CdbComponentDatabaseInfo *dBInfo)
137 138
{
	/* master is always reported as alive */
A
Ashwin Agrawal 已提交
139
	if (dBInfo->segindex == MASTER_SEGMENT_ID)
140
		return true;
141

142 143 144 145 146 147 148 149 150
	/*
	 * If fullscan is not requested, caller is just trying to optimize on the
	 * cached version of the segment status.  If the cached version is not
	 * initialized yet, just return positively back.  This is mainly to avoid
	 * queries incorrectly failing just after QD restarts if FTS process is yet
	 * to start and complete initializing the cached status.  We shouldn't be
	 * checking against uninitialzed variable.
	 */
	return ftsProbeInfo->fts_statusVersion ?
A
Ashwin Agrawal 已提交
151
		FTS_STATUS_IS_UP(ftsProbeInfo->fts_status[dBInfo->dbid]) :
152
		true;
153 154 155
}

/*
G
Gang Xiong 已提交
156 157 158
 * Check if any segment DB is down.
 *
 * returns true if any segment DB is down.
159 160
 */
bool
A
Ashwin Agrawal 已提交
161
FtsTestSegmentDBIsDown(SegmentDatabaseDescriptor *segdbDesc, int size)
162
{
A
Ashwin Agrawal 已提交
163
	int			i = 0;
164 165 166 167 168

	for (i = 0; i < size; i++)
	{
		CdbComponentDatabaseInfo *segInfo = segdbDesc[i].segment_database_info;

G
Gang Xiong 已提交
169 170
		elog(DEBUG2, "FtsTestSegmentDBIsDown: looking for real fault on segment dbid %d", segInfo->dbid);

A
Ashwin Agrawal 已提交
171
		if (!FtsIsSegmentUp(segInfo))
172
		{
G
Gang Xiong 已提交
173
			ereport(LOG, (errmsg_internal("FTS: found fault with segment dbid %d. "
A
Ashwin Agrawal 已提交
174
										  "Reconfiguration is in progress", segInfo->dbid)));
G
Gang Xiong 已提交
175
			return true;
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
		}
	}

	return false;
}

void
FtsCondSetTxnReadOnly(bool *XactFlag)
{
	if (*ftsReadOnlyFlag && Gp_role != GP_ROLE_UTILITY)
		*XactFlag = true;
}

bool
isFtsReadOnlySet(void)
{
	return *ftsReadOnlyFlag;
}
G
Gang Xiong 已提交
194

195
uint8
A
Ashwin Agrawal 已提交
196
getFtsVersion(void)
G
Gang Xiong 已提交
197 198 199
{
	return ftsProbeInfo->fts_statusVersion;
}