コード例 #1
0
ファイル: gistutil.c プロジェクト: BALDELab/incubator-hawq
/*
 * Verify that a freshly-read page looks sane.
 */
void
gistcheckpage(Relation rel, Buffer buf)
{
	Page		page = BufferGetPage(buf);

	/*
	 * ReadBuffer verifies that every newly-read page passes
	 * PageHeaderIsValid, which means it either contains a reasonably sane
	 * page header or is all-zero.	We have to defend against the all-zero
	 * case, however.
	 */
	if (PageIsNew(page))
		ereport(ERROR,
				(errcode(ERRCODE_INDEX_CORRUPTED),
			 errmsg("index \"%s\" contains unexpected zero page at block %u",
					RelationGetRelationName(rel),
					BufferGetBlockNumber(buf)),
				 errhint("Please REINDEX it."),
				 errSendAlert(true)));

	/*
	 * Additionally check that the special area looks sane.
	 */
	if (((PageHeader) (page))->pd_special !=
		(BLCKSZ - MAXALIGN(sizeof(GISTPageOpaqueData))))
		ereport(ERROR,
				(errcode(ERRCODE_INDEX_CORRUPTED),
				 errmsg("index \"%s\" contains corrupted page at block %u",
						RelationGetRelationName(rel),
						BufferGetBlockNumber(buf)),
				 errhint("Please REINDEX it."),
				 errSendAlert(true)));
}
コード例 #2
0
ファイル: cdbfilerepconnserver.c プロジェクト: karthijrk/gpdb
int 
FileRepConnServer_StartListener(
		char	*hostAddress,
		int		portLocal)
{

	int	status = STATUS_OK;
	int i;
	
	for (i=0; i < FILEREP_MAX_LISTEN; i++) {
		listenSocket[i] = -1;
	}
	
	/* NOTE check if family AF_UNIX has to be considered as well */
	status = StreamServerPort(
					AF_UNSPEC, 
					hostAddress,
					(unsigned short) portLocal,
					NULL,
					listenSocket,
					FILEREP_MAX_LISTEN);

	if (status != STATUS_OK) {
		ereport(WARNING, 
				(errcode_for_socket_access(),
				 errmsg("could not start listener, host:'%s' port:'%d': %m",
						hostAddress,
						portLocal),
				 errSendAlert(true),
				 FileRep_errcontext()));
	}
	
	return status;
}
コード例 #3
0
ファイル: cdbfts.c プロジェクト: BALDELab/incubator-hawq
void
FtsHandleNetFailure(SegmentDatabaseDescriptor ** segDB, int numOfFailed)
{
	elog(LOG, "FtsHandleNetFailure: numOfFailed %d", numOfFailed);

	ereport(ERROR, (errmsg_internal("MPP detected %d segment failures, system is reconnected", numOfFailed),
			errSendAlert(true)));
}
コード例 #4
0
int
FileRepConnClient_EstablishConnection(
									  char *hostAddress,
									  int port,
									  bool reportError)
{
	int			status = STATUS_OK;
	char		portbuf[11];
	char		timeoutbuf[11];
	const char *keys[5];
	const char *vals[5];

/*	FileRepConnClient_CloseConnection();*/

	snprintf(portbuf, sizeof(portbuf), "%d", port);
	snprintf(timeoutbuf, sizeof(timeoutbuf), "%d", gp_segment_connect_timeout);

	keys[0] = "host";
	vals[0] = hostAddress;
	keys[1] = "port";
	vals[1] = portbuf;
	keys[2] = "dbname";
	vals[2] = "postgres";
	keys[3] = "connect_timeout";
	vals[3] = timeoutbuf;
	keys[4] = NULL;
	vals[4] = NULL;

	filerep_conn = PQconnectdbParams(keys, vals, false);

	if (PQstatus(filerep_conn) != CONNECTION_OK)
	{
		if (reportError || Debug_filerep_print)
			ereport(WARNING,
					(errcode_for_socket_access(),
					 errmsg("could not establish connection with server, host:'%s' port:'%d' err:'%s' : %m",
							hostAddress,
							port,
							PQerrorMessage(filerep_conn)),
					 errSendAlert(true),
					 FileRep_errcontext()));

		status = STATUS_ERROR;

		if (filerep_conn)
		{
			PQfinish(filerep_conn);
			filerep_conn = NULL;
		}
	}

	/* NOTE Handle error message see ftsprobe.c */

	return status;
}
コード例 #5
0
ファイル: cdbfts.c プロジェクト: qiuyesuifeng/gpdb
/*
 * Re-Configure the system: if someone has noticed that the status
 * version has been updated, they call this to verify that they've got
 * the right configuration.
 *
 * NOTE: This *always* destroys gangs. And also attempts to inform the
 * fault-prober to do a full scan.
 */
void
FtsReConfigureMPP(bool create_new_gangs)
{
	/* need to scan to pick up the latest view */
	detectFailedConnections();
	local_fts_statusVersion = ftsProbeInfo->fts_statusVersion;

	ereport(LOG, (errmsg_internal("FTS: reconfiguration is in progress"),
			errSendAlert(true)));
	disconnectAndDestroyAllGangs();

	/* Caller should throw an error. */
	return;
}
コード例 #6
0
ファイル: postinit.c プロジェクト: chrishajas/gpdb
/*
 * ProcessRoleGUC --
 * We now process pg_authid.rolconfig separately from InitializeSessionUserId,
 * since it's too early to access toast table before initializing all
 * relcaches in phase3.
 */
static void
ProcessRoleGUC(void)
{
	cqContext  *pcqCtx;
	Oid			roleId;
	HeapTuple	roleTup;
	Datum		datum;
	bool		isnull;

	/* This should have been set by now */
	roleId = GetUserId();
	Assert(OidIsValid(roleId));

	pcqCtx = caql_beginscan(
			NULL,
			cql("SELECT * FROM pg_authid "
				" WHERE oid = :1",
				ObjectIdGetDatum(roleId)));

	roleTup = caql_getnext(pcqCtx);

	if (!HeapTupleIsValid(roleTup))
		ereport(FATAL,
				(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
				 errmsg("role %u does not exist", roleId), errSendAlert(false)));

	/*
	 * Set up user-specific configuration variables.  This is a good place to
	 * do it so we don't have to read pg_authid twice during session startup.
	 */
	datum = caql_getattr(pcqCtx,
						 Anum_pg_authid_rolconfig, &isnull);
	if (!isnull)
	{
		ArrayType  *a = DatumGetArrayTypeP(datum);

		/*
		 * We process all the options at SUSET level.  We assume that the
		 * right to insert an option into pg_authid was checked when it was
		 * inserted.
		 */
		ProcessGUCArray(a, PGC_SUSET, PGC_S_USER, GUC_ACTION_SET);
	}

	caql_endscan(pcqCtx);
}
コード例 #7
0
ファイル: cdbfts.c プロジェクト: BALDELab/incubator-hawq
bool QDMirroringWriteCheck(void)
{
	bool giveWarning = false;
	QDMIRRORDisabledReason	disabledReason = QDMIRROR_DISABLEDREASON_NONE;
	struct timeval lastLogTimeVal = {0, 0};

	if (ftsQDMirrorInfo == NULL)
		return false;	// Don't know yet.

	LWLockAcquire(ftsQDMirrorLock, LW_EXCLUSIVE);
	if (ftsQDMirrorInfo->state == QDMIRROR_STATE_SYNCHRONIZED)
	{
		LWLockRelease(ftsQDMirrorLock);
		return true;
	}

	if (ftsQDMirrorInfo->QDMirroringNotSynchronizedWarningGiven == false &&
		ftsQDMirrorInfo->state == QDMIRROR_STATE_DISABLED)
	{
		giveWarning = true;
		ftsQDMirrorInfo->QDMirroringNotSynchronizedWarningGiven = true;
		disabledReason = ftsQDMirrorInfo->disabledReason;
		lastLogTimeVal = ftsQDMirrorInfo->lastLogTimeVal;
	}

	LWLockRelease(ftsQDMirrorLock);

	if (giveWarning)
	{
		char logTimeStr[100];

		QDMirroringFormatTime(logTimeStr, sizeof(logTimeStr),
					          &lastLogTimeVal);

		ereport(LOG,
				(errcode(ERRCODE_GP_INTERCONNECTION_ERROR),
				 errmsg("Master mirroring is not synchronized as of %s (%s).  "
				        "The GPDB system is currently not highly-available",
				        logTimeStr,
				        QDMirroringDisabledReasonToString(disabledReason)),
				 errSendAlert(true)));
	}

	return false;
}
コード例 #8
0
ファイル: cdbfts.c プロジェクト: qiuyesuifeng/gpdb
/*
 * FtsHandleGangConnectionFailure is called by createGang during
 * creating connections return true if error need to be thrown
 */
bool
FtsHandleGangConnectionFailure(SegmentDatabaseDescriptor * segdbDesc, int size)
{
	int			i;
	bool		dtx_active;
	bool		reportError = false;
    bool		realFaultFound = false;
	bool		forceRescan=true;

    for (i = 0; i < size; i++)
    {
        if (PQstatus(segdbDesc[i].conn) != CONNECTION_OK)
        {
			CdbComponentDatabaseInfo *segInfo = segdbDesc[i].segment_database_info;

			elog(DEBUG2, "FtsHandleGangConnectionFailure: looking for real fault on segment dbid %d", segInfo->dbid);

			if (!FtsTestConnection(segInfo, forceRescan))
			{
				elog(DEBUG2, "found fault with segment dbid %d", segInfo->dbid);
				realFaultFound = true;

				/* that at least one fault exists is enough, for now */
				break;
			}
			forceRescan = false; /* only force the rescan on the first call. */
        }
    }

    if (!realFaultFound)
	{
		/* If we successfully tested the gang and didn't notice a
		 * failure, our caller must've seen some kind of transient
		 * failure when the gang was originally constructed ...  */
		elog(DEBUG2, "FtsHandleGangConnectionFailure: no real fault found!");
        return false;
	}

	if (!isFTSEnabled())
	{
		return false;
	}

	ereport(LOG, (errmsg_internal("FTS: reconfiguration is in progress")));

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

		if (PQstatus(segdbDesc[i].conn) != CONNECTION_OK)
		{
			if (!FtsTestConnection(segInfo, forceRescan))
			{
				ereport(LOG, (errmsg_internal("FTS: found bad segment with dbid %d", segInfo->dbid),
						errSendAlert(true)));
				/* probe process has already marked segment down. */
			}
			forceRescan = false; /* only force rescan on first call. */
		}
	}

	if (gangsExist())
	{
		reportError = true;
		disconnectAndDestroyAllGangs();
	}

	/*
	 * KLUDGE: Do not error out if we are attempting a DTM protocol retry
	 */
	if (DistributedTransactionContext == DTX_CONTEXT_QD_RETRY_PHASE_2)
	{
		return false;
	}

	/* is there a transaction active ? */
	dtx_active = isCurrentDtxActive();

    /* When the error is raised, it will abort the current DTM transaction */
	if (dtx_active)
	{
		elog((Debug_print_full_dtm ? LOG : DEBUG5),
			 "FtsHandleGangConnectionFailure found an active DTM transaction (returning true).");
		return true;
	}

	/*
	 * error out if this sets read only flag, at this stage the read only
	 * transaction checking has passed, so error out, but do not error out if
	 * tm is in recovery
	 */
	if ((*ftsReadOnlyFlag && !isTMInRecovery()) || reportError)
		return true;

	elog((Debug_print_full_dtm ? LOG : DEBUG5),
		 "FtsHandleGangConnectionFailure returning false.");

	return false;
}
コード例 #9
0
ファイル: postinit.c プロジェクト: nellaivijay/incubator-hawq
/* --------------------------------
 * InitPostgres
 *		Initialize POSTGRES.
 *
 * The database can be specified by name, using the in_dbname parameter, or by
 * OID, using the dboid parameter.	In the latter case, the computed database
 * name is passed out to the caller as a palloc'ed string in out_dbname.
 *
 * In bootstrap mode no parameters are used.
 *
 * The return value indicates whether the userID is a superuser.  (That
 * can only be tested inside a transaction, so we want to do it during
 * the startup transaction rather than doing a separate one in postgres.c.)
 *
 * As of PostgreSQL 8.2, we expect InitProcess() was already called, so we
 * already have a PGPROC struct ... but it's not filled in yet.
 *
 * Note:
 *		Be very careful with the order of calls in the InitPostgres function.
 * --------------------------------
 */
bool
InitPostgres(const char *in_dbname, Oid dboid, const char *username,
             char **out_dbname)
{
    bool		bootstrap = IsBootstrapProcessingMode();
    bool		autovacuum = IsAutoVacuumProcess();
    bool		am_superuser;
    char	   *fullpath;
    char		dbname[NAMEDATALEN];

    /*
     * Set up the global variables holding database id and path.  But note we
     * won't actually try to touch the database just yet.
     *
     * We take a shortcut in the bootstrap case, otherwise we have to look up
     * the db name in pg_database.
     */
    if (bootstrap)
    {
        MyDatabaseId = TemplateDbOid;
        MyDatabaseTableSpace = DEFAULTTABLESPACE_OID;
    }
    else
    {
        /*
         * Find tablespace of the database we're about to open. Since we're
         * not yet up and running we have to use one of the hackish
         * FindMyDatabase variants, which look in the flat-file copy of
         * pg_database.
         *
         * If the in_dbname param is NULL, lookup database by OID.
         */
        if (in_dbname == NULL)
        {
            if (!FindMyDatabaseByOid(dboid, dbname, &MyDatabaseTableSpace))
                ereport(FATAL,
                        (errcode(ERRCODE_UNDEFINED_DATABASE),
                         errmsg("database %u does not exist", dboid),
                         errSendAlert(false)));
            MyDatabaseId = dboid;
            /* pass the database name to the caller */
            *out_dbname = pstrdup(dbname);
        }
        else
        {
            if (!FindMyDatabase(in_dbname, &MyDatabaseId, &MyDatabaseTableSpace))
                ereport(FATAL,
                        (errcode(ERRCODE_UNDEFINED_DATABASE),
                         errmsg("database \"%s\" does not exist",
                                in_dbname),
                         errOmitLocation(true),
                         errSendAlert(false)));
            /* our database name is gotten from the caller */
            strlcpy(dbname, in_dbname, NAMEDATALEN);
        }
    }

    fullpath = GetDatabasePath(MyDatabaseId, MyDatabaseTableSpace);

    SetDatabasePath(fullpath);

    /*
     * Finish filling in the PGPROC struct, and add it to the ProcArray. (We
     * need to know MyDatabaseId before we can do this, since it's entered
     * into the PGPROC struct.)
     *
     * Once I have done this, I am visible to other backends!
     */
    InitProcessPhase2();

    // get temporary directory for QD
    if (!bootstrap && Gp_role == GP_ROLE_DISPATCH)
    {
        if (get_tmpdir_from_rm)
        {
            getLocalTmpDirFromMasterRM();
        }
        else
        {
            getLocalTmpDirFromMasterConfig(gp_session_id);
            elog(LOG, "getLocalTmpDirFromMasterConfig session_id:%d tmpdir:%s", gp_session_id, LocalTempPath);
        }

    }
    /* Initialize SessionState entry */
    SessionState_Init();
    /* Initialize memory protection */
    GPMemoryProtect_Init();

    /*
     * Initialize my entry in the shared-invalidation manager's array of
     * per-backend data.
     *
     * Sets up MyBackendId, a unique backend identifier.
     */
    MyBackendId = InvalidBackendId;

    SharedInvalBackendInit(false);

    if (MyBackendId > MaxBackends || MyBackendId <= 0)
        elog(FATAL, "bad backend id: %d", MyBackendId);

    /* Now that we have a BackendId, we can participate in ProcSignal */
    ProcSignalInit(MyBackendId);

    /*
     * bufmgr needs another initialization call too
     */
    InitBufferPoolBackend();

    /*
     * Initialize local process's access to XLOG.  In bootstrap case we may
     * skip this since StartupXLOG() was run instead.
     */
    if (!bootstrap)
        InitXLOGAccess();

    /*
     * Initialize the relation cache and the system catalog caches.  Note that
     * no catalog access happens here; we only set up the hashtable structure.
     * We must do this before starting a transaction because transaction abort
     * would try to touch these hashtables.
     */
    RelationCacheInitialize();
    InitCatalogCache();

    /* Initialize portal manager */
    EnablePortalManager();

    /* Initialize stats collection --- must happen before first xact */
    if (!bootstrap)
        pgstat_initialize();

    /*
     * Set up process-exit callback to do pre-shutdown cleanup.  This has to
     * be after we've initialized all the low-level modules like the buffer
     * manager, because during shutdown this has to run before the low-level
     * modules start to close down.  On the other hand, we want it in place
     * before we begin our first transaction --- if we fail during the
     * initialization transaction, as is entirely possible, we need the
     * AbortTransaction call to clean up.
     */
    on_shmem_exit(ShutdownPostgres, 0);

    /*
     * Start a new transaction here before first access to db, and get a
     * snapshot.  We don't have a use for the snapshot itself, but we're
     * interested in the secondary effect that it sets RecentGlobalXmin.
     */
    if (!bootstrap)
    {
        StartTransactionCommand();
        (void) GetTransactionSnapshot();
    }

    /*
     * Now that we have a transaction, we can take locks.  Take a writer's
     * lock on the database we are trying to connect to.  If there is a
     * concurrently running DROP DATABASE on that database, this will block us
     * until it finishes (and has updated the flat file copy of pg_database).
     *
     * Note that the lock is not held long, only until the end of this startup
     * transaction.  This is OK since we are already advertising our use of
     * the database in the PGPROC array; anyone trying a DROP DATABASE after
     * this point will see us there.
     *
     * Note: use of RowExclusiveLock here is reasonable because we envision
     * our session as being a concurrent writer of the database.  If we had a
     * way of declaring a session as being guaranteed-read-only, we could use
     * AccessShareLock for such sessions and thereby not conflict against
     * CREATE DATABASE.
     */
    if (!bootstrap)
    {
        if (MyDatabaseId == TemplateDbOid)
            LockSharedObject(DatabaseRelationId, MyDatabaseId, 0,
                             AccessShareLock);
        else
            LockSharedObject(DatabaseRelationId, MyDatabaseId, 0,
                             RowExclusiveLock);
    }

    /*
     * Recheck the flat file copy of pg_database to make sure the target
     * database hasn't gone away.  If there was a concurrent DROP DATABASE,
     * this ensures we will die cleanly without creating a mess.
     */
    if (!bootstrap)
    {
        Oid			dbid2;
        Oid			tsid2;

        if (!FindMyDatabase(dbname, &dbid2, &tsid2) ||
                dbid2 != MyDatabaseId || tsid2 != MyDatabaseTableSpace)
            ereport(FATAL,
                    (errcode(ERRCODE_UNDEFINED_DATABASE),
                     errmsg("database \"%s\" does not exist",
                            dbname),
                     errdetail("It seems to have just been dropped or renamed.")));
    }

    /*
     * Now we should be able to access the database directory safely. Verify
     * it's there and looks reasonable.
     */
    if (!bootstrap)
    {
        if (access(fullpath, F_OK) == -1)
        {
            if (errno == ENOENT)
                ereport(FATAL,
                        (errcode(ERRCODE_UNDEFINED_DATABASE),
                         errmsg("database \"%s\" does not exist",
                                dbname),
                         errdetail("The database subdirectory \"%s\" is missing.",
                                   fullpath)));
            else
                ereport(FATAL,
                        (errcode_for_file_access(),
                         errmsg("could not access directory \"%s\": %m",
                                fullpath)));
        }

        ValidatePgVersion(fullpath);
    }

    /*
     * It's now possible to do real access to the system catalogs.
     *
     * Load relcache entries for the system catalogs.  This must create at
     * least the minimum set of "nailed-in" cache entries.
     */
    RelationCacheInitializePhase2();

    /*
     * Figure out our postgres user id, and see if we are a superuser.
     *
     * In standalone mode and in the autovacuum process, we use a fixed id,
     * otherwise we figure it out from the authenticated user name.
     */
    if (bootstrap || autovacuum)
    {
        InitializeSessionUserIdStandalone();
        am_superuser = true;
    }
    else if (!IsUnderPostmaster)
    {
        InitializeSessionUserIdStandalone();
        am_superuser = true;
        if (!ThereIsAtLeastOneRole())
            ereport(WARNING,
                    (errcode(ERRCODE_UNDEFINED_OBJECT),
                     errmsg("no roles are defined in this database system"),
                     errhint("You should immediately run CREATE USER \"%s\" CREATEUSER;.",
                             username)));
    }
    else
    {
        /* normal multiuser case */
        InitializeSessionUserId(username);
        am_superuser = superuser();
    }

    /* set up ACL framework (so CheckMyDatabase can check permissions) */
    initialize_acl();

    /*
     * Read the real pg_database row for our database, check permissions and
     * set up database-specific GUC settings.  We can't do this until all the
     * database-access infrastructure is up.  (Also, it wants to know if the
     * user is a superuser, so the above stuff has to happen first.)
     */
    if (!bootstrap)
        CheckMyDatabase(dbname, am_superuser);

    /*
     * Check a normal user hasn't connected to a superuser reserved slot.
     */
    if (!am_superuser &&
            ReservedBackends > 0 &&
            !HaveNFreeProcs(ReservedBackends))
        ereport(FATAL,
                (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
                 errmsg("connection limit exceeded for non-superusers"),
                 errOmitLocation(true),
                 errSendAlert(true)));

    /*
     * Initialize various default states that can't be set up until we've
     * selected the active user and gotten the right GUC settings.
     */

    /* set default namespace search path */
    InitializeSearchPath();

    /* initialize client encoding */
    InitializeClientEncoding();

    /* report this backend in the PgBackendStatus array */
    if (!bootstrap)
        pgstat_bestart();

    /*
    * MPP package setup
    *
    * Primary function is to establish connctions to the qExecs.
    * This is SKIPPED when the database is in bootstrap mode or
    * Is not UnderPostmaster.
    */
    if (!bootstrap && IsUnderPostmaster)
    {
        cdb_setup();
        on_proc_exit( cdb_cleanup, 0 );
    }

    /* close the transaction we started above */
    if (!bootstrap)
        CommitTransactionCommand();

    return am_superuser;
}
コード例 #10
0
ファイル: postinit.c プロジェクト: nellaivijay/incubator-hawq
/*
 * CheckMyDatabase -- fetch information from the pg_database entry for our DB
 */
static void
CheckMyDatabase(const char *name, bool am_superuser)
{
    HeapTuple	tup;
    Form_pg_database dbform;

    /* Fetch our real pg_database row */
    tup = SearchSysCache(DATABASEOID,
                         ObjectIdGetDatum(MyDatabaseId),
                         0, 0, 0);
    if (!HeapTupleIsValid(tup))
        elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);
    dbform = (Form_pg_database) GETSTRUCT(tup);

    /* This recheck is strictly paranoia */
    if (strcmp(name, NameStr(dbform->datname)) != 0)
        ereport(FATAL,
                (errcode(ERRCODE_UNDEFINED_DATABASE),
                 errmsg("database \"%s\" has disappeared from pg_database",
                        name),
                 errdetail("Database OID %u now seems to belong to \"%s\".",
                           MyDatabaseId, NameStr(dbform->datname))));

    /*
     * Check permissions to connect to the database.
     *
     * These checks are not enforced when in standalone mode, so that there is
     * a way to recover from disabling all access to all databases, for
     * example "UPDATE pg_database SET datallowconn = false;".
     *
     * We do not enforce them for the autovacuum worker processes either.
     */
    if (IsUnderPostmaster && !IsAutoVacuumProcess())
    {
        /*
         * Check that the database is currently allowing connections.
         * (exception during upgrade_mode)
         */
        if (gp_upgrade_mode && !dbform->datallowconn)
            elog(INFO, "Connecting to no-connection db in upgrade mode.");

        if (!dbform->datallowconn && !gp_upgrade_mode)
            ereport(FATAL,
                    (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
                     errmsg("database \"%s\" is not currently accepting connections",
                            name),
                     errOmitLocation(true),
                     errSendAlert(false)));

        /*
         * Check privilege to connect to the database.	(The am_superuser test
         * is redundant, but since we have the flag, might as well check it
         * and save a few cycles.)
         */
        if (!am_superuser &&
                pg_database_aclcheck(MyDatabaseId, GetUserId(),
                                     ACL_CONNECT) != ACLCHECK_OK)
            ereport(FATAL,
                    (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                     errmsg("permission denied for database \"%s\"", name),
                     errdetail("User does not have CONNECT privilege."),
                     errOmitLocation(true),
                     errSendAlert(false)));

        /*
         * Check connection limit for this database.
         *
         * There is a race condition here --- we create our PGPROC before
         * checking for other PGPROCs.	If two backends did this at about the
         * same time, they might both think they were over the limit, while
         * ideally one should succeed and one fail.  Getting that to work
         * exactly seems more trouble than it is worth, however; instead we
         * just document that the connection limit is approximate.
         */
        if (dbform->datconnlimit >= 0 &&
                !am_superuser &&
                CountDBBackends(MyDatabaseId) > dbform->datconnlimit)
            ereport(FATAL,
                    (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
                     errmsg("too many connections for database \"%s\"",
                            name),
                     errOmitLocation(true),
                     errSendAlert(false)));
    }

    /*
     * OK, we're golden.  Next to-do item is to save the encoding info out of
     * the pg_database tuple.
     */
    if (GpIdentity.segindex == UNINITIALIZED_GP_IDENTITY_VALUE ||
            GpIdentity.segindex == MASTER_CONTENT_ID)
        SetDatabaseEncoding(dbform->encoding);
    else
        SetDatabaseEncoding(MyProcPort->encoding);

    /* Record it as a GUC internal option, too */
    SetConfigOption("server_encoding", GetDatabaseEncodingName(),
                    PGC_INTERNAL, PGC_S_OVERRIDE);
    /* If we have no other source of client_encoding, use server encoding */
    SetConfigOption("client_encoding", GetDatabaseEncodingName(),
                    PGC_BACKEND, PGC_S_DEFAULT);

    /* Use the right encoding in translated messages */
#ifdef ENABLE_NLS
    pg_bind_textdomain_codeset(textdomain(NULL));
#endif

    /*
     * Lastly, set up any database-specific configuration variables.
     */
    if (IsUnderPostmaster)
    {
        Datum		datum;
        bool		isnull;

        datum = SysCacheGetAttr(DATABASEOID, tup, Anum_pg_database_datconfig,
                                &isnull);
        if (!isnull)
        {
            ArrayType  *a = DatumGetArrayTypeP(datum);

            ProcessGUCArray(a, PGC_S_DATABASE);
        }
    }

    ReleaseSysCache(tup);
}
コード例 #11
0
ファイル: cdbfilerepprimaryack.c プロジェクト: hsyuan/gpdb
/*
 * 
 * FileRepAckPrimary_StartReceiver
 */
void 
FileRepAckPrimary_StartReceiver(void)
{	
	int				status = STATUS_OK;
	struct timeval	currentTime;
	pg_time_t		beginTime = 0;
	pg_time_t		endTime = 0;	
	int				retval = 0;
	
	FileRep_InsertConfigLogEntry("start receiver ack");

	{
		char	tmpBuf[FILEREP_MAX_LOG_DESCRIPTION_LEN];
		
		snprintf(tmpBuf, sizeof(tmpBuf), "primary address(port) '%s(%d)' mirror address(port) '%s(%d)' ",
				 fileRepPrimaryHostAddress, 
				 fileRepPrimaryPort,
				 fileRepMirrorHostAddress, 
				 fileRepMirrorPort);
		
		FileRep_InsertConfigLogEntry(tmpBuf);
	}
		
	FileRepAckPrimary_ShmemReInit();
	
	Insist(fileRepRole == FileRepPrimaryRole);
	
	if (filerep_inject_listener_fault)
	{
		status = STATUS_ERROR;
		ereport(WARNING,
				(errmsg("mirror failure, "
						"injected fault by guc filerep_inject_listener_fault, "
						"failover requested"), 
				 FileRep_errcontext()));												
		
		FileRep_SetSegmentState(SegmentStateFault, FaultTypeMirror);
		FileRepSubProcess_SetState(FileRepStateFault);
		FileRepSubProcess_ProcessSignals();
		return;
	}
	
	status = FileRepConnServer_StartListener(
								 fileRepPrimaryHostAddress,
								 fileRepPrimaryPort);
	
	gettimeofday(&currentTime, NULL);
	beginTime = (pg_time_t) currentTime.tv_sec;
	
	while (1) {
		
		if (status != STATUS_OK) 
		{
			FileRep_SetSegmentState(SegmentStateFault, FaultTypeMirror);
			FileRepSubProcess_SetState(FileRepStateFault);
		}
		
		while (FileRepSubProcess_GetState() == FileRepStateFault) {
			
			FileRepSubProcess_ProcessSignals();
			pg_usleep(50000L); /* 50 ms */	
		}
		
		if (FileRepSubProcess_GetState() == FileRepStateShutdown) {
			
			break;
		}

		PG_SETMASK(&BlockSig);
		retval = FileRepConnServer_Select();	
		PG_SETMASK(&UnBlockSig);
		
		gettimeofday(&currentTime, NULL);
		endTime = (pg_time_t) currentTime.tv_sec;

		if ((endTime - beginTime) > gp_segment_connect_timeout) 
		{
			ereport(WARNING, 
					(errmsg("mirror failure, "
							"no connection was established from client from mirror, "
							"primary address(port) '%s(%d)' mirror address(port) '%s(%d)' timeout reached '%d' "
							"failover requested",
							fileRepPrimaryHostAddress, 
							fileRepPrimaryPort,
							fileRepMirrorHostAddress, 
							fileRepMirrorPort,
							gp_segment_connect_timeout),
					 errSendAlert(true),
					 FileRep_errcontext()));
			
			status = STATUS_ERROR;
			continue;
		}

		/* 
		 * check and process any signals received 
		 * The routine returns TRUE if the received signal requests
		 * process shutdown.
		 */
		if (FileRepSubProcess_ProcessSignals()) {
			continue;
		}
		
		if (retval < 0) {
			status = STATUS_ERROR;
			continue;
		}
		
		if (retval == 0) {
			continue;
		}
		
		Assert(retval > 0);
		
		status = FileRepConnServer_CreateConnection();
		
		if (status != STATUS_OK) {
			continue;
		}				
		
		status = FileRepConnServer_ReceiveStartupPacket();
		if (status != STATUS_OK) {
			continue;
		} 
		
		fileRepShmemArray[0]->state = FileRepStateInitialization;
		
		status = FileRepAckPrimary_RunReceiver();
		
	} // while(1)
			
	FileRepConnServer_CloseConnection();
	
	return;
}
コード例 #12
0
ファイル: bufpage.c プロジェクト: qiuyesuifeng/gpdb
/*
 * PageIndexMultiDelete
 *
 * This routine handles the case of deleting multiple tuples from an
 * index page at once.	It is considerably faster than a loop around
 * PageIndexTupleDelete ... however, the caller *must* supply the array
 * of item numbers to be deleted in item number order!
 */
void
PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
{
	PageHeader	phdr = (PageHeader) page;
	Offset		pd_lower = phdr->pd_lower;
	Offset		pd_upper = phdr->pd_upper;
	Offset		pd_special = phdr->pd_special;
	itemIdSort	itemidbase,
				itemidptr;
	ItemId		lp;
	int			nline,
				nused;
	int			i;
	Size		totallen;
	Offset		upper;
	Size		size;
	unsigned	offset;
	int			nextitm;
	OffsetNumber offnum;

	/*
	 * If there aren't very many items to delete, then retail
	 * PageIndexTupleDelete is the best way.  Delete the items in reverse
	 * order so we don't have to think about adjusting item numbers for
	 * previous deletions.
	 *
	 * TODO: tune the magic number here
	 */
	if (nitems <= 2)
	{
		while (--nitems >= 0)
			PageIndexTupleDelete(page, itemnos[nitems]);
		return;
	}

	/*
	 * As with PageRepairFragmentation, paranoia seems justified.
	 */
	if (pd_lower < SizeOfPageHeaderData ||
		pd_lower > pd_upper ||
		pd_upper > pd_special ||
		pd_special > BLCKSZ ||
		pd_special != MAXALIGN(pd_special))
		ereport(ERROR,
				(errcode(ERRCODE_DATA_CORRUPTED),
				 errmsg("corrupted page pointers: lower = %u, upper = %u, special = %u",
						pd_lower, pd_upper, pd_special),
				 errSendAlert(true)));

	/*
	 * Scan the item pointer array and build a list of just the ones we are
	 * going to keep.  Notice we do not modify the page yet, since we are
	 * still validity-checking.
	 */
	nline = PageGetMaxOffsetNumber(page);
	itemidbase = (itemIdSort) palloc(sizeof(itemIdSortData) * nline);
	itemidptr = itemidbase;
	totallen = 0;
	nused = 0;
	nextitm = 0;
	for (offnum = 1; offnum <= nline; offnum++)
	{
		lp = PageGetItemId(page, offnum);
		size = ItemIdGetLength(lp);
		offset = ItemIdGetOffset(lp);
		if (offset < pd_upper ||
			(offset + size) > pd_special ||
			offset != MAXALIGN(offset))
			ereport(ERROR,
					(errcode(ERRCODE_DATA_CORRUPTED),
					 errmsg("corrupted item pointer: offset = %u, size = %u",
							offset, (unsigned int) size),
					 errSendAlert(true)));

		if (nextitm < nitems && offnum == itemnos[nextitm])
		{
			/* skip item to be deleted */
			nextitm++;
		}
		else
		{
			itemidptr->offsetindex = nused;		/* where it will go */
			itemidptr->itemoff = offset;
			itemidptr->olditemid = *lp;
			itemidptr->alignedlen = MAXALIGN(size);
			totallen += itemidptr->alignedlen;
			itemidptr++;
			nused++;
		}
	}

	/* this will catch invalid or out-of-order itemnos[] */
	if (nextitm != nitems)
		elog(ERROR, "incorrect index offsets supplied");

	if (totallen > (Size) (pd_special - pd_lower))
		ereport(ERROR,
				(errcode(ERRCODE_DATA_CORRUPTED),
			   errmsg("corrupted item lengths: total %u, available space %u",
					  (unsigned int) totallen, pd_special - pd_lower),
			   errSendAlert(true)));

	/* sort itemIdSortData array into decreasing itemoff order */
	qsort((char *) itemidbase, nused, sizeof(itemIdSortData),
		  itemoffcompare);

	/* compactify page and install new itemids */
	upper = pd_special;

	for (i = 0, itemidptr = itemidbase; i < nused; i++, itemidptr++)
	{
		lp = PageGetItemId(page, itemidptr->offsetindex + 1);
		upper -= itemidptr->alignedlen;
		memmove((char *) page + upper,
				(char *) page + itemidptr->itemoff,
				itemidptr->alignedlen);
		*lp = itemidptr->olditemid;
		lp->lp_off = upper;
	}

	phdr->pd_lower = SizeOfPageHeaderData + nused * sizeof(ItemIdData);
	phdr->pd_upper = upper;

	pfree(itemidbase);
}
コード例 #13
0
ファイル: bufpage.c プロジェクト: qiuyesuifeng/gpdb
/*
 * PageIndexTupleDelete
 *
 * This routine does the work of removing a tuple from an index page.
 *
 * Unlike heap pages, we compact out the line pointer for the removed tuple.
 */
void
PageIndexTupleDelete(Page page, OffsetNumber offnum)
{
	PageHeader	phdr = (PageHeader) page;
	char	   *addr;
	ItemId		tup;
	Size		size;
	unsigned	offset;
	int			nbytes;
	int			offidx;
	int			nline;

	/*
	 * As with PageRepairFragmentation, paranoia seems justified.
	 */
	if (phdr->pd_lower < SizeOfPageHeaderData ||
		phdr->pd_lower > phdr->pd_upper ||
		phdr->pd_upper > phdr->pd_special ||
		phdr->pd_special > BLCKSZ)
		ereport(ERROR,
				(errcode(ERRCODE_DATA_CORRUPTED),
				 errmsg("corrupted page pointers: lower = %u, upper = %u, special = %u",
						phdr->pd_lower, phdr->pd_upper, phdr->pd_special),
				 errSendAlert(true)));

	nline = PageGetMaxOffsetNumber(page);
	if ((int) offnum <= 0 || (int) offnum > nline)
		elog(ERROR, "invalid index offnum: %u", offnum);

	/* change offset number to offset index */
	offidx = offnum - 1;

	tup = PageGetItemId(page, offnum);
	size = ItemIdGetLength(tup);
	offset = ItemIdGetOffset(tup);

	if (offset < phdr->pd_upper || (offset + size) > phdr->pd_special ||
		offset != MAXALIGN(offset) || size != MAXALIGN(size))
		ereport(ERROR,
				(errcode(ERRCODE_DATA_CORRUPTED),
				 errmsg("corrupted item pointer: offset = %u, size = %u",
						offset, (unsigned int) size),
				 errSendAlert(true)));

	/*
	 * First, we want to get rid of the pd_linp entry for the index tuple. We
	 * copy all subsequent linp's back one slot in the array. We don't use
	 * PageGetItemId, because we are manipulating the _array_, not individual
	 * linp's.
	 */
	nbytes = phdr->pd_lower -
		((char *) &phdr->pd_linp[offidx + 1] - (char *) phdr);

	if (nbytes > 0)
		memmove((char *) &(phdr->pd_linp[offidx]),
				(char *) &(phdr->pd_linp[offidx + 1]),
				nbytes);

	/*
	 * Now move everything between the old upper bound (beginning of tuple
	 * space) and the beginning of the deleted tuple forward, so that space in
	 * the middle of the page is left free.  If we've just deleted the tuple
	 * at the beginning of tuple space, then there's no need to do the copy
	 * (and bcopy on some architectures SEGV's if asked to move zero bytes).
	 */

	/* beginning of tuple space */
	addr = (char *) page + phdr->pd_upper;

	if (offset > phdr->pd_upper)
		memmove(addr + size, addr, (int) (offset - phdr->pd_upper));

	/* adjust free space boundary pointers */
	phdr->pd_upper += size;
	phdr->pd_lower -= sizeof(ItemIdData);

	/*
	 * Finally, we need to adjust the linp entries that remain.
	 *
	 * Anything that used to be before the deleted tuple's data was moved
	 * forward by the size of the deleted tuple.
	 */
	if (!PageIsEmpty(page))
	{
		int			i;

		nline--;				/* there's one less than when we started */
		for (i = 1; i <= nline; i++)
		{
			ItemId		ii = PageGetItemId(phdr, i);

			if (ItemIdGetOffset(ii) <= offset)
				ii->lp_off += size;
		}
	}
}
コード例 #14
0
ファイル: bufpage.c プロジェクト: qiuyesuifeng/gpdb
/*
 * PageRepairFragmentation
 *
 * Frees fragmented space on a page.
 * It doesn't remove unused line pointers! Please don't change this.
 *
 * This routine is usable for heap pages only, but see PageIndexMultiDelete.
 *
 * Returns number of unused line pointers on page.	If "unused" is not NULL
 * then the unused[] array is filled with indexes of unused line pointers.
 */
int
PageRepairFragmentation(Page page, OffsetNumber *unused)
{
	Offset		pd_lower = ((PageHeader) page)->pd_lower;
	Offset		pd_upper = ((PageHeader) page)->pd_upper;
	Offset		pd_special = ((PageHeader) page)->pd_special;
	itemIdSort	itemidbase,
				itemidptr;
	ItemId		lp;
	int			nline,
				nused;
	int			i;
	Size		totallen;
	Offset		upper;

	/*
	 * It's worth the trouble to be more paranoid here than in most places,
	 * because we are about to reshuffle data in (what is usually) a shared
	 * disk buffer.  If we aren't careful then corrupted pointers, lengths,
	 * etc could cause us to clobber adjacent disk buffers, spreading the data
	 * loss further.  So, check everything.
	 */
	if (pd_lower < SizeOfPageHeaderData ||
		pd_lower > pd_upper ||
		pd_upper > pd_special ||
		pd_special > BLCKSZ ||
		pd_special != MAXALIGN(pd_special))
		ereport(ERROR,
				(errcode(ERRCODE_DATA_CORRUPTED),
				 errmsg("corrupted page pointers: lower = %u, upper = %u, special = %u",
						pd_lower, pd_upper, pd_special),
				 errSendAlert(true)));

	nline = PageGetMaxOffsetNumber(page);
	nused = 0;
	for (i = 0; i < nline; i++)
	{
		lp = PageGetItemId(page, i + 1);
		if (ItemIdDeleted(lp))	/* marked for deletion */
			lp->lp_flags &= ~(LP_USED | LP_DELETE);
		if (ItemIdIsUsed(lp))
			nused++;
		else if (unused)
			unused[i - nused] = (OffsetNumber) i;
	}

	if (nused == 0)
	{
		/* Page is completely empty, so just reset it quickly */
		for (i = 0; i < nline; i++)
		{
			lp = PageGetItemId(page, i + 1);
			lp->lp_len = 0;		/* indicate unused & deallocated */
		}
		((PageHeader) page)->pd_upper = pd_special;
	}
	else
	{							/* nused != 0 */
		/* Need to compact the page the hard way */
		itemidbase = (itemIdSort) palloc(sizeof(itemIdSortData) * nused);
		itemidptr = itemidbase;
		totallen = 0;
		for (i = 0; i < nline; i++)
		{
			lp = PageGetItemId(page, i + 1);
			if (ItemIdIsUsed(lp))
			{
				itemidptr->offsetindex = i;
				itemidptr->itemoff = ItemIdGetOffset(lp);
				if (itemidptr->itemoff < (int) pd_upper ||
					itemidptr->itemoff >= (int) pd_special)
					ereport(ERROR,
							(errcode(ERRCODE_DATA_CORRUPTED),
							 errmsg("corrupted item pointer: %u",
									itemidptr->itemoff),
							 errSendAlert(true)));
				itemidptr->alignedlen = MAXALIGN(ItemIdGetLength(lp));
				totallen += itemidptr->alignedlen;
				itemidptr++;
			}
			else
			{
				lp->lp_len = 0; /* indicate unused & deallocated */
			}
		}

		if (totallen > (Size) (pd_special - pd_lower))
			ereport(ERROR,
					(errcode(ERRCODE_DATA_CORRUPTED),
			   errmsg("corrupted item lengths: total %u, available space %u",
					  (unsigned int) totallen, pd_special - pd_lower),
			   errSendAlert(true)));

		/* sort itemIdSortData array into decreasing itemoff order */
		qsort((char *) itemidbase, nused, sizeof(itemIdSortData),
			  itemoffcompare);

		/* compactify page */
		upper = pd_special;

		for (i = 0, itemidptr = itemidbase; i < nused; i++, itemidptr++)
		{
			lp = PageGetItemId(page, itemidptr->offsetindex + 1);
			upper -= itemidptr->alignedlen;
			memmove((char *) page + upper,
					(char *) page + itemidptr->itemoff,
					itemidptr->alignedlen);
			lp->lp_off = upper;
		}

		((PageHeader) page)->pd_upper = upper;

		pfree(itemidbase);
	}

	/* Set hint bit for PageAddItem */
	if (nused < nline)
		PageSetHasFreeLinePointers(page);
	else
		PageClearHasFreeLinePointers(page);

	return (nline - nused);
}
コード例 #15
0
ファイル: bitmappages.c プロジェクト: AnLingm/gpdb
/*
 * _bitmap_init() -- initialize the bitmap index.
 *
 * Create the meta page, a new heap which stores the distinct values for
 * the attributes to be indexed, a btree index on this new heap for searching
 * those distinct values, and the first LOV page.
 */
void
_bitmap_init(Relation rel, Oid comptypeOid,
			 Oid heapOid, Oid indexOid,
			 Oid heapRelfilenode, Oid indexRelfilenode,
			 bool use_wal)
{
	MIRROREDLOCK_BUFMGR_DECLARE;

	BMMetaPage		metapage;
	Buffer			metabuf;
	Page			page;
	Buffer			buf;
	BMLOVItem 		lovItem;
	OffsetNumber	newOffset;
	Page			currLovPage;
	OffsetNumber	o;
  
	/* sanity check */
	if (RelationGetNumberOfBlocks(rel) != 0)
		ereport(ERROR,
				(errcode(ERRCODE_INDEX_CORRUPTED),
				errmsg("cannot initialize non-empty bitmap index \"%s\"",
				RelationGetRelationName(rel)),
				errSendAlert(true)));
	
	// -------- MirroredLock ----------
	MIRROREDLOCK_BUFMGR_LOCK;
	
	/* create the metapage */
	metabuf = _bitmap_getbuf(rel, P_NEW, BM_WRITE);
	page = BufferGetPage(metabuf);
	Assert(PageIsNew(page));

	/* initialize the LOV metadata */
	_bitmap_create_lov_heapandindex(rel, comptypeOid,
									&(heapOid),
									&(indexOid),
									heapRelfilenode,
									indexRelfilenode);

	START_CRIT_SECTION();

	MarkBufferDirty(metabuf);

	/* initialize the metapage */
	PageInit(page, BufferGetPageSize(metabuf), 0);
	metapage = (BMMetaPage) PageGetContents(page);
	
	metapage->bm_magic = BITMAP_MAGIC;
	metapage->bm_version = BITMAP_VERSION;
	metapage->bm_lov_heapId = heapOid;
	metapage->bm_lov_indexId = indexOid;

	if (use_wal)
		_bitmap_log_metapage(rel, page);

	/* allocate the first LOV page. */
	buf = _bitmap_getbuf(rel, P_NEW, BM_WRITE);
	_bitmap_init_lovpage(rel, buf);

	MarkBufferDirty(buf);

	currLovPage = BufferGetPage(buf);

	/* set the first item to support NULL value */
	lovItem = _bitmap_formitem(0);
	newOffset = OffsetNumberNext(PageGetMaxOffsetNumber(currLovPage));

	/*
	 * XXX: perhaps this could be a special page, with more efficient storage
	 * after all, we have fixed size data
	 */
	o = PageAddItem(currLovPage, (Item)lovItem, sizeof(BMLOVItemData),
                    newOffset, LP_USED);

	if (o == InvalidOffsetNumber)
		ereport(ERROR,
				(errcode(ERRCODE_INTERNAL_ERROR),
				 errmsg("failed to add LOV item to \"%s\"",
				 RelationGetRelationName(rel))));

	metapage->bm_lov_lastpage = BufferGetBlockNumber(buf);

	if(use_wal)
		_bitmap_log_lovitem(rel, buf, newOffset, lovItem, metabuf, true);

	END_CRIT_SECTION();

	_bitmap_wrtbuf(buf);
	_bitmap_wrtbuf(metabuf);
	
	MIRROREDLOCK_BUFMGR_UNLOCK;
	// -------- MirroredLock ----------
	
	pfree(lovItem);
}
コード例 #16
0
ファイル: cdbfilerepprimaryack.c プロジェクト: hsyuan/gpdb
/*
 * Backend checks if acknowledgement that its operation is completed
 * is received from mirror. 
 * If acknowledgement is received (state == FileRepAckStateCompleted) then
 *			a) entry is removed from hash
 *			b) TRUE is returned 
 */
bool 
FileRepAckPrimary_IsOperationCompleted(
					   FileRepIdentifier_u	 fileRepIdentifier,
					   FileRepRelationType_e fileRepRelationType)
{

	FileRepAckHashEntry_s	*entry = NULL;
	bool					isCompleted = FALSE;
	bool					isRemoved;
	FileName				fileName = NULL;
	int						retry = 0;
	bool					retval = FALSE;
	bool					wait = FALSE;

	fileName = FileRep_GetFileName(fileRepIdentifier, fileRepRelationType);
	
	while ((isCompleted == FALSE) && FileRep_IsRetry(retry)) 
	{
		
		LWLockAcquire(FileRepAckHashShmemLock, LW_EXCLUSIVE);
		
		entry = FileRepAckPrimary_LookupHashEntry(fileName);
		
		if (entry == NULL)
		{
			LWLockRelease(FileRepAckHashShmemLock);
			break;
		}
			
		if (! FileRep_IsIpcSleep(entry->fileRepOperation))
		{					
			if (wait == TRUE)
			{	
				wait = FALSE;
			}
		}
							
		switch (entry->fileRepAckState) 
		{
			case FileRepAckStateWaiting:
				/* No Operation */
				break;
			case FileRepAckStateCompleted:
				
				retval = TRUE;
				xLogEof = entry->xLogEof;
				mirrorStatus = entry->mirrorStatus;
				/* no BREAK */
			case FileRepAckStateMirrorInFault:
				
				isCompleted = TRUE;
				
				isRemoved = FileRepAckPrimary_RemoveHashEntry(fileName);
				
				Assert(isRemoved == TRUE);
				
				break;
			default:
				break;
		}
		
		if (isCompleted == false) 
		{
			if (! FileRep_IsIpcSleep(entry->fileRepOperation))
			{					
					fileRepIpcArray[fileRepAckHashShmem->ipcArrayIndex]->refCountSemP++;
					wait = TRUE;
			}
		}
		
		LWLockRelease(FileRepAckHashShmemLock);
		
		if (isCompleted == false) 
		{
			if (FileRepSubProcess_IsStateTransitionRequested())
			{
				break;
			}
			
			if (FileRep_IsIpcSleep(entry->fileRepOperation))
			{					
				FileRep_Sleep1ms(retry);
				
				if (retry == (3 * file_rep_retry / 4))
					ereport(WARNING,
						(errmsg("threshold '75' percent of 'gp_segment_connect_timeout=%d' is reached, "
								"mirror may not be able to keep up with primary, "
								"primary may transition to change tracking",
								gp_segment_connect_timeout),
						errhint("increase guc 'gp_segment_connect_timeout' by 'gpconfig' and 'gpstop -u' "),
						errSendAlert(true)));	

				FileRep_IncrementRetry(retry);
			}
			else
			{
				FileRep_IpcWait(fileRepIpcArray[fileRepAckHashShmem->ipcArrayIndex]->semP, &fileRepIpcArray[fileRepAckHashShmem->ipcArrayIndex]->refCountSemP, FileRepAckHashShmemLock);
			}			
			
			/*
			 * if the message was from the main filerep process then it is a
			 *   graceful shutdown message to the mirror.  We don't want to stall
			 *   shutdown if the mirror is unavailable so we wait a smaller amount
			 *   of time
			 */
			if ( entry->fileRepOperation == FileRepOperationShutdown &&
			     retry == 50)
            {
				FileRepAckPrimary_RemoveHashEntry(fileName);
                break;
            }
		}
	}
	
	if (retval == FALSE) 
	{
		mirrorStatus = FileRepStatusMirrorLossOccurred;
		
		if (! primaryMirrorIsIOSuspended())
		{
			ereport(WARNING,
					(errmsg("mirror failure, "
							"could not complete mirrored request identifier '%s' ack state '%s', "
							"failover requested",
							(fileName == NULL) ? "<null>" : fileName,
							(entry == NULL) ? "<entry not found>" : FileRepAckStateToString[entry->fileRepAckState]),
					 errhint("run gprecoverseg to re-establish mirror connectivity"),
					 FileRep_errdetail_ShmemAck(),
					 FileRep_errcontext()));	
		}
	}
	
	if (fileName) 
	{
		pfree(fileName);
		fileName = NULL;
	}		
	
	return retval;
}
コード例 #17
0
ファイル: postinit.c プロジェクト: qiuyesuifeng/gpdb
/* --------------------------------
 * InitPostgres
 *		Initialize POSTGRES.
 *
 * The database can be specified by name, using the in_dbname parameter, or by
 * OID, using the dboid parameter.	In the latter case, the actual database
 * name can be returned to the caller in out_dbname.  If out_dbname isn't
 * NULL, it must point to a buffer of size NAMEDATALEN.
 *
 * In bootstrap mode no parameters are used.
 *
 * The return value indicates whether the userID is a superuser.  (That
 * can only be tested inside a transaction, so we want to do it during
 * the startup transaction rather than doing a separate one in postgres.c.)
 *
 * As of PostgreSQL 8.2, we expect InitProcess() was already called, so we
 * already have a PGPROC struct ... but it's not filled in yet.
 *
 * Note:
 *		Be very careful with the order of calls in the InitPostgres function.
 * --------------------------------
 */
void
InitPostgres(const char *in_dbname, Oid dboid, const char *username,
			 char *out_dbname)
{
	bool		bootstrap = IsBootstrapProcessingMode();
	bool		autovacuum = IsAutoVacuumProcess();
	bool		am_superuser;
	char	   *fullpath;
	char		dbname[NAMEDATALEN];

	/*
	 * Add my PGPROC struct to the ProcArray.
	 *
	 * Once I have done this, I am visible to other backends!
	 */
	InitProcessPhase2();

	/* Initialize SessionState entry */
	SessionState_Init();
	/* Initialize memory protection */
	GPMemoryProtect_Init();

	/*
	 * Initialize my entry in the shared-invalidation manager's array of
	 * per-backend data.
	 *
	 * Sets up MyBackendId, a unique backend identifier.
	 */
	MyBackendId = InvalidBackendId;

	SharedInvalBackendInit(false);

	if (MyBackendId > MaxBackends || MyBackendId <= 0)
		elog(FATAL, "bad backend id: %d", MyBackendId);

	/* Now that we have a BackendId, we can participate in ProcSignal */
	ProcSignalInit(MyBackendId);

	/*
	 * bufmgr needs another initialization call too
	 */
	InitBufferPoolBackend();

	/*
	 * Initialize local process's access to XLOG.  In bootstrap case we may
	 * skip this since StartupXLOG() was run instead.
	 */
	if (!bootstrap)
		InitXLOGAccess();

	/*
	 * Initialize the relation cache and the system catalog caches.  Note that
	 * no catalog access happens here; we only set up the hashtable structure.
	 * We must do this before starting a transaction because transaction abort
	 * would try to touch these hashtables.
	 */
	RelationCacheInitialize();
	InitCatalogCache();

	/* Initialize portal manager */
	EnablePortalManager();

	/* Initialize stats collection --- must happen before first xact */
	if (!bootstrap)
		pgstat_initialize();

	/*
	 * Load relcache entries for the shared system catalogs.  This must create
	 * at least entries for pg_database and catalogs used for authentication.
	 */
	RelationCacheInitializePhase2();

	/*
	 * Set up process-exit callback to do pre-shutdown cleanup.  This has to
	 * be after we've initialized all the low-level modules like the buffer
	 * manager, because during shutdown this has to run before the low-level
	 * modules start to close down.  On the other hand, we want it in place
	 * before we begin our first transaction --- if we fail during the
	 * initialization transaction, as is entirely possible, we need the
	 * AbortTransaction call to clean up.
	 */
	on_shmem_exit(ShutdownPostgres, 0);

	/* TODO: autovacuum launcher should be done here? */

	/*
	 * Start a new transaction here before first access to db, and get a
	 * snapshot.  We don't have a use for the snapshot itself, but we're
	 * interested in the secondary effect that it sets RecentGlobalXmin.
	 */
	if (!bootstrap)
	{
		StartTransactionCommand();
		(void) GetTransactionSnapshot();
	}

	/*
	 * Figure out our postgres user id, and see if we are a superuser.
	 *
	 * In standalone mode and in the autovacuum process, we use a fixed id,
	 * otherwise we figure it out from the authenticated user name.
	 */
	if (bootstrap || autovacuum)
	{
		InitializeSessionUserIdStandalone();
		am_superuser = true;
	}
	else if (!IsUnderPostmaster)
	{
		InitializeSessionUserIdStandalone();
		am_superuser = true;
		if (!ThereIsAtLeastOneRole())
			ereport(WARNING,
					(errcode(ERRCODE_UNDEFINED_OBJECT),
					 errmsg("no roles are defined in this database system"),
					 errhint("You should immediately run CREATE USER \"%s\" CREATEUSER;.",
							 username)));
	}
	else
	{
		/* normal multiuser case */
		Assert(MyProcPort != NULL);
		PerformAuthentication(MyProcPort);
		InitializeSessionUserId(username);
		am_superuser = superuser();
	}

	/*
	 * Check a normal user hasn't connected to a superuser reserved slot.
	 */
	if (!am_superuser &&
		ReservedBackends > 0 &&
		!HaveNFreeProcs(ReservedBackends))
		ereport(FATAL,
				(errcode(ERRCODE_TOO_MANY_CONNECTIONS),
				 errmsg("connection limit exceeded for non-superusers"),
				 errSendAlert(true)));

	/*
	 * If walsender, we don't want to connect to any particular database. Just
	 * finish the backend startup by processing any options from the startup
	 * packet, and we're done.
	 */
	if (am_walsender)
	{
		Assert(!bootstrap);

		/*
		 * We don't have replication role, which existed in postgres.
		 */
		if (!superuser())
			ereport(FATAL,
					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
					 errmsg("must be superuser role to start walsender")));

		/* process any options passed in the startup packet */
		if (MyProcPort != NULL)
			process_startup_options(MyProcPort, am_superuser);

		/* Apply PostAuthDelay as soon as we've read all options */
		if (PostAuthDelay > 0)
			pg_usleep(PostAuthDelay * 1000000L);

		/* initialize client encoding */
		InitializeClientEncoding();

		/* report this backend in the PgBackendStatus array */
		pgstat_bestart();

		/* close the transaction we started above */
		CommitTransactionCommand();

		return;
	}

	/*
	 * Set up the global variables holding database id and path.  But note we
	 * won't actually try to touch the database just yet.
	 *
	 * We take a shortcut in the bootstrap case, otherwise we have to look up
	 * the db name in pg_database.
	 */
	if (bootstrap)
	{
		MyDatabaseId = TemplateDbOid;
		MyDatabaseTableSpace = DEFAULTTABLESPACE_OID;
	}
	else if (in_dbname != NULL)
	{
		HeapTuple	tuple;
		Form_pg_database dbform;

		tuple = GetDatabaseTuple(in_dbname);
		if (!HeapTupleIsValid(tuple))
			ereport(FATAL,
					(errcode(ERRCODE_UNDEFINED_DATABASE),
					 errmsg("database \"%s\" does not exist", in_dbname)));
		dbform = (Form_pg_database) GETSTRUCT(tuple);
		MyDatabaseId = HeapTupleGetOid(tuple);
		MyDatabaseTableSpace = dbform->dattablespace;
		/* take database name from the caller, just for paranoia */
		strlcpy(dbname, in_dbname, sizeof(dbname));
		pfree(tuple);
	}
	else
	{
		/* caller specified database by OID */
		HeapTuple	tuple;
		Form_pg_database dbform;

		tuple = GetDatabaseTupleByOid(dboid);
		if (!HeapTupleIsValid(tuple))
			ereport(FATAL,
					(errcode(ERRCODE_UNDEFINED_DATABASE),
					 errmsg("database %u does not exist", dboid)));
		dbform = (Form_pg_database) GETSTRUCT(tuple);
		MyDatabaseId = HeapTupleGetOid(tuple);
		MyDatabaseTableSpace = dbform->dattablespace;
		Assert(MyDatabaseId == dboid);
		strlcpy(dbname, NameStr(dbform->datname), sizeof(dbname));
		/* pass the database name back to the caller */
		if (out_dbname)
			strcpy(out_dbname, dbname);
		pfree(tuple);
	}

	/* Now we can mark our PGPROC entry with the database ID */
	/* (We assume this is an atomic store so no lock is needed) */
	MyProc->databaseId = MyDatabaseId;

	/*
	 * Now, take a writer's lock on the database we are trying to connect to.
	 * If there is a concurrently running DROP DATABASE on that database, this
	 * will block us until it finishes (and has committed its update of
	 * pg_database).
	 *
	 * Note that the lock is not held long, only until the end of this startup
	 * transaction.  This is OK since we are already advertising our use of
	 * the database in the PGPROC array; anyone trying a DROP DATABASE after
	 * this point will see us there.
	 *
	 * Note: use of RowExclusiveLock here is reasonable because we envision
	 * our session as being a concurrent writer of the database.  If we had a
	 * way of declaring a session as being guaranteed-read-only, we could use
	 * AccessShareLock for such sessions and thereby not conflict against
	 * CREATE DATABASE.
	 */
	if (!bootstrap)
		LockSharedObject(DatabaseRelationId, MyDatabaseId, 0,
						 RowExclusiveLock);

	/*
	 * Recheck pg_database to make sure the target database hasn't gone away.
	 * If there was a concurrent DROP DATABASE, this ensures we will die
	 * cleanly without creating a mess.
	 */
	if (!bootstrap)
	{
		HeapTuple	tuple;

		tuple = GetDatabaseTuple(dbname);
		if (!HeapTupleIsValid(tuple) ||
			MyDatabaseId != HeapTupleGetOid(tuple) ||
			MyDatabaseTableSpace != ((Form_pg_database) GETSTRUCT(tuple))->dattablespace)
			ereport(FATAL,
					(errcode(ERRCODE_UNDEFINED_DATABASE),
					 errmsg("database \"%s\" does not exist", dbname),
			   errdetail("It seems to have just been dropped or renamed.")));
	}

	fullpath = GetDatabasePath(MyDatabaseId, MyDatabaseTableSpace);

	if (!bootstrap)
	{
		if (access(fullpath, F_OK) == -1)
		{
			if (errno == ENOENT)
				ereport(FATAL,
						(errcode(ERRCODE_UNDEFINED_DATABASE),
						 errmsg("database \"%s\" does not exist",
								dbname),
					errdetail("The database subdirectory \"%s\" is missing.",
							  fullpath)));
			else
				ereport(FATAL,
						(errcode_for_file_access(),
						 errmsg("could not access directory \"%s\": %m",
								fullpath)));
		}

		ValidatePgVersion(fullpath);
	}

	SetDatabasePath(fullpath);

	/*
	 * It's now possible to do real access to the system catalogs.
	 *
	 * Load relcache entries for the system catalogs.  This must create at
	 * least the minimum set of "nailed-in" cache entries.
	 */
	RelationCacheInitializePhase3();

	/*
	 * Now we have full access to catalog including toast tables,
	 * we can process pg_authid.rolconfig.  This ought to come before
	 * processing startup options so that it can override the settings.
	 */
	if (!bootstrap)
		ProcessRoleGUC();

	/* set up ACL framework (so CheckMyDatabase can check permissions) */
	initialize_acl();

	/*
	 * Re-read the pg_database row for our database, check permissions and set
	 * up database-specific GUC settings.  We can't do this until all the
	 * database-access infrastructure is up.  (Also, it wants to know if the
	 * user is a superuser, so the above stuff has to happen first.)
	 */
	if (!bootstrap)
		CheckMyDatabase(dbname, am_superuser);

	/*
	 * Now process any command-line switches and any additional GUC variable
	 * settings passed in the startup packet.	We couldn't do this before
	 * because we didn't know if client is a superuser.
	 */
	if (MyProcPort != NULL)
		process_startup_options(MyProcPort, am_superuser);

	/*
	 * Maintenance Mode: allow superuser to connect when
	 * gp_maintenance_conn GUC is set.  We cannot check it until
	 * process_startup_options parses the GUC.
	 */
	if (gp_maintenance_mode && Gp_role == GP_ROLE_DISPATCH &&
		!(superuser() && gp_maintenance_conn))
		ereport(FATAL,
				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
				 errmsg("maintenance mode: connected by superuser only"),
				 errSendAlert(false)));

	/*
	 * MPP:  If we were started in utility mode then we only want to allow
	 * incoming sessions that specify gp_session_role=utility as well.  This
	 * lets the bash scripts start the QD in utility mode and connect in but
	 * protect ourselves from normal clients who might be trying to connect to
	 * the system while we startup.
	 */
	if ((Gp_role == GP_ROLE_UTILITY) && (Gp_session_role != GP_ROLE_UTILITY))
	{
		ereport(FATAL,
				(errcode(ERRCODE_CANNOT_CONNECT_NOW),
				 errmsg("System was started in master-only utility mode - only utility mode connections are allowed")));
	}

	/* Apply PostAuthDelay as soon as we've read all options */
	if (PostAuthDelay > 0)
		pg_usleep(PostAuthDelay * 1000000L);

	/* set default namespace search path */
	InitializeSearchPath();

	/* initialize client encoding */
	InitializeClientEncoding();

	/* report this backend in the PgBackendStatus array */
	if (!bootstrap)
		pgstat_bestart();
		
	/* 
     * MPP package setup 
     *
     * Primary function is to establish connctions to the qExecs.
     * This is SKIPPED when the database is in bootstrap mode or 
     * Is not UnderPostmaster.
     */
    if (!bootstrap && IsUnderPostmaster)
    {
		cdb_setup();
		on_proc_exit( cdb_cleanup, 0 );
    }

    /* 
     * MPP SharedSnapshot Setup
	 */
	if (Gp_role == GP_ROLE_DISPATCH)
	{
		addSharedSnapshot("Query Dispatcher", gp_session_id);
	}
	else if (Gp_role == GP_ROLE_DISPATCHAGENT)
	{
		SharedLocalSnapshotSlot = NULL;
	}
    else if (Gp_segment == -1 && Gp_role == GP_ROLE_EXECUTE && !Gp_is_writer)
    {
		/* 
		 * Entry db singleton QE is a user of the shared snapshot -- not a creator.
		 * The lookup will occur once the distributed snapshot has been received.
		 */	
		lookupSharedSnapshot("Entry DB Singleton", "Query Dispatcher", gp_session_id);
    }
    else if (Gp_role == GP_ROLE_EXECUTE)
	{
		if (Gp_is_writer)
		{
			addSharedSnapshot("Writer qExec", gp_session_id);
		}
		else
		{
			/*
			 * NOTE: This assumes that the Slot has already been
			 *       allocated by the writer.  Need to make sure we
			 *       always allocate the writer qExec first.
			 */			 			
			lookupSharedSnapshot("Reader qExec", "Writer qExec", gp_session_id);
		}
	}

	/* close the transaction we started above */
	if (!bootstrap)
		CommitTransactionCommand();

	return;
}
コード例 #18
0
ファイル: cdbfilerepprimaryack.c プロジェクト: hsyuan/gpdb
/*
 * FileRepAckPrimary_RunConsumer()
 */
static int
FileRepAckPrimary_RunConsumer(void)
{
	FileRepShmemMessageDescr_s	*fileRepShmemMessageDescr = NULL;
	FileRepMessageHeader_s		*fileRepMessageHeader = NULL;
	pg_crc32					*fileRepMessageHeaderCrc;
	pg_crc32					messageHeaderCrcLocal = 0;
	int							status = STATUS_OK;
	bool						movePositionConsume = FALSE;
	FileRepShmem_s              *fileRepAckShmem = NULL;
		
	FileRep_InsertConfigLogEntry("run consumer");
	
	fileRepAckShmem = fileRepAckShmemArray[FILEREP_ACKSHMEM_MESSAGE_SLOT_PRIMARY_ACK];
	
	while (1) {	
		
		LWLockAcquire(FileRepAckShmemLock, LW_EXCLUSIVE);
		
		if (movePositionConsume) {
			
			fileRepAckShmem->positionConsume = 
				fileRepAckShmem->positionConsume +
				fileRepShmemMessageDescr->messageLength + 
				sizeof(FileRepShmemMessageDescr_s);
			
			if (fileRepAckShmem->positionConsume == fileRepAckShmem->positionWraparound &&
				fileRepAckShmem->positionInsert != fileRepAckShmem->positionWraparound) {
				
				fileRepAckShmem->positionConsume = fileRepAckShmem->positionBegin;
				fileRepAckShmem->positionWraparound = fileRepAckShmem->positionEnd;
			}
			FileRep_IpcSignal(fileRepIpcArray[fileRepAckShmem->ipcArrayIndex]->semP, 
							  &fileRepIpcArray[fileRepAckShmem->ipcArrayIndex]->refCountSemP);
		}
				
		fileRepShmemMessageDescr = 
			(FileRepShmemMessageDescr_s*) fileRepAckShmem->positionConsume;	

		while ((fileRepAckShmem->positionConsume == fileRepAckShmem->positionInsert) ||
			   ((fileRepAckShmem->positionConsume != fileRepAckShmem->positionInsert) &&
				(fileRepShmemMessageDescr->messageState != FileRepShmemMessageStateReady))) {
			
			fileRepIpcArray[fileRepAckShmem->ipcArrayIndex]->refCountSemC++;

			LWLockRelease(FileRepAckShmemLock);
						
			FileRepSubProcess_ProcessSignals();
			if (FileRepSubProcess_GetState() != FileRepStateReady &&
				FileRepSubProcess_GetState() != FileRepStateInitialization) {
				LWLockAcquire(FileRepAckShmemLock, LW_EXCLUSIVE);
				break;
			}
			
			FileRep_IpcWait(fileRepIpcArray[fileRepAckShmem->ipcArrayIndex]->semC, &fileRepIpcArray[fileRepAckShmem->ipcArrayIndex]->refCountSemC, FileRepAckShmemLock);
			
			LWLockAcquire(FileRepAckShmemLock, LW_EXCLUSIVE);
			
			if (fileRepAckShmem->positionConsume == fileRepAckShmem->positionWraparound &&
				fileRepAckShmem->positionInsert != fileRepAckShmem->positionWraparound) {
				
				fileRepAckShmem->positionConsume = fileRepAckShmem->positionBegin;
				fileRepAckShmem->positionWraparound = fileRepAckShmem->positionEnd;
			}
			
			/* Re-assign to find if messageState is changed */
			fileRepShmemMessageDescr = 
				(FileRepShmemMessageDescr_s*) fileRepAckShmem->positionConsume;	
				
		} // internal while
		fileRepAckShmem->consumeCount++;
		LWLockRelease(FileRepAckShmemLock);
		
		FileRepSubProcess_ProcessSignals();
		if (FileRepSubProcess_GetState() != FileRepStateReady && 
			FileRepSubProcess_GetState() != FileRepStateInitialization) {
			break;
		}
		
		SIMPLE_FAULT_INJECTOR(FileRepConsumer);
		
		/* Calculate and compare FileRepMessageHeader_s Crc */
		fileRepMessageHeader = (FileRepMessageHeader_s*) (fileRepAckShmem->positionConsume + 
														  sizeof(FileRepShmemMessageDescr_s));
		
		FileRep_CalculateCrc((char *) fileRepMessageHeader,
							 sizeof(FileRepMessageHeader_s),
							 &messageHeaderCrcLocal);	
		
		fileRepMessageHeaderCrc =
			(pg_crc32 *) (fileRepAckShmem->positionConsume + 
						  sizeof(FileRepMessageHeader_s) + 
						  sizeof(FileRepShmemMessageDescr_s));
		
		if (*fileRepMessageHeaderCrc != messageHeaderCrcLocal) 
		{
			status = STATUS_ERROR;
			ereport(WARNING,
					(errmsg("mirror failure, "
							"could not match ack message header checksum between primary '%u' and mirror '%u', "
							"failover requested", 
							*fileRepMessageHeaderCrc, 
							messageHeaderCrcLocal),
					 errhint("run gprecoverseg to re-establish mirror connectivity"),
					 FileRep_errdetail(fileRepMessageHeader->fileRepIdentifier,
									   fileRepMessageHeader->fileRepRelationType,
									   fileRepMessageHeader->fileRepOperation,
									   fileRepMessageHeader->messageCount),
					 FileRep_errdetail_ShmemAck(),
					 FileRep_errcontext()));		
						
			break;
		}
				
	    /* Write operation is never acknowledged. 
		 * That means message should never have body. 
		 * CRC of body should be always 0.
		 */
		Assert(fileRepMessageHeader->fileRepOperation != FileRepOperationWrite);
		Assert(fileRepMessageHeader->fileRepMessageBodyCrc == 0);
		
		switch (fileRepMessageHeader->fileRepOperation)
		{
			case FileRepOperationReconcileXLogEof:			
				xLogEof = fileRepMessageHeader->fileRepOperationDescription.reconcile.xLogEof;

				if (Debug_filerep_print)
					ereport(LOG,
						(errmsg("ack reconcile xlogid '%d' xrecoff '%d' ",
							xLogEof.xlogid, 
							xLogEof.xrecoff)));	

				break;
		
			case FileRepOperationValidation:
				mirrorStatus = fileRepMessageHeader->fileRepOperationDescription.validation.mirrorStatus;

				if (Debug_filerep_print)
					ereport(LOG,
						(errmsg("ack validation status '%s' ",
							FileRepStatusToString[mirrorStatus])));	

				break;
				
			case FileRepOperationCreate:
				mirrorStatus = fileRepMessageHeader->fileRepOperationDescription.create.mirrorStatus;

				if (Debug_filerep_print)
					ereport(LOG,
						(errmsg("ack create status '%s' ",
								FileRepStatusToString[mirrorStatus])));	

				break;

			case FileRepOperationStartSlruChecksum:
				mirrorStatus =
					fileRepMessageHeader->fileRepOperationDescription.startChecksum.mirrorStatus;

				if (Debug_filerep_print)
				{
					ereport(LOG,
						(errmsg("ack start SLRU checksum: status = '%s', directory = '%s' ",
								FileRepStatusToString[mirrorStatus],
								fileRepMessageHeader->fileRepIdentifier.fileRepFlatFileIdentifier.directorySimpleName)));
				}

				break;

			case FileRepOperationVerifySlruDirectoryChecksum:
				mirrorStatus =
					fileRepMessageHeader->fileRepOperationDescription.verifyDirectoryChecksum.mirrorStatus;

				if (Debug_filerep_print)
				{
					ereport(LOG,
						(errmsg("ack verify SLRU directory checksum: status = '%s', directory = '%s' ",
								FileRepStatusToString[mirrorStatus],
								fileRepMessageHeader->fileRepIdentifier.fileRepFlatFileIdentifier.directorySimpleName)));
				}

				break;
				
			default:
				break;
		}
		
		if (fileRepMessageHeader->fileRepAckState != FileRepAckStateCompleted) {

			status = STATUS_ERROR;
			
			ereport(WARNING,
					(errmsg("mirror failure, "
							"could not complete operation on mirror ack state '%s', "
							"failover requested", 
							FileRepAckStateToString[fileRepMessageHeader->fileRepAckState]),
					 errhint("run gprecoverseg to re-establish mirror connectivity"),
					 errSendAlert(true),
					 FileRep_errdetail(fileRepMessageHeader->fileRepIdentifier,
									   fileRepMessageHeader->fileRepRelationType,
									   fileRepMessageHeader->fileRepOperation,
									   fileRepMessageHeader->messageCount),
					 FileRep_errdetail_Shmem(),
					 FileRep_errdetail_ShmemAck(),
					 FileRep_errcontext()));	
			
			/* 
			 * FAULT has to be set before entry is updated in ack hash table
			 * in order to suspend backend process.
			 */	
			FileRep_SetSegmentState(SegmentStateFault, FaultTypeMirror);
			FileRepSubProcess_ProcessSignals();
		}
				
		if (FileRepAckPrimary_UpdateHashEntry(
				fileRepMessageHeader->fileRepIdentifier,
				fileRepMessageHeader->fileRepRelationType,
				fileRepMessageHeader->fileRepAckState) != STATUS_OK) {
			
			status = STATUS_ERROR;
			ereport(WARNING,
					(errmsg("mirror failure, "
							"could not update ack state '%s' in ack hash table, "
							"failover requested", 
							FileRepAckStateToString[fileRepMessageHeader->fileRepAckState]),
					 errhint("run gprecoverseg to re-establish mirror connectivity"),
					 errSendAlert(true),
					 FileRep_errdetail(fileRepMessageHeader->fileRepIdentifier,
									   fileRepMessageHeader->fileRepRelationType,
									   fileRepMessageHeader->fileRepOperation,
									   fileRepMessageHeader->messageCount),
					 FileRep_errdetail_Shmem(),
					 FileRep_errdetail_ShmemAck(),
					 FileRep_errcontext()));					
		}
	
		FileRep_InsertLogEntry(
							   "P_RunConsumer",
							   fileRepMessageHeader->fileRepIdentifier,
							   fileRepMessageHeader->fileRepRelationType,
							   fileRepMessageHeader->fileRepOperation,
							   messageHeaderCrcLocal,
							   fileRepMessageHeader->fileRepMessageBodyCrc,
							   fileRepMessageHeader->fileRepAckState,
							   FILEREP_UNDEFINED,
							   fileRepMessageHeader->messageCount);				
		
		if (status != STATUS_OK) {
			break;
		}
				
		movePositionConsume = TRUE;		
	} // while(1)	
	
	return status;
}
コード例 #19
0
ファイル: cdbfts.c プロジェクト: BALDELab/incubator-hawq
void
disableQDMirroring(char *detail, char *errorMessage, QDMIRRORDisabledReason disabledReason)
{
	struct timeval lastLogTimeVal;

	Assert(ftsQDMirrorInfo != NULL);

	LWLockAcquire(ftsQDMirrorLock, LW_EXCLUSIVE);

	/*
	 * Don't overwrite.
	 */
	if (ftsQDMirrorInfo->state != QDMIRROR_STATE_DISABLED)
	{
		ftsQDMirrorInfo->state = QDMIRROR_STATE_DISABLED;
		ftsQDMirrorInfo->disabledReason = disabledReason;

		switch (disabledReason)
		{
			case QDMIRROR_DISABLEDREASON_TOOFARBEHIND:
			case QDMIRROR_DISABLEDREASON_CONNECTIONERROR:
			case QDMIRROR_DISABLEDREASON_WALSENDSERVERERROR:
			case QDMIRROR_DISABLEDREASON_ADMINISTRATORDISABLED:
			case QDMIRROR_DISABLEDREASON_UNEXPECTEDERROR:
				if (disabledReason == QDMIRROR_DISABLEDREASON_ADMINISTRATORDISABLED)
					ereport(NOTICE,
							(errcode(ERRCODE_GP_INTERCONNECTION_ERROR),
							 errmsg("Master mirroring not synchronized because the standby master was not started by the administrator")));
				else
					ereport(WARNING,
							(errcode(ERRCODE_GP_INTERCONNECTION_ERROR),
							 errSendAlert(true),
							 errmsg("Master mirroring synchronization lost"),
							 errdetail("%s\nThe Greenplum Database is no longer highly available.", detail)));

				gettimeofday(&lastLogTimeVal, NULL);

				ftsQDMirrorInfo->QDMirroringNotSynchronizedWarningGiven = true;

				if (ftsQDMirrorInfo->valid)
				{
					/*
					 * Only do the update if we need to.
					 */
					ftsQDMirrorInfo->updateMask |= QDMIRROR_UPDATEMASK_VALIDFLAG;
				}
				ftsQDMirrorInfo->updateMask |= QDMIRROR_UPDATEMASK_MASTERMIRRORING;

				ftsQDMirrorInfo->lastLogTimeVal = lastLogTimeVal;

				/*
				 * Not specified or too long error message string will end up NULL
				 * in gp_master_mirroring table.
				 */
				if (errorMessage == NULL ||
					strlen(errorMessage) + 1 >= sizeof(ftsQDMirrorInfo->errorMessage))
					strcpy(ftsQDMirrorInfo->errorMessage, "");
				else
					strcpy(ftsQDMirrorInfo->errorMessage, errorMessage);
				break;

			case QDMIRROR_DISABLEDREASON_SHUTDOWN:
				break;

			default:
				elog(ERROR, "Unknown disabled reason %d", (int)disabledReason);
		}
	}

	LWLockRelease(ftsQDMirrorLock);
}
コード例 #20
0
ファイル: hashutil.c プロジェクト: AnLingm/gpdb
/*
 * _hash_checkpage -- sanity checks on the format of all hash pages
 */
void
_hash_checkpage(Relation rel, Buffer buf, int flags)
{
	Page		page = BufferGetPage(buf);

	/*
	 * ReadBuffer verifies that every newly-read page passes
	 * PageHeaderIsValid, which means it either contains a reasonably sane
	 * page header or is all-zero.	We have to defend against the all-zero
	 * case, however.
	 */
	if (PageIsNew(page))
		ereport(ERROR,
				(errcode(ERRCODE_INDEX_CORRUPTED),
			 errmsg("index \"%s\" contains unexpected zero page at block %u",
					RelationGetRelationName(rel),
					BufferGetBlockNumber(buf)),
				 errhint("Please REINDEX it."),
				 errSendAlert(true)));

	/*
	 * Additionally check that the special area looks sane.
	 */
	if (((PageHeader) (page))->pd_special !=
		(BLCKSZ - MAXALIGN(sizeof(HashPageOpaqueData))))
		ereport(ERROR,
				(errcode(ERRCODE_INDEX_CORRUPTED),
				 errmsg("index \"%s\" contains corrupted page at block %u",
						RelationGetRelationName(rel),
						BufferGetBlockNumber(buf)),
				 errhint("Please REINDEX it."),
				 errSendAlert(true)));

	if (flags)
	{
		HashPageOpaque opaque = (HashPageOpaque) PageGetSpecialPointer(page);

		if ((opaque->hasho_flag & flags) == 0)
			ereport(ERROR,
					(errcode(ERRCODE_INDEX_CORRUPTED),
				   errmsg("index \"%s\" contains corrupted page at block %u",
						  RelationGetRelationName(rel),
						  BufferGetBlockNumber(buf)),
					 errhint("Please REINDEX it."),
					 errSendAlert(true)));
	}

	/*
	 * When checking the metapage, also verify magic number and version.
	 */
	if (flags == LH_META_PAGE)
	{
		HashMetaPage metap = (HashMetaPage) page;

		if (metap->hashm_magic != HASH_MAGIC)
			ereport(ERROR,
					(errcode(ERRCODE_INDEX_CORRUPTED),
					 errmsg("index \"%s\" is not a hash index",
							RelationGetRelationName(rel))));

		if (metap->hashm_version != HASH_VERSION)
			ereport(ERROR,
					(errcode(ERRCODE_INDEX_CORRUPTED),
					 errmsg("index \"%s\" has wrong hash version",
							RelationGetRelationName(rel)),
					 errhint("Please REINDEX it."),
					 errSendAlert(true)));
	}
}
コード例 #21
0
ファイル: fts.c プロジェクト: LJoNe/gpdb
/**
 * Marks the given db as in-sync in the segment configuration.
 */
void
FtsMarkSegmentsInSync(CdbComponentDatabaseInfo *primary, CdbComponentDatabaseInfo *mirror)
{
	if (!FTS_STATUS_ISALIVE(primary->dbid, ftsProbeInfo->fts_status) ||
	    !FTS_STATUS_ISALIVE(mirror->dbid, ftsProbeInfo->fts_status) ||
	    !FTS_STATUS_ISPRIMARY(primary->dbid, ftsProbeInfo->fts_status) ||
 	    FTS_STATUS_ISPRIMARY(mirror->dbid, ftsProbeInfo->fts_status) ||
	    FTS_STATUS_IS_SYNCED(primary->dbid, ftsProbeInfo->fts_status) ||
	    FTS_STATUS_IS_SYNCED(mirror->dbid, ftsProbeInfo->fts_status) ||
	    FTS_STATUS_IS_CHANGELOGGING(primary->dbid, ftsProbeInfo->fts_status) ||
	    FTS_STATUS_IS_CHANGELOGGING(mirror->dbid, ftsProbeInfo->fts_status))
	{
		FtsRequestPostmasterShutdown(primary, mirror);
	}

	if (ftsProbeInfo->fts_pauseProbes)
	{
		return;
	}

	uint8	segStatus=0;
	Relation configrel;
	Relation histrel;
	ScanKeyData scankey;
	SysScanDesc sscan;
	HeapTuple configtuple;
	HeapTuple newtuple;
	HeapTuple histtuple;
	Datum configvals[Natts_gp_segment_configuration];
	bool confignulls[Natts_gp_segment_configuration] = { false };
	bool repls[Natts_gp_segment_configuration] = { false };
	Datum histvals[Natts_gp_configuration_history];
	bool histnulls[Natts_gp_configuration_history] = { false };
	char *desc = "FTS: changed segment to insync from resync.";
	/*
	 * Commit/abort transaction below will destroy
	 * CurrentResourceOwner.  We need it for catalog reads.
	 */
	ResourceOwner save = CurrentResourceOwner;
	StartTransactionCommand();

	/* update primary */
	segStatus = ftsProbeInfo->fts_status[primary->dbid];
	segStatus |= FTS_STATUS_SYNCHRONIZED;
	ftsProbeInfo->fts_status[primary->dbid] = segStatus;

	/* update mirror */
	segStatus = ftsProbeInfo->fts_status[mirror->dbid];
	segStatus |= FTS_STATUS_SYNCHRONIZED;
	ftsProbeInfo->fts_status[mirror->dbid] = segStatus;

	histrel = heap_open(GpConfigHistoryRelationId,
						RowExclusiveLock);
	configrel = heap_open(GpSegmentConfigRelationId,
						  RowExclusiveLock);

	/* update gp_segment_configuration to insync */
	ScanKeyInit(&scankey,
				Anum_gp_segment_configuration_dbid,
				BTEqualStrategyNumber, F_INT2EQ,
				Int16GetDatum(primary->dbid));
	sscan = systable_beginscan(configrel, GpSegmentConfigDbidIndexId,
							   true, SnapshotNow, 1, &scankey);
	configtuple = systable_getnext(sscan);
	if (!HeapTupleIsValid(configtuple))
	{
		elog(ERROR,"FTS cannot find dbid (%d, %d) in %s", primary->dbid,
			 mirror->dbid, RelationGetRelationName(configrel));
	}
	configvals[Anum_gp_segment_configuration_mode-1] = CharGetDatum('s');
	repls[Anum_gp_segment_configuration_mode-1] = true;
	newtuple = heap_modify_tuple(configtuple, RelationGetDescr(configrel),
								 configvals, confignulls, repls);
	simple_heap_update(configrel, &configtuple->t_self, newtuple);
	CatalogUpdateIndexes(configrel, newtuple);

	systable_endscan(sscan);

	ScanKeyInit(&scankey,
				Anum_gp_segment_configuration_dbid,
				BTEqualStrategyNumber, F_INT2EQ,
				Int16GetDatum(mirror->dbid));
	sscan = systable_beginscan(configrel, GpSegmentConfigDbidIndexId,
							   true, SnapshotNow, 1, &scankey);
	configtuple = systable_getnext(sscan);
	if (!HeapTupleIsValid(configtuple))
	{
		elog(ERROR,"FTS cannot find dbid (%d, %d) in %s", primary->dbid,
			 mirror->dbid, RelationGetRelationName(configrel));
	}
	newtuple = heap_modify_tuple(configtuple, RelationGetDescr(configrel),
								 configvals, confignulls, repls);
	simple_heap_update(configrel, &configtuple->t_self, newtuple);
	CatalogUpdateIndexes(configrel, newtuple);

	systable_endscan(sscan);

	/* update configuration history */
	histvals[Anum_gp_configuration_history_time-1] =
			TimestampTzGetDatum(GetCurrentTimestamp());
	histvals[Anum_gp_configuration_history_dbid-1] =
			Int16GetDatum(primary->dbid);
	histvals[Anum_gp_configuration_history_desc-1] =
				CStringGetTextDatum(desc);
	histtuple = heap_form_tuple(RelationGetDescr(histrel), histvals, histnulls);
	simple_heap_insert(histrel, histtuple);
	CatalogUpdateIndexes(histrel, histtuple);

	histvals[Anum_gp_configuration_history_dbid-1] =
			Int16GetDatum(mirror->dbid);
	histtuple = heap_form_tuple(RelationGetDescr(histrel), histvals, histnulls);
	simple_heap_insert(histrel, histtuple);
	CatalogUpdateIndexes(histrel, histtuple);
	ereport(LOG,
			(errmsg("FTS: resynchronization of mirror (dbid=%d, content=%d) on %s:%d has completed.",
					mirror->dbid, mirror->segindex, mirror->address, mirror->port ),
			 errSendAlert(true)));

	heap_close(histrel, RowExclusiveLock);
	heap_close(configrel, RowExclusiveLock);
	/*
	 * Do not block shutdown.  We will always get a change to update
	 * gp_segment_configuration in subsequent probes upon database
	 * restart.
	 */
	if (shutdown_requested)
	{
		elog(LOG, "Shutdown in progress, ignoring FTS prober updates.");
		return;
	}
	CommitTransactionCommand();
	CurrentResourceOwner = save;
}