Exemple #1
0
/*
 * Initialize timezone library
 *
 * This is called after initial loading of postgresql.conf.  If no TimeZone
 * setting was found therein, we try to derive one from the environment.
 * Likewise for log_timezone.
 */
void
pg_timezone_initialize(void)
{
	pg_tz	   *def_tz = NULL;

	/* Do we need to try to figure the session timezone? */
	if (pg_strcasecmp(GetConfigOption("timezone", false), "UNKNOWN") == 0)
	{
		/* Select setting */
		def_tz = select_default_timezone();
		session_timezone = def_tz;
		/* Tell GUC about the value. Will redundantly call pg_tzset() */
		SetConfigOption("timezone", pg_get_timezone_name(def_tz),
						PGC_POSTMASTER, PGC_S_ARGV);
	}

	/* What about the log timezone? */
	if (pg_strcasecmp(GetConfigOption("log_timezone", false), "UNKNOWN") == 0)
	{
		/* Select setting, but don't duplicate work */
		if (!def_tz)
			def_tz = select_default_timezone();
		log_timezone = def_tz;
		/* Tell GUC about the value. Will redundantly call pg_tzset() */
		SetConfigOption("log_timezone", pg_get_timezone_name(def_tz),
						PGC_POSTMASTER, PGC_S_ARGV);
	}
}
Exemple #2
0
/*
 * Initialize timezone library
 *
 * This is called after initial loading of postgresql.conf.  If no TimeZone
 * setting was found therein, we try to derive one from the environment.
 * Likewise for log_timezone.
 *
 * Note: this is also called from ProcessConfigFile, to re-establish valid
 * GUC settings if the GUCs have been reset to default following their
 * removal from postgresql.conf.
 */
void
pg_timezone_initialize(void)
{
	pg_tz	   *def_tz = NULL;

	/*
	 * Make sure that session_timezone and log_timezone are set.
	 * (session_timezone could still be NULL even if a timezone value was set
	 * in postgresql.conf, if that setting was interval-based rather than
	 * timezone-based.)
	 */
	if (!session_timezone)
	{
		def_tz = select_default_timezone();
		session_timezone = def_tz;
	}
	if (!log_timezone)
	{
		/* Don't duplicate work */
		if (!def_tz)
			def_tz = select_default_timezone();
		log_timezone = def_tz;
	}

	/*
	 * Now, set the timezone and log_timezone GUCs if they're still default.
	 * (This will redundantly call pg_tzset().)
	 *
	 * We choose to label these values PGC_S_ENV_VAR, rather than
	 * PGC_S_DYNAMIC_DEFAULT which would be functionally equivalent, because
	 * they came either from getenv("TZ") or from libc behavior that's
	 * determined by process environment of some kind.
	 *
	 * Note: in the case where a setting has just been removed from
	 * postgresql.conf, this code will not do what you might expect, namely
	 * call select_default_timezone() and install that value as the setting.
	 * Rather, the previously active setting --- typically the one from
	 * postgresql.conf --- will be reinstalled, relabeled as PGC_S_ENV_VAR. If
	 * we did try to install the "correct" default value, the effect would be
	 * that each postmaster child would independently run an extremely
	 * expensive search of the timezone database, bringing the database to its
	 * knees for possibly multiple seconds.  This is so unpleasant, and could
	 * so easily be triggered quite unintentionally, that it seems better to
	 * violate the principle of least astonishment.
	 */
	if (GetConfigOptionResetString("timezone") == NULL)
		SetConfigOption("timezone", pg_get_timezone_name(session_timezone),
						PGC_POSTMASTER, PGC_S_ENV_VAR);

	if (GetConfigOptionResetString("log_timezone") == NULL)
		SetConfigOption("log_timezone", pg_get_timezone_name(log_timezone),
						PGC_POSTMASTER, PGC_S_ENV_VAR);
}
/*
 * NormalizeWorkerListPath converts the path configured via
 * citus.worker_list_file into an absolute path, falling back to the default
 * value if necessary. The previous value of the config variable is
 * overwritten with the normalized value.
 *
 * NB: This has to be called before ChangeToDataDir() is called as otherwise
 * the relative paths won't make much sense to the user anymore.
 */
static void
NormalizeWorkerListPath(void)
{
	char *absoluteFileName = NULL;

	if (WorkerListFileName != NULL)
	{
		absoluteFileName = make_absolute_path(WorkerListFileName);
	}
	else if (DataDir != NULL)
	{
		absoluteFileName = malloc(strlen(DataDir) + strlen(WORKER_LIST_FILENAME) + 2);
		if (absoluteFileName == NULL)
		{
			ereport(FATAL, (errcode(ERRCODE_OUT_OF_MEMORY),
							errmsg("out of memory")));
		}

		sprintf(absoluteFileName, "%s/%s", DataDir, WORKER_LIST_FILENAME);
	}
	else
	{
		ereport(FATAL, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
						errmsg("%s does not know where to find the \"worker_list_file\" "
							   "configuration file.\n"
							   "This can be specified as \"citus.worker_list_file\" in "
							   "\"%s\", or by the -D invocation option, or by the PGDATA "
							   "environment variable.\n", progname, ConfigFileName)));
	}

	SetConfigOption("citus.worker_list_file", absoluteFileName, PGC_POSTMASTER,
					PGC_S_OVERRIDE);
	free(absoluteFileName);
}
Exemple #4
0
void CoreConfig::OnRootConsoleCommand(const char *cmdname, const CCommand &command)
{
	int argcount = command.ArgC();
	if (argcount >= 4)
	{
		const char *option = command.Arg(2);
		const char *value = command.Arg(3);

		char error[255];

		ConfigResult res = SetConfigOption(option, value, ConfigSource_Console, error, sizeof(error));

		if (res == ConfigResult_Reject)
		{
			g_RootMenu.ConsolePrint("[SM] Could not set config option \"%s\" to \"%s\" (%s)", option, value, error);
		} else if (res == ConfigResult_Ignore) {
			g_RootMenu.ConsolePrint("[SM] No such config option \"%s\" exists.", option);
		} else {
			g_RootMenu.ConsolePrint("Config option \"%s\" successfully set to \"%s.\"", option, value);
		}

		return;
	}

	g_RootMenu.ConsolePrint("[SM] Usage: sm config <option> <value>");
}
Exemple #5
0
/*
 * Process any command-line switches and any additional GUC variable
 * settings passed in the startup packet.
 */
static void
process_startup_options(Port *port, bool am_superuser)
{
    GucContext	gucctx;
    ListCell   *gucopts;

    gucctx = am_superuser ? PGC_SUSET : PGC_BACKEND;

    /*
     * First process any command-line switches that were included in the
     * startup packet, if we are in a regular backend.
     */
    if (port->cmdline_options != NULL)
    {
        /*
         * The maximum possible number of commandline arguments that could
         * come from port->cmdline_options is (strlen + 1) / 2; see
         * pg_split_opts().
         */
        char	  **av;
        int			maxac;
        int			ac;

        maxac = 2 + (strlen(port->cmdline_options) + 1) / 2;

        av = (char **) palloc(maxac * sizeof(char *));
        ac = 0;

        av[ac++] = "postgres";

        /* Note this mangles port->cmdline_options */
        pg_split_opts(av, &ac, port->cmdline_options);

        av[ac] = NULL;

        Assert(ac < maxac);

        (void) process_postgres_switches(ac, av, gucctx, NULL);
    }

    /*
     * Process any additional GUC variable settings passed in startup packet.
     * These are handled exactly like command-line variables.
     */
    gucopts = list_head(port->guc_options);
    while (gucopts)
    {
        char	   *name;
        char	   *value;

        name = lfirst(gucopts);
        gucopts = lnext(gucopts);

        value = lfirst(gucopts);
        gucopts = lnext(gucopts);

        SetConfigOption(name, value, gucctx, PGC_S_CLIENT);
    }
}
Exemple #6
0
/*
 * Initialize timezone library
 *
 * This is called after initial loading of postgresql.conf.  If no TimeZone
 * setting was found therein, we try to derive one from the environment.
 * Likewise for log_timezone.
 */
void
pg_timezone_initialize(void)
{
	pg_tz	   *def_tz = NULL;

	/*
	 * Make sure that session_timezone and log_timezone are set.
	 * (session_timezone could still be NULL even if a timezone value was set
	 * in postgresql.conf, if that setting was interval-based rather than
	 * timezone-based.)
	 */
	if (!session_timezone)
	{
		def_tz = select_default_timezone();
		session_timezone = def_tz;
	}
	if (!log_timezone)
	{
		/* Don't duplicate work */
		if (!def_tz)
			def_tz = select_default_timezone();
		log_timezone = def_tz;
	}

	/* Now, set the timezone GUC if it's not already set */
	if (GetConfigOption("timezone", false) == NULL)
	{
		/* Tell GUC about the value. Will redundantly call pg_tzset() */
		SetConfigOption("timezone", pg_get_timezone_name(session_timezone),
						PGC_POSTMASTER, PGC_S_ENV_VAR);
	}

	/* Likewise for log timezone */
	if (GetConfigOption("log_timezone", false) == NULL)
	{
		/* Tell GUC about the value. Will redundantly call pg_tzset() */
		SetConfigOption("log_timezone", pg_get_timezone_name(log_timezone),
						PGC_POSTMASTER, PGC_S_ENV_VAR);
	}
}
Exemple #7
0
/* set_curcfg(text) */
Datum
tsa_set_curcfg_byname(PG_FUNCTION_ARGS)
{
	text	   *arg0 = PG_GETARG_TEXT_PP(0);
	char	   *name;

	name = text_to_cstring(arg0);

	SetConfigOption("default_text_search_config", name,
					PGC_USERSET, PGC_S_SESSION);

	PG_RETURN_VOID();
}
Exemple #8
0
SMCResult CoreConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value)
{
	char error[255];
	ConfigResult err = SetConfigOption(key, value, ConfigSource_File, error, sizeof(error));

	if (err == ConfigResult_Reject)
	{
		/* This is a fatal error */
		g_Logger.LogFatal("Config error (key: %s) (value: %s) %s", key, value, error);
	}

	return SMCResult_Continue;
}
Exemple #9
0
/*
 * Initialize timezone library
 *
 * This is called after initial loading of postgresql.conf.  If no TimeZone
 * setting was found therein, we try to derive one from the environment.
 */
void
pg_timezone_initialize(void)
{
	/* Do we need to try to figure the timezone? */
	if (pg_strcasecmp(GetConfigOption("timezone"), "UNKNOWN") == 0)
	{
		const char *def_tz;

		/* Select setting */
		def_tz = select_default_timezone();
		/* Tell GUC about the value. Will redundantly call pg_tzset() */
		SetConfigOption("timezone", def_tz, PGC_POSTMASTER, PGC_S_ARGV);
	}
}
Exemple #10
0
/* set_curcfg(int) */
Datum
tsa_set_curcfg(PG_FUNCTION_ARGS)
{
	Oid			arg0 = PG_GETARG_OID(0);
	char	   *name;

	name = DatumGetCString(DirectFunctionCall1(regconfigout,
											   ObjectIdGetDatum(arg0)));

	SetConfigOption("default_text_search_config", name,
					PGC_USERSET, PGC_S_SESSION);

	PG_RETURN_VOID();
}
Exemple #11
0
/*
 * Deprecated function.
 * Use "pg_trgm.similarity_threshold" GUC variable instead of this function.
 */
Datum
set_limit(PG_FUNCTION_ARGS)
{
	float4		nlimit = PG_GETARG_FLOAT4(0);
	char	   *nlimit_str;
	Oid			func_out_oid;
	bool		is_varlena;

	getTypeOutputInfo(FLOAT4OID, &func_out_oid, &is_varlena);

	nlimit_str = OidOutputFunctionCall(func_out_oid, Float4GetDatum(nlimit));

	SetConfigOption("pg_trgm.similarity_threshold", nlimit_str,
					PGC_USERSET, PGC_S_SESSION);

	PG_RETURN_FLOAT4(similarity_threshold);
}
Exemple #12
0
void Gamestate_Start(struct Game *game, struct dosowiskoResources* data) {
	  al_set_sample_instance_gain(game->data->muzyczka.instance.drums, 0.0);
		al_set_sample_instance_gain(game->data->muzyczka.instance.fg, 0.0);
		al_set_sample_instance_gain(game->data->muzyczka.instance.bg, 1.5);

		char *end = "";
		data->score = strtol(GetConfigOptionDefault(game, "Mediator", "score", "0"), &end, 10);

		if (game->data->mediator.score > data->score) {
			  char text[255];
				snprintf(text, 255, "%d", game->data->mediator.score);
				SetConfigOption(game, "Mediator", "score", text);
				data->score = game->data->mediator.score;
		}

		al_ungrab_mouse();
		if (!game->config.fullscreen) al_show_mouse_cursor(game->display);

		al_play_sample_instance(data->sound);

}
Exemple #13
0
void Gamestate_ProcessEvent(struct Game *game, struct MenuResources* data, ALLEGRO_EVENT *ev) {

	if ((data->menustate == MENUSTATE_ABOUT) && (ev->type == ALLEGRO_EVENT_KEY_DOWN)) {
		ChangeMenuState(game, data, MENUSTATE_MAIN);
		return;
	}

	if (ev->type != ALLEGRO_EVENT_KEY_DOWN) return;

	if (data->starting) return;

	if (ev->keyboard.keycode==ALLEGRO_KEY_UP) {
		data->selected--;
		if ((data->selected == 2) && ((data->menustate==MENUSTATE_VIDEO) || (data->menustate==MENUSTATE_OPTIONS) || (data->menustate==MENUSTATE_AUDIO))) {
			data->selected --;
		}
		if ((data->menustate==MENUSTATE_VIDEO) && (data->selected==1) && (data->options.fullscreen)) data->selected--;
		al_play_sample_instance(data->click);
	} else if (ev->keyboard.keycode==ALLEGRO_KEY_DOWN) {
		data->selected++;
		if ((data->menustate==MENUSTATE_VIDEO) && (data->selected==1) && (data->options.fullscreen)) data->selected++;
		if ((data->selected == 2) && ((data->menustate==MENUSTATE_VIDEO) || (data->menustate==MENUSTATE_OPTIONS) || (data->menustate==MENUSTATE_AUDIO))) {
			data->selected ++;
		}


		al_play_sample_instance(data->click);
	}

	if (ev->keyboard.keycode==ALLEGRO_KEY_ENTER) {
		char *text;
		al_play_sample_instance(data->click);
		switch (data->menustate) {
			case MENUSTATE_MAIN:
				switch (data->selected) {
					case 0:
						StartGame(game, data);
						break;
					case 1:
						ChangeMenuState(game,data,MENUSTATE_OPTIONS);
						break;
					case 2:
						ChangeMenuState(game,data,MENUSTATE_ABOUT);
						break;
					case 3:
						UnloadGamestate(game, "menu");
						break;
				}
				break;
			case MENUSTATE_HIDDEN:
				ChangeMenuState(game,data,MENUSTATE_MAIN);
				break;
			case MENUSTATE_AUDIO:
				text = malloc(255*sizeof(char));
				switch (data->selected) {
					case 0:
						game->config.music--;
						if (game->config.music<0) game->config.music=10;
						snprintf(text, 255, "%d", game->config.music);
						SetConfigOption(game, "SuperDerpy", "music", text);
						al_set_mixer_gain(game->audio.music, game->config.music/10.0);
						break;
					case 1:
						game->config.fx--;
						if (game->config.fx<0) game->config.fx=10;
						snprintf(text, 255, "%d", game->config.fx);
						SetConfigOption(game, "SuperDerpy", "fx", text);
						al_set_mixer_gain(game->audio.fx, game->config.fx/10.0);
						break;
					case 2:
						game->config.voice--;
						if (game->config.voice<0) game->config.voice=10;
						snprintf(text, 255, "%d", game->config.voice);
						SetConfigOption(game, "SuperDerpy", "voice", text);
						al_set_mixer_gain(game->audio.voice, game->config.voice/10.0);
						break;
					case 3:
						ChangeMenuState(game,data,MENUSTATE_OPTIONS);
						break;
				}
				free(text);
				break;
			case MENUSTATE_OPTIONS:
				switch (data->selected) {
					case 0:
						ChangeMenuState(game,data,MENUSTATE_VIDEO);
						break;
					case 1:
						ChangeMenuState(game,data,MENUSTATE_AUDIO);
						break;
					case 3:
						ChangeMenuState(game,data,MENUSTATE_MAIN);
						break;
					default:
						break;
				}
				break;
			case MENUSTATE_VIDEO:
				switch (data->selected) {
					case 0:
						data->options.fullscreen = !data->options.fullscreen;
						if (data->options.fullscreen)
							SetConfigOption(game, "SuperDerpy", "fullscreen", "1");
						else
							SetConfigOption(game, "SuperDerpy", "fullscreen", "0");
						al_set_display_flag(game->display, ALLEGRO_FULLSCREEN_WINDOW, data->options.fullscreen);
						SetupViewport(game);
						PrintConsole(game, "Fullscreen toggled");
						break;
					case 1:
						data->options.resolution++;

						int max = 0, i = 0;

						for (i=0; i < al_get_num_video_adapters(); i++) {
							ALLEGRO_MONITOR_INFO aminfo;
							al_get_monitor_info(i , &aminfo);
							int desktop_width = aminfo.x2 - aminfo.x1 + 1;
							int desktop_height = aminfo.y2 - aminfo.y1 + 1;
							int localmax = desktop_width / 320;
							if (desktop_height / 180 < localmax) localmax = desktop_height / 180;
							if (localmax > max) max = localmax;
						}


						if (data->options.resolution > max) data->options.resolution = 1;
						text = malloc(255*sizeof(char));
						snprintf(text, 255, "%d", data->options.resolution * 320);
						SetConfigOption(game, "SuperDerpy", "width", text);
						snprintf(text, 255, "%d", data->options.resolution * 180);
						SetConfigOption(game, "SuperDerpy", "height", text);
						free(text);
						al_resize_display(game->display, data->options.resolution * 320, data->options.resolution * 180);

						if ((al_get_display_width(game->display) < (data->options.resolution * 320)) || (al_get_display_height(game->display) < (data->options.resolution * 180))) {
							SetConfigOption(game, "SuperDerpy", "width", "320");
							SetConfigOption(game, "SuperDerpy", "height", "180");
							data->options.resolution = 1;
							al_resize_display(game->display, 320, 180);
						}

						SetupViewport(game);
						PrintConsole(game, "Resolution changed");
						break;
					case 3:
						ChangeMenuState(game,data,MENUSTATE_OPTIONS);
						break;
					default:
						break;
				}
				break;
			case MENUSTATE_ABOUT:
				break;
			default:
				UnloadGamestate(game, "menu");
				return;
				break;
		}
	} else if (ev->keyboard.keycode==ALLEGRO_KEY_ESCAPE) {
		switch (data->menustate) {
			case MENUSTATE_OPTIONS:
				ChangeMenuState(game,data,MENUSTATE_MAIN);
				break;
			case MENUSTATE_ABOUT:
				ChangeMenuState(game,data,MENUSTATE_MAIN);
				break;
			case MENUSTATE_HIDDEN:
				UnloadGamestate(game, "menu");
				break;
			case MENUSTATE_VIDEO:
				ChangeMenuState(game,data,MENUSTATE_OPTIONS);
				break;
			case MENUSTATE_AUDIO:
				ChangeMenuState(game,data,MENUSTATE_OPTIONS);
				break;
			default:
				ChangeMenuState(game,data,MENUSTATE_HIDDEN);
				data->selected = -1;
				data->title_pos = 0;
				return;
		}
	}

	if (data->selected==-1) data->selected=3;
	if (data->selected==4) data->selected=0;
	return;
}
Exemple #14
0
/*
 * 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;
    char	   *collate;
    char	   *ctype;

    /* Fetch our pg_database row normally, via syscache */
    tup = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(MyDatabaseId));
    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 autovacuum worker processes either.
     */
    if (IsUnderPostmaster && !IsAutoVacuumWorkerProcess())
    {
        /*
         * Check that the database is currently allowing connections.
         */
        if (!dbform->datallowconn)
            ereport(FATAL,
                    (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
                     errmsg("database \"%s\" is not currently accepting connections",
                            name)));

        /*
         * 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.")));

        /*
         * 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)));
    }

    /*
     * OK, we're golden.  Next to-do item is to save the encoding info out of
     * the pg_database tuple.
     */
    SetDatabaseEncoding(dbform->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_DYNAMIC_DEFAULT);

    /* assign locale variables */
    collate = NameStr(dbform->datcollate);
    ctype = NameStr(dbform->datctype);

    if (pg_perm_setlocale(LC_COLLATE, collate) == NULL)
        ereport(FATAL,
                (errmsg("database locale is incompatible with operating system"),
                 errdetail("The database was initialized with LC_COLLATE \"%s\", "
                           " which is not recognized by setlocale().", collate),
                 errhint("Recreate the database with another locale or install the missing locale.")));

    if (pg_perm_setlocale(LC_CTYPE, ctype) == NULL)
        ereport(FATAL,
                (errmsg("database locale is incompatible with operating system"),
                 errdetail("The database was initialized with LC_CTYPE \"%s\", "
                           " which is not recognized by setlocale().", ctype),
                 errhint("Recreate the database with another locale or install the missing locale.")));

    /* Make the locale settings visible as GUC variables, too */
    SetConfigOption("lc_collate", collate, PGC_INTERNAL, PGC_S_OVERRIDE);
    SetConfigOption("lc_ctype", ctype, PGC_INTERNAL, PGC_S_OVERRIDE);

    ReleaseSysCache(tup);
}
/* --------------------------------
 * 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 autovacuum launcher process
 * doesn't use any parameters either, because it only goes far enough to be
 * able to read pg_database; it doesn't connect to any particular database.
 * In walsender mode only username is used.
 *
 * As of PostgreSQL 8.2, we expect InitProcess() was already called, so we
 * already have a PGPROC struct ... but it's not completely 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		am_superuser;
	GucContext	gucctx;
	char	   *fullpath;
	char		dbname[NAMEDATALEN];

	elog(DEBUG3, "InitPostgres");

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

	/*
	 * 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, if appropriate.  In
	 * bootstrap case we skip this since StartupXLOG() was run instead.
	 */
	if (!bootstrap)
		(void) RecoveryInProgress();

	/*
	 * 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();
	InitPlanCache();

	/* 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 an entry for pg_database.
	 */
	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);

	/* The autovacuum launcher is done here */
	if (IsAutoVacuumLauncherProcess())
		return;

	/*
	 * 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. (This
	 * is critical for anything that reads heap pages, because HOT may decide
	 * to prune them even if the process doesn't attempt to modify any
	 * tuples.)
	 */
	if (!bootstrap)
	{
		StartTransactionCommand();
		(void) GetTransactionSnapshot();
	}

	/*
	 * Set up the global variables holding database id and default tablespace.
	 * But note we won't actually try to touch the database just yet.
	 *
	 * We take a shortcut in the bootstrap and walsender case, otherwise we
	 * have to look up the db's entry in pg_database.
	 */
	if (bootstrap || am_walsender)
	{
		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));
	}
	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);
	}

	/* 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 && !am_walsender)
		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 && !am_walsender)
	{
		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.")));
	}

	/*
	 * Now we should be able to access the database directory safely. Verify
	 * it's there and looks reasonable.
	 */
	fullpath = GetDatabasePath(MyDatabaseId, MyDatabaseTableSpace);

	if (!bootstrap && !am_walsender)
	{
		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();

	/*
	 * Perform client authentication if necessary, then figure out our
	 * postgres user ID, and see if we are a superuser.
	 *
	 * In standalone mode and in autovacuum worker processes, we use a fixed
	 * ID, otherwise we figure it out from the authenticated user name.
	 */
	if (bootstrap || IsAutoVacuumWorkerProcess())
	{
		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\" SUPERUSER;.",
							 username)));
	}
	else
	{
		/* normal multiuser case */
		Assert(MyProcPort != NULL);
		PerformAuthentication(MyProcPort);
		InitializeSessionUserId(username);
		am_superuser = superuser();
	}

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

	/* Process pg_db_role_setting options */
	process_settings(MyDatabaseId, GetSessionUserId());

	/*
	 * 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 && !am_walsender)
		CheckMyDatabase(dbname, am_superuser);

	/*
	 * If we're trying to shut down, only superusers can connect.
	 */
	if (!am_superuser &&
		MyProcPort != NULL &&
		MyProcPort->canAcceptConnections == CAC_WAITBACKUP)
		ereport(FATAL,
				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
		   errmsg("must be superuser to connect during database shutdown")));

	/*
	 * 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")));

	/*
	 * Now process any command-line switches that were included in the startup
	 * packet, if we are in a regular backend.	We couldn't do this before
	 * because we didn't know if client is a superuser.
	 */
	gucctx = am_superuser ? PGC_SUSET : PGC_BACKEND;

	if (MyProcPort != NULL &&
		MyProcPort->cmdline_options != NULL)
	{
		/*
		 * The maximum possible number of commandline arguments that could
		 * come from MyProcPort->cmdline_options is (strlen + 1) / 2; see
		 * pg_split_opts().
		 */
		char	  **av;
		int			maxac;
		int			ac;

		maxac = 2 + (strlen(MyProcPort->cmdline_options) + 1) / 2;

		av = (char **) palloc(maxac * sizeof(char *));
		ac = 0;

		av[ac++] = "postgres";

		/* Note this mangles MyProcPort->cmdline_options */
		pg_split_opts(av, &ac, MyProcPort->cmdline_options);

		av[ac] = NULL;

		Assert(ac < maxac);

		(void) process_postgres_switches(ac, av, gucctx);
	}

	/*
	 * Process any additional GUC variable settings passed in startup packet.
	 * These are handled exactly like command-line variables.
	 */
	if (MyProcPort != NULL)
	{
		ListCell   *gucopts = list_head(MyProcPort->guc_options);

		while (gucopts)
		{
			char	   *name;
			char	   *value;

			name = lfirst(gucopts);
			gucopts = lnext(gucopts);

			value = lfirst(gucopts);
			gucopts = lnext(gucopts);

			SetConfigOption(name, value, gucctx, PGC_S_CLIENT);
		}
	}

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

	/*
	 * 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();

	/* reset the database for walsender */
	if (am_walsender)
		MyProc->databaseId = MyDatabaseId = InvalidOid;

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

	/* close the transaction we started above */
	if (!bootstrap)
		CommitTransactionCommand();
}
Exemple #16
0
int Menu_Keydown(struct Game *game, ALLEGRO_EVENT *ev) {

	if (ev->keyboard.keycode==ALLEGRO_KEY_UP) {
		game->menu.selected--;
		if ((game->menu.menustate==MENUSTATE_VIDEO) && (game->menu.selected==1) && (game->menu.options.fullscreen)) game->menu.selected--;
		al_play_sample_instance(game->menu.click);
	} else if (ev->keyboard.keycode==ALLEGRO_KEY_DOWN) {
		game->menu.selected++;
		if ((game->menu.menustate==MENUSTATE_VIDEO) && (game->menu.selected==1) && (game->menu.options.fullscreen)) game->menu.selected++;
		al_play_sample_instance(game->menu.click);
	}

	if (ev->keyboard.keycode==ALLEGRO_KEY_ENTER) {
		char *text;
		al_play_sample_instance(game->menu.click);
		switch (game->menu.menustate) {
			case MENUSTATE_MAIN:
				switch (game->menu.selected) {
					case 0:
						UnloadGameState(game);
						game->gamestate = GAMESTATE_LOADING;
						game->loadstate = GAMESTATE_DISCLAIMER;
						break;
					case 1:
						ChangeMenuState(game,MENUSTATE_OPTIONS);
						break;
					case 2:
						UnloadGameState(game);
						game->gamestate = GAMESTATE_LOADING;
						game->loadstate = GAMESTATE_ABOUT;
						break;
					case 3:
						return 1;
						break;
				}
				break;
			case MENUSTATE_AUDIO:
				text = malloc(255*sizeof(char));
				switch (game->menu.selected) {
					case 0:
						game->music--;
						if (game->music<0) game->music=10;
						sprintf(text, "%d", game->music);
						SetConfigOption("SuperDerpy", "music", text);
						al_set_mixer_gain(game->audio.music, game->music/10.0);
						break;
					case 1:
						game->fx--;
						if (game->fx<0) game->fx=10;
						sprintf(text, "%d", game->fx);
						SetConfigOption("SuperDerpy", "fx", text);
						al_set_mixer_gain(game->audio.fx, game->fx/10.0);
						break;
					case 2:
						game->voice--;
						if (game->voice<0) game->voice=10;
						sprintf(text, "%d", game->voice);
						SetConfigOption("SuperDerpy", "voice", text);
						al_set_mixer_gain(game->audio.voice, game->voice/10.0);
						break;
					case 3:
						ChangeMenuState(game,MENUSTATE_OPTIONS);
						break;
				}
				free(text);
				break;
			case MENUSTATE_OPTIONS:
				switch (game->menu.selected) {
					case 0:
						ChangeMenuState(game,MENUSTATE_CONTROLS);
						break;
					case 1:
						ChangeMenuState(game,MENUSTATE_VIDEO);
						break;
					case 2:
						ChangeMenuState(game,MENUSTATE_AUDIO);
						break;
					case 3:
						ChangeMenuState(game,MENUSTATE_MAIN);
						break;
					default:
						break;
				}
				break;
			case MENUSTATE_PAUSE:
				switch (game->menu.selected){
					case 0:
						PrintConsole(game,"Game resumed.");
						al_destroy_bitmap(game->pause.bitmap);
						game->pause.bitmap = NULL;
						ResumeGameState(game);
						game->gamestate = game->loadstate;
						break;
					case 1:
						game->gamestate=game->loadstate;
						UnloadGameState(game);
						game->gamestate = GAMESTATE_LOADING;
						game->loadstate = GAMESTATE_MAP;
						break;
					case 2:
						ChangeMenuState(game,MENUSTATE_OPTIONS);
						break;
					case 3:
						return 1;
					default:
						break;
				}
				break;
			case MENUSTATE_CONTROLS:
				switch (game->menu.selected) {
					case 3:
						ChangeMenuState(game,MENUSTATE_OPTIONS);
						break;
					default:
						break;
				}
				break;
			case MENUSTATE_VIDEO:
				switch (game->menu.selected) {
					case 0:
						game->menu.options.fullscreen = !game->menu.options.fullscreen;
						if (game->menu.options.fullscreen)
							SetConfigOption("SuperDerpy", "fullscreen", "1");
						else
							SetConfigOption("SuperDerpy", "fullscreen", "0");
						break;
					case 3:
						if ((game->menu.options.fullscreen==game->fullscreen) && (game->menu.options.fps==game->fps) && (game->menu.options.width==game->width) && (game->menu.options.height==game->height)) {
							ChangeMenuState(game,MENUSTATE_OPTIONS);
						} else {
							PrintConsole(game, "video settings changed, restarting...");
							game->restart = true;
							return 1;
						}
						break;
					default:
						break;
				}
				break;
			default:
				return 1;
				break;
		}
	} else if (ev->keyboard.keycode==ALLEGRO_KEY_ESCAPE) {
		switch (game->menu.menustate) {
			case MENUSTATE_OPTIONS:
				ChangeMenuState(game,MENUSTATE_MAIN);
				break;
			case MENUSTATE_VIDEO:
				ChangeMenuState(game,MENUSTATE_OPTIONS);
				break;
			case MENUSTATE_AUDIO:
				ChangeMenuState(game,MENUSTATE_OPTIONS);
				break;
			case MENUSTATE_CONTROLS:
				ChangeMenuState(game,MENUSTATE_OPTIONS);
				break;
			case MENUSTATE_PAUSE:
				PrintConsole(game,"Game resumed.");
				al_destroy_bitmap(game->pause.bitmap);
				game->pause.bitmap = NULL;
				ResumeGameState(game);
				game->gamestate = game->loadstate;
				break;
			default:
				return 1;
				break;
		}
	}

	if (game->menu.selected==-1) game->menu.selected=3;
	if (game->menu.selected==4) game->menu.selected=0;
	return 0;
}
Exemple #17
0
/*
 * 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 pg_database row normally, via syscache */
	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 autovacuum worker processes either.
	 */
	if (IsUnderPostmaster && !IsAutoVacuumProcess())
	{
		/*
		 * Check that the database is currently allowing connections.
		 */
		if (!dbform->datallowconn)
			ereport(FATAL,
					(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
			 errmsg("database \"%s\" is not currently accepting connections",
					name)));

		/*
		 * 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.")));

		/*
		 * 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)));
	}

	/*
	 * OK, we're golden.  Next to-do item is to save the encoding info out of
	 * the pg_database tuple.
	 */
	SetDatabaseEncoding(dbform->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);
}
Exemple #18
0
/*
 * AutoVacMain
 */
NON_EXEC_STATIC void
AutoVacMain(int argc, char *argv[])
{
    ListCell   *cell;
    List	   *dblist;
    autovac_dbase *db;
    TransactionId xidForceLimit;
    bool		for_xid_wrap;
    sigjmp_buf	local_sigjmp_buf;

    /* we are a postmaster subprocess now */
    IsUnderPostmaster = true;
    am_autovacuum = true;

    /* MPP-4990: Autovacuum always runs as utility-mode */
    Gp_role = GP_ROLE_UTILITY;

    /* reset MyProcPid */
    MyProcPid = getpid();

    /* record Start Time for logging */
    MyStartTime = time(NULL);

    /* Identify myself via ps */
    init_ps_display("autovacuum process", "", "", "");

    SetProcessingMode(InitProcessing);

    /*
     * If possible, make this process a group leader, so that the postmaster
     * can signal any child processes too.  (autovacuum probably never has
     * any child processes, but for consistency we make all postmaster
     * child processes do this.)
     */
#ifdef HAVE_SETSID
    if (setsid() < 0)
        elog(FATAL, "setsid() failed: %m");
#endif

    /*
     * Set up signal handlers.	We operate on databases much like a regular
     * backend, so we use the same signal handling.  See equivalent code in
     * tcop/postgres.c.
     *
     * Currently, we don't pay attention to postgresql.conf changes that
     * happen during a single daemon iteration, so we can ignore SIGHUP.
     */
    pqsignal(SIGHUP, SIG_IGN);

    /*
     * SIGINT is used to signal cancelling the current table's vacuum; SIGTERM
     * means abort and exit cleanly, and SIGQUIT means abandon ship.
     */
    pqsignal(SIGINT, StatementCancelHandler);
    pqsignal(SIGTERM, die);
    pqsignal(SIGQUIT, quickdie);
    pqsignal(SIGALRM, handle_sig_alarm);

    pqsignal(SIGPIPE, SIG_IGN);
    pqsignal(SIGUSR1, procsignal_sigusr1_handler);
    /* We don't listen for async notifies */
    pqsignal(SIGUSR2, SIG_IGN);
    pqsignal(SIGFPE, FloatExceptionHandler);
    pqsignal(SIGCHLD, SIG_DFL);

    /* Early initialization */
    BaseInit();

    /*
     * Create a per-backend PGPROC struct in shared memory, except in the
     * EXEC_BACKEND case where this was done in SubPostmasterMain. We must do
     * this before we can use LWLocks (and in the EXEC_BACKEND case we already
     * had to do some stuff with LWLocks).
     */
#ifndef EXEC_BACKEND
    InitProcess();
#endif

    /*
     * If an exception is encountered, processing resumes here.
     *
     * See notes in postgres.c about the design of this coding.
     */
    if (sigsetjmp(local_sigjmp_buf, 1) != 0)
    {
        /* Prevents interrupts while cleaning up */
        HOLD_INTERRUPTS();

        /* Report the error to the server log */
        EmitErrorReport();

        /*
         * We can now go away.	Note that because we called InitProcess, a
         * callback was registered to do ProcKill, which will clean up
         * necessary state.
         */
        proc_exit(0);
    }

    /* We can now handle ereport(ERROR) */
    PG_exception_stack = &local_sigjmp_buf;

    PG_SETMASK(&UnBlockSig);

    /*
     * Force zero_damaged_pages OFF in the autovac process, even if it is set
     * in postgresql.conf.	We don't really want such a dangerous option being
     * applied non-interactively.
     */
    SetConfigOption("zero_damaged_pages", "false", PGC_SUSET, PGC_S_OVERRIDE);

    /* Get a list of databases */
    dblist = autovac_get_database_list();

    /*
     * Determine the oldest datfrozenxid/relfrozenxid that we will allow
     * to pass without forcing a vacuum.  (This limit can be tightened for
     * particular tables, but not loosened.)
     */
    recentXid = ReadNewTransactionId();
    xidForceLimit = recentXid - autovacuum_freeze_max_age;
    /* ensure it's a "normal" XID, else TransactionIdPrecedes misbehaves */
    if (xidForceLimit < FirstNormalTransactionId)
        xidForceLimit -= FirstNormalTransactionId;

    /*
     * Choose a database to connect to.  We pick the database that was least
     * recently auto-vacuumed, or one that needs vacuuming to prevent Xid
     * wraparound-related data loss.  If any db at risk of wraparound is
     * found, we pick the one with oldest datfrozenxid,
     * independently of autovacuum times.
     *
     * Note that a database with no stats entry is not considered, except for
     * Xid wraparound purposes.  The theory is that if no one has ever
     * connected to it since the stats were last initialized, it doesn't need
     * vacuuming.
     *
     * XXX This could be improved if we had more info about whether it needs
     * vacuuming before connecting to it.  Perhaps look through the pgstats
     * data for the database's tables?  One idea is to keep track of the
     * number of new and dead tuples per database in pgstats.  However it
     * isn't clear how to construct a metric that measures that and not cause
     * starvation for less busy databases.
     */
    db = NULL;
    for_xid_wrap = false;
    foreach(cell, dblist)
    {
        autovac_dbase *tmp = lfirst(cell);

        /* Find pgstat entry if any */
        tmp->entry = pgstat_fetch_stat_dbentry(tmp->oid);

        /* Check to see if this one is at risk of wraparound */
        if (TransactionIdPrecedes(tmp->frozenxid, xidForceLimit))
        {
            if (db == NULL ||
                    TransactionIdPrecedes(tmp->frozenxid, db->frozenxid))
                db = tmp;
            for_xid_wrap = true;
            continue;
        }
        else if (for_xid_wrap)
            continue;			/* ignore not-at-risk DBs */

        /*
         * Otherwise, skip a database with no pgstat entry; it means it
         * hasn't seen any activity.
         */
        if (!tmp->entry)
            continue;

        /*
         * Remember the db with oldest autovac time.  (If we are here,
         * both tmp->entry and db->entry must be non-null.)
         */
        if (db == NULL ||
                tmp->entry->last_autovac_time < db->entry->last_autovac_time)
            db = tmp;
    }
Exemple #19
0
/* --------------------------------
 *		ReverifyMyDatabase
 *
 * Since we are forced to fetch the database OID out of pg_database without
 * benefit of locking or transaction ID checking (see utils/misc/database.c),
 * we might have gotten a wrong answer.  Or, we might have attached to a
 * database that's in process of being destroyed by destroydb().  This
 * routine is called after we have all the locking and other infrastructure
 * running --- now we can check that we are really attached to a valid
 * database.
 *
 * In reality, if destroydb() is running in parallel with our startup,
 * it's pretty likely that we will have failed before now, due to being
 * unable to read some of the system tables within the doomed database.
 * This routine just exists to make *sure* we have not started up in an
 * invalid database.  If we quit now, we should have managed to avoid
 * creating any serious problems.
 *
 * This is also a handy place to fetch the database encoding info out
 * of pg_database.
 *
 * To avoid having to read pg_database more times than necessary
 * during session startup, this place is also fitting to set up any
 * database-specific configuration variables.
 * --------------------------------
 */
static void
ReverifyMyDatabase(const char *name)
{
	Relation	pgdbrel;
	HeapScanDesc pgdbscan;
	ScanKeyData key;
	HeapTuple	tup;
	Form_pg_database dbform;

	/*
	 * Because we grab AccessShareLock here, we can be sure that destroydb
	 * is not running in parallel with us (any more).
	 */
	pgdbrel = heap_openr(DatabaseRelationName, AccessShareLock);

	ScanKeyEntryInitialize(&key, 0, Anum_pg_database_datname,
						   F_NAMEEQ, NameGetDatum(name));

	pgdbscan = heap_beginscan(pgdbrel, SnapshotNow, 1, &key);

	tup = heap_getnext(pgdbscan, ForwardScanDirection);
	if (!HeapTupleIsValid(tup) ||
		HeapTupleGetOid(tup) != MyDatabaseId)
	{
		/* OOPS */
		heap_close(pgdbrel, AccessShareLock);

		/*
		 * The only real problem I could have created is to load dirty
		 * buffers for the dead database into shared buffer cache; if I
		 * did, some other backend will eventually try to write them and
		 * die in mdblindwrt.  Flush any such pages to forestall trouble.
		 */
		DropBuffers(MyDatabaseId);
		/* Now I can commit hara-kiri with a clear conscience... */
		ereport(FATAL,
				(errcode(ERRCODE_UNDEFINED_DATABASE),
				 errmsg("database \"%s\", OID %u, has disappeared from pg_database",
						name, MyDatabaseId)));
	}

	/*
	 * Also check that the database is currently allowing connections.
	 * (We do not enforce this in standalone mode, however, so that there is
	 * a way to recover from "UPDATE pg_database SET datallowconn = false;")
	 */
	dbform = (Form_pg_database) GETSTRUCT(tup);
	if (IsUnderPostmaster && !dbform->datallowconn)
		ereport(FATAL,
				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
		 errmsg("database \"%s\" is not currently accepting connections",
				name)));

	/*
	 * OK, we're golden.  Only other to-do item is to save the encoding
	 * info out of the pg_database tuple.
	 */
	SetDatabaseEncoding(dbform->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);

	/*
	 * Set up database-specific configuration variables.
	 */
	if (IsUnderPostmaster)
	{
		Datum		datum;
		bool		isnull;

		datum = heap_getattr(tup, Anum_pg_database_datconfig,
							 RelationGetDescr(pgdbrel), &isnull);
		if (!isnull)
		{
			ArrayType  *a = DatumGetArrayTypeP(datum);

			ProcessGUCArray(a, PGC_S_DATABASE);
		}
	}

	heap_endscan(pgdbscan);
	heap_close(pgdbrel, AccessShareLock);
}
Exemple #20
0
/* shared library initialization function */
void
_PG_init(void)
{
	if (!process_shared_preload_libraries_in_progress)
	{
		ereport(ERROR, (errmsg("Citus can only be loaded via shared_preload_libraries"),
						errhint("Add citus to shared_preload_libraries configuration "
								"variable in postgresql.conf in master and workers. Note "
								"that citus should be at the beginning of "
								"shared_preload_libraries.")));
	}

	/*
	 * Perform checks before registering any hooks, to avoid erroring out in a
	 * partial state.
	 *
	 * In many cases (e.g. planner and utility hook, to run inside
	 * pg_stat_statements et. al.) we have to be loaded before other hooks
	 * (thus as the innermost/last running hook) to be able to do our
	 * duties. For simplicity insist that all hooks are previously unused.
	 */
	if (planner_hook != NULL ||
		ExplainOneQuery_hook != NULL ||
		ExecutorStart_hook != NULL ||
		ExecutorRun_hook != NULL ||
		ExecutorFinish_hook != NULL ||
		ExecutorEnd_hook != NULL ||
		ProcessUtility_hook != NULL)
	{
		ereport(ERROR, (errmsg("Citus has to be loaded first"),
						errhint("Place citus at the beginning of "
								"shared_preload_libraries.")));
	}

	/*
	 * Extend the database directory structure before continuing with
	 * initialization - one of the later steps might require them to exist.
	 */
	CreateRequiredDirectories();

	/*
	 * Register Citus configuration variables. Do so before intercepting
	 * hooks or calling initialization functions, in case we want to do the
	 * latter in a configuration dependent manner.
	 */
	RegisterCitusConfigVariables();

	/* make our additional node types known */
	RegisterNodes();

	/* intercept planner */
	planner_hook = multi_planner;

	/* intercept explain */
	ExplainOneQuery_hook = MultiExplainOneQuery;

	/* intercept executor */
	ExecutorStart_hook = multi_ExecutorStart;
	ExecutorRun_hook = multi_ExecutorRun;
	ExecutorFinish_hook = multi_ExecutorFinish;
	ExecutorEnd_hook = multi_ExecutorEnd;

	/* register utility hook */
	ProcessUtility_hook = multi_ProcessUtility;

	/* register for planner hook */
	set_rel_pathlist_hook = multi_relation_restriction_hook;

	/* organize that task tracker is started once server is up */
	TaskTrackerRegister();

	/* initialize transaction callbacks */
	RegisterRouterExecutorXactCallbacks();
	RegisterShardPlacementXactCallbacks();

	/* enable modification of pg_catalog tables during pg_upgrade */
	if (IsBinaryUpgrade)
	{
		SetConfigOption("allow_system_table_mods", "true", PGC_POSTMASTER,
						PGC_S_OVERRIDE);
	}
}