pgindent run for release 9.3

This is the first run of the Perl-based pgindent script.  Also update
pgindent instructions.
This commit is contained in:
Bruce Momjian 2013-05-29 16:58:43 -04:00
parent 07ab261ef3
commit 9af4159fce
367 changed files with 4222 additions and 3829 deletions

View File

@ -97,7 +97,6 @@ gbt_bit_xfrm(bytea *leaf)
static GBT_VARKEY * static GBT_VARKEY *
gbt_bit_l2n(GBT_VARKEY *leaf) gbt_bit_l2n(GBT_VARKEY *leaf)
{ {
GBT_VARKEY *out = leaf; GBT_VARKEY *out = leaf;
GBT_VARKEY_R r = gbt_var_key_readable(leaf); GBT_VARKEY_R r = gbt_var_key_readable(leaf);
bytea *o; bytea *o;

View File

@ -121,7 +121,6 @@ gbt_text_compress(PG_FUNCTION_ARGS)
Datum Datum
gbt_bpchar_compress(PG_FUNCTION_ARGS) gbt_bpchar_compress(PG_FUNCTION_ARGS)
{ {
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
GISTENTRY *retval; GISTENTRY *retval;

View File

@ -382,7 +382,6 @@ gbt_ts_union(PG_FUNCTION_ARGS)
Datum Datum
gbt_ts_penalty(PG_FUNCTION_ARGS) gbt_ts_penalty(PG_FUNCTION_ARGS)
{ {
tsKEY *origentry = (tsKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key); tsKEY *origentry = (tsKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
tsKEY *newentry = (tsKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key); tsKEY *newentry = (tsKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
float *result = (float *) PG_GETARG_POINTER(2); float *result = (float *) PG_GETARG_POINTER(2);

View File

@ -137,7 +137,6 @@ gbt_num_union(GBT_NUMKEY *out, const GistEntryVector *entryvec, const gbtree_nin
bool bool
gbt_num_same(const GBT_NUMKEY *a, const GBT_NUMKEY *b, const gbtree_ninfo *tinfo) gbt_num_same(const GBT_NUMKEY *a, const GBT_NUMKEY *b, const gbtree_ninfo *tinfo)
{ {
GBT_NUMKEY_R b1, GBT_NUMKEY_R b1,
b2; b2;
@ -159,7 +158,6 @@ gbt_num_same(const GBT_NUMKEY *a, const GBT_NUMKEY *b, const gbtree_ninfo *tinfo
void void
gbt_num_bin_union(Datum *u, GBT_NUMKEY *e, const gbtree_ninfo *tinfo) gbt_num_bin_union(Datum *u, GBT_NUMKEY *e, const gbtree_ninfo *tinfo)
{ {
GBT_NUMKEY_R rd; GBT_NUMKEY_R rd;
rd.lower = &e[0]; rd.lower = &e[0];

View File

@ -56,7 +56,6 @@ gbt_var_decompress(PG_FUNCTION_ARGS)
GBT_VARKEY_R GBT_VARKEY_R
gbt_var_key_readable(const GBT_VARKEY *k) gbt_var_key_readable(const GBT_VARKEY *k)
{ {
GBT_VARKEY_R r; GBT_VARKEY_R r;
r.lower = (bytea *) &(((char *) k)[VARHDRSZ]); r.lower = (bytea *) &(((char *) k)[VARHDRSZ]);
@ -270,7 +269,6 @@ gbt_var_bin_union(Datum *u, GBT_VARKEY *e, Oid collation,
GISTENTRY * GISTENTRY *
gbt_var_compress(GISTENTRY *entry, const gbtree_vinfo *tinfo) gbt_var_compress(GISTENTRY *entry, const gbtree_vinfo *tinfo)
{ {
GISTENTRY *retval; GISTENTRY *retval;
if (entry->leafkey) if (entry->leafkey)
@ -299,7 +297,6 @@ GBT_VARKEY *
gbt_var_union(const GistEntryVector *entryvec, int32 *size, Oid collation, gbt_var_union(const GistEntryVector *entryvec, int32 *size, Oid collation,
const gbtree_vinfo *tinfo) const gbtree_vinfo *tinfo)
{ {
int i = 0, int i = 0,
numranges = entryvec->n; numranges = entryvec->n;
GBT_VARKEY *cur; GBT_VARKEY *cur;

View File

@ -1973,7 +1973,7 @@ dblink_fdw_validator(PG_FUNCTION_ARGS)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FDW_OUT_OF_MEMORY), (errcode(ERRCODE_FDW_OUT_OF_MEMORY),
errmsg("out of memory"), errmsg("out of memory"),
errdetail("could not get libpq's default connection options"))); errdetail("could not get libpq's default connection options")));
} }
/* Validate each supplied option. */ /* Validate each supplied option. */
@ -1984,9 +1984,9 @@ dblink_fdw_validator(PG_FUNCTION_ARGS)
if (!is_valid_dblink_option(options, def->defname, context)) if (!is_valid_dblink_option(options, def->defname, context))
{ {
/* /*
* Unknown option, or invalid option for the context specified, * Unknown option, or invalid option for the context specified, so
* so complain about it. Provide a hint with list of valid * complain about it. Provide a hint with list of valid options
* options for the context. * for the context.
*/ */
StringInfoData buf; StringInfoData buf;
const PQconninfoOption *opt; const PQconninfoOption *opt;

View File

@ -140,8 +140,8 @@ static void fileGetOptions(Oid foreigntableid,
char **filename, List **other_options); char **filename, List **other_options);
static List *get_file_fdw_attribute_options(Oid relid); static List *get_file_fdw_attribute_options(Oid relid);
static bool check_selective_binary_conversion(RelOptInfo *baserel, static bool check_selective_binary_conversion(RelOptInfo *baserel,
Oid foreigntableid, Oid foreigntableid,
List **columns); List **columns);
static void estimate_size(PlannerInfo *root, RelOptInfo *baserel, static void estimate_size(PlannerInfo *root, RelOptInfo *baserel,
FileFdwPlanState *fdw_private); FileFdwPlanState *fdw_private);
static void estimate_costs(PlannerInfo *root, RelOptInfo *baserel, static void estimate_costs(PlannerInfo *root, RelOptInfo *baserel,
@ -478,7 +478,7 @@ fileGetForeignPaths(PlannerInfo *root,
&startup_cost, &total_cost); &startup_cost, &total_cost);
/* /*
* Create a ForeignPath node and add it as only possible path. We use the * Create a ForeignPath node and add it as only possible path. We use the
* fdw_private list of the path to carry the convert_selectively option; * fdw_private list of the path to carry the convert_selectively option;
* it will be propagated into the fdw_private list of the Plan node. * it will be propagated into the fdw_private list of the Plan node.
*/ */
@ -770,7 +770,7 @@ check_selective_binary_conversion(RelOptInfo *baserel,
/* Add all the attributes used by restriction clauses. */ /* Add all the attributes used by restriction clauses. */
foreach(lc, baserel->baserestrictinfo) foreach(lc, baserel->baserestrictinfo)
{ {
RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc); RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
pull_varattnos((Node *) rinfo->clause, baserel->relid, pull_varattnos((Node *) rinfo->clause, baserel->relid,
&attrs_used); &attrs_used);

View File

@ -1300,7 +1300,7 @@ hstore_to_json_loose(PG_FUNCTION_ARGS)
* digit as numeric - could be a zip code or similar * digit as numeric - could be a zip code or similar
*/ */
if (src->len > 0 && if (src->len > 0 &&
!(src->data[0] == '0' && isdigit((unsigned char) src->data[1])) && !(src->data[0] == '0' && isdigit((unsigned char) src->data[1])) &&
strspn(src->data, "+-0123456789Ee.") == src->len) strspn(src->data, "+-0123456789Ee.") == src->len)
{ {
/* /*
@ -1308,9 +1308,9 @@ hstore_to_json_loose(PG_FUNCTION_ARGS)
* value. Ignore any actual parsed value. * value. Ignore any actual parsed value.
*/ */
char *endptr = "junk"; char *endptr = "junk";
long lval; long lval;
lval = strtol(src->data, &endptr, 10); lval = strtol(src->data, &endptr, 10);
(void) lval; (void) lval;
if (*endptr == '\0') if (*endptr == '\0')
{ {
@ -1323,7 +1323,7 @@ hstore_to_json_loose(PG_FUNCTION_ARGS)
else else
{ {
/* not an int - try a double */ /* not an int - try a double */
double dval; double dval;
dval = strtod(src->data, &endptr); dval = strtod(src->data, &endptr);
(void) dval; (void) dval;

View File

@ -215,7 +215,7 @@ add_one_elt(char *eltname, eary *eary)
{ {
eary ->alloc *= 2; eary ->alloc *= 2;
eary ->array = (char **) pg_realloc(eary->array, eary ->array = (char **) pg_realloc(eary->array,
eary->alloc * sizeof(char *)); eary->alloc * sizeof(char *));
} }
eary ->array[eary->num] = pg_strdup(eltname); eary ->array[eary->num] = pg_strdup(eltname);

View File

@ -299,8 +299,8 @@ main(int argc, char **argv)
dryrun = true; dryrun = true;
break; break;
case 'x': case 'x':
additional_ext = strdup(optarg); /* Extension to remove from additional_ext = strdup(optarg); /* Extension to remove
* xlogfile names */ * from xlogfile names */
break; break;
default: default:
fprintf(stderr, "Try \"%s --help\" for more information.\n", progname); fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);

View File

@ -593,7 +593,7 @@ main(int argc, char **argv)
* There's no way to trigger failover via signal on Windows. * There's no way to trigger failover via signal on Windows.
*/ */
(void) pqsignal(SIGUSR1, sighandler); (void) pqsignal(SIGUSR1, sighandler);
(void) pqsignal(SIGINT, sighandler); /* deprecated, use SIGUSR1 */ (void) pqsignal(SIGINT, sighandler); /* deprecated, use SIGUSR1 */
(void) pqsignal(SIGQUIT, sigquit_handler); (void) pqsignal(SIGQUIT, sigquit_handler);
#endif #endif

View File

@ -18,7 +18,7 @@ static uint64 test_timing(int32);
static void output(uint64 loop_count); static void output(uint64 loop_count);
/* record duration in powers of 2 microseconds */ /* record duration in powers of 2 microseconds */
int64 histogram[32]; int64 histogram[32];
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
@ -110,8 +110,11 @@ test_timing(int32 duration)
uint64 total_time; uint64 total_time;
int64 time_elapsed = 0; int64 time_elapsed = 0;
uint64 loop_count = 0; uint64 loop_count = 0;
uint64 prev, cur; uint64 prev,
instr_time start_time, end_time, temp; cur;
instr_time start_time,
end_time,
temp;
total_time = duration > 0 ? duration * 1000000 : 0; total_time = duration > 0 ? duration * 1000000 : 0;
@ -120,7 +123,8 @@ test_timing(int32 duration)
while (time_elapsed < total_time) while (time_elapsed < total_time)
{ {
int32 diff, bits = 0; int32 diff,
bits = 0;
prev = cur; prev = cur;
INSTR_TIME_SET_CURRENT(temp); INSTR_TIME_SET_CURRENT(temp);
@ -163,12 +167,13 @@ test_timing(int32 duration)
static void static void
output(uint64 loop_count) output(uint64 loop_count)
{ {
int64 max_bit = 31, i; int64 max_bit = 31,
i;
/* find highest bit value */ /* find highest bit value */
while (max_bit > 0 && histogram[max_bit] == 0) while (max_bit > 0 && histogram[max_bit] == 0)
max_bit--; max_bit--;
printf("Histogram of timing durations:\n"); printf("Histogram of timing durations:\n");
printf("%6s %10s %10s\n", "< usec", "% of total", "count"); printf("%6s %10s %10s\n", "< usec", "% of total", "count");
@ -179,6 +184,6 @@ output(uint64 loop_count)
/* lame hack to work around INT64_FORMAT deficiencies */ /* lame hack to work around INT64_FORMAT deficiencies */
snprintf(buf, sizeof(buf), INT64_FORMAT, histogram[i]); snprintf(buf, sizeof(buf), INT64_FORMAT, histogram[i]);
printf("%6ld %9.5f %10s\n", 1l << i, printf("%6ld %9.5f %10s\n", 1l << i,
(double) histogram[i] * 100 / loop_count, buf); (double) histogram[i] * 100 / loop_count, buf);
} }
} }

View File

@ -347,8 +347,8 @@ get_wildcard_part(const char *str, int lenstr,
else else
{ {
/* /*
* Back up endword to the escape character when stopping at * Back up endword to the escape character when stopping at an
* an escaped char, so that subsequent get_wildcard_part will * escaped char, so that subsequent get_wildcard_part will
* restart from the escape character. We assume here that * restart from the escape character. We assume here that
* escape chars are single-byte. * escape chars are single-byte.
*/ */

View File

@ -28,7 +28,7 @@ static char *get_canonical_locale_name(int category, const char *locale);
* fix_path_separator * fix_path_separator
* For non-Windows, just return the argument. * For non-Windows, just return the argument.
* For Windows convert any forward slash to a backslash * For Windows convert any forward slash to a backslash
* such as is suitable for arguments to builtin commands * such as is suitable for arguments to builtin commands
* like RMDIR and DEL. * like RMDIR and DEL.
*/ */
static char * static char *
@ -36,8 +36,8 @@ fix_path_separator(char *path)
{ {
#ifdef WIN32 #ifdef WIN32
char *result; char *result;
char *c; char *c;
result = pg_strdup(path); result = pg_strdup(path);
@ -46,11 +46,9 @@ fix_path_separator(char *path)
*c = '\\'; *c = '\\';
return result; return result;
#else #else
return path; return path;
#endif #endif
} }
@ -156,21 +154,21 @@ check_new_cluster(void)
check_is_super_user(&new_cluster); check_is_super_user(&new_cluster);
/* /*
* We don't restore our own user, so both clusters must match have * We don't restore our own user, so both clusters must match have
* matching install-user oids. * matching install-user oids.
*/ */
if (old_cluster.install_role_oid != new_cluster.install_role_oid) if (old_cluster.install_role_oid != new_cluster.install_role_oid)
pg_log(PG_FATAL, pg_log(PG_FATAL,
"Old and new cluster install users have different values for pg_authid.oid.\n"); "Old and new cluster install users have different values for pg_authid.oid.\n");
/* /*
* We only allow the install user in the new cluster because other * We only allow the install user in the new cluster because other defined
* defined users might match users defined in the old cluster and * users might match users defined in the old cluster and generate an
* generate an error during pg_dump restore. * error during pg_dump restore.
*/ */
if (new_cluster.role_count != 1) if (new_cluster.role_count != 1)
pg_log(PG_FATAL, "Only the install user can be defined in the new cluster.\n"); pg_log(PG_FATAL, "Only the install user can be defined in the new cluster.\n");
check_for_prepared_transactions(&new_cluster); check_for_prepared_transactions(&new_cluster);
} }
@ -247,14 +245,14 @@ output_completion_banner(char *analyze_script_file_name,
if (deletion_script_file_name) if (deletion_script_file_name)
pg_log(PG_REPORT, pg_log(PG_REPORT,
"Running this script will delete the old cluster's data files:\n" "Running this script will delete the old cluster's data files:\n"
" %s\n", " %s\n",
deletion_script_file_name); deletion_script_file_name);
else else
pg_log(PG_REPORT, pg_log(PG_REPORT,
"Could not create a script to delete the old cluster's data\n" "Could not create a script to delete the old cluster's data\n"
"files because user-defined tablespaces exist in the old cluster\n" "files because user-defined tablespaces exist in the old cluster\n"
"directory. The old cluster's contents must be deleted manually.\n"); "directory. The old cluster's contents must be deleted manually.\n");
} }
@ -323,8 +321,8 @@ check_cluster_compatibility(bool live_check)
/* We read the real port number for PG >= 9.1 */ /* We read the real port number for PG >= 9.1 */
if (live_check && GET_MAJOR_VERSION(old_cluster.major_version) < 901 && if (live_check && GET_MAJOR_VERSION(old_cluster.major_version) < 901 &&
old_cluster.port == DEF_PGUPORT) old_cluster.port == DEF_PGUPORT)
pg_log(PG_FATAL, "When checking a pre-PG 9.1 live old server, " pg_log(PG_FATAL, "When checking a pre-PG 9.1 live old server, "
"you must specify the old server's port number.\n"); "you must specify the old server's port number.\n");
if (live_check && old_cluster.port == new_cluster.port) if (live_check && old_cluster.port == new_cluster.port)
pg_log(PG_FATAL, "When checking a live server, " pg_log(PG_FATAL, "When checking a live server, "
@ -366,18 +364,18 @@ set_locale_and_encoding(ClusterInfo *cluster)
if (GET_MAJOR_VERSION(cluster->major_version) < 902) if (GET_MAJOR_VERSION(cluster->major_version) < 902)
{ {
/* /*
* Pre-9.2 did not canonicalize the supplied locale names * Pre-9.2 did not canonicalize the supplied locale names to match
* to match what the system returns, while 9.2+ does, so * what the system returns, while 9.2+ does, so convert pre-9.2 to
* convert pre-9.2 to match. * match.
*/ */
ctrl->lc_collate = get_canonical_locale_name(LC_COLLATE, ctrl->lc_collate = get_canonical_locale_name(LC_COLLATE,
pg_strdup(PQgetvalue(res, 0, i_datcollate))); pg_strdup(PQgetvalue(res, 0, i_datcollate)));
ctrl->lc_ctype = get_canonical_locale_name(LC_CTYPE, ctrl->lc_ctype = get_canonical_locale_name(LC_CTYPE,
pg_strdup(PQgetvalue(res, 0, i_datctype))); pg_strdup(PQgetvalue(res, 0, i_datctype)));
} }
else else
{ {
ctrl->lc_collate = pg_strdup(PQgetvalue(res, 0, i_datcollate)); ctrl->lc_collate = pg_strdup(PQgetvalue(res, 0, i_datcollate));
ctrl->lc_ctype = pg_strdup(PQgetvalue(res, 0, i_datctype)); ctrl->lc_ctype = pg_strdup(PQgetvalue(res, 0, i_datctype));
} }
@ -410,21 +408,21 @@ check_locale_and_encoding(ControlData *oldctrl,
ControlData *newctrl) ControlData *newctrl)
{ {
/* /*
* These are often defined with inconsistent case, so use pg_strcasecmp(). * These are often defined with inconsistent case, so use pg_strcasecmp().
* They also often use inconsistent hyphenation, which we cannot fix, e.g. * They also often use inconsistent hyphenation, which we cannot fix, e.g.
* UTF-8 vs. UTF8, so at least we display the mismatching values. * UTF-8 vs. UTF8, so at least we display the mismatching values.
*/ */
if (pg_strcasecmp(oldctrl->lc_collate, newctrl->lc_collate) != 0) if (pg_strcasecmp(oldctrl->lc_collate, newctrl->lc_collate) != 0)
pg_log(PG_FATAL, pg_log(PG_FATAL,
"lc_collate cluster values do not match: old \"%s\", new \"%s\"\n", "lc_collate cluster values do not match: old \"%s\", new \"%s\"\n",
oldctrl->lc_collate, newctrl->lc_collate); oldctrl->lc_collate, newctrl->lc_collate);
if (pg_strcasecmp(oldctrl->lc_ctype, newctrl->lc_ctype) != 0) if (pg_strcasecmp(oldctrl->lc_ctype, newctrl->lc_ctype) != 0)
pg_log(PG_FATAL, pg_log(PG_FATAL,
"lc_ctype cluster values do not match: old \"%s\", new \"%s\"\n", "lc_ctype cluster values do not match: old \"%s\", new \"%s\"\n",
oldctrl->lc_ctype, newctrl->lc_ctype); oldctrl->lc_ctype, newctrl->lc_ctype);
if (pg_strcasecmp(oldctrl->encoding, newctrl->encoding) != 0) if (pg_strcasecmp(oldctrl->encoding, newctrl->encoding) != 0)
pg_log(PG_FATAL, pg_log(PG_FATAL,
"encoding cluster values do not match: old \"%s\", new \"%s\"\n", "encoding cluster values do not match: old \"%s\", new \"%s\"\n",
oldctrl->encoding, newctrl->encoding); oldctrl->encoding, newctrl->encoding);
} }
@ -597,16 +595,16 @@ create_script_for_old_cluster_deletion(char **deletion_script_file_name)
SCRIPT_EXT); SCRIPT_EXT);
/* /*
* Some users (oddly) create tablespaces inside the cluster data * Some users (oddly) create tablespaces inside the cluster data
* directory. We can't create a proper old cluster delete script * directory. We can't create a proper old cluster delete script in that
* in that case. * case.
*/ */
strlcpy(old_cluster_pgdata, old_cluster.pgdata, MAXPGPATH); strlcpy(old_cluster_pgdata, old_cluster.pgdata, MAXPGPATH);
canonicalize_path(old_cluster_pgdata); canonicalize_path(old_cluster_pgdata);
for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++) for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
{ {
char old_tablespace_dir[MAXPGPATH]; char old_tablespace_dir[MAXPGPATH];
strlcpy(old_tablespace_dir, os_info.old_tablespaces[tblnum], MAXPGPATH); strlcpy(old_tablespace_dir, os_info.old_tablespaces[tblnum], MAXPGPATH);
canonicalize_path(old_tablespace_dir); canonicalize_path(old_tablespace_dir);
if (path_is_prefix_of_path(old_cluster_pgdata, old_tablespace_dir)) if (path_is_prefix_of_path(old_cluster_pgdata, old_tablespace_dir))
@ -649,7 +647,7 @@ create_script_for_old_cluster_deletion(char **deletion_script_file_name)
/* remove PG_VERSION? */ /* remove PG_VERSION? */
if (GET_MAJOR_VERSION(old_cluster.major_version) <= 804) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 804)
fprintf(script, RM_CMD " %s%s%cPG_VERSION\n", fprintf(script, RM_CMD " %s%s%cPG_VERSION\n",
fix_path_separator(os_info.old_tablespaces[tblnum]), fix_path_separator(os_info.old_tablespaces[tblnum]),
fix_path_separator(old_cluster.tablespace_suffix), fix_path_separator(old_cluster.tablespace_suffix),
PATH_SEPARATOR); PATH_SEPARATOR);
@ -668,7 +666,7 @@ create_script_for_old_cluster_deletion(char **deletion_script_file_name)
* or a version-specific subdirectory. * or a version-specific subdirectory.
*/ */
fprintf(script, RMDIR_CMD " %s%s\n", fprintf(script, RMDIR_CMD " %s%s\n",
fix_path_separator(os_info.old_tablespaces[tblnum]), fix_path_separator(os_info.old_tablespaces[tblnum]),
fix_path_separator(old_cluster.tablespace_suffix)); fix_path_separator(old_cluster.tablespace_suffix));
} }
@ -997,7 +995,7 @@ get_canonical_locale_name(int category, const char *locale)
save = setlocale(category, NULL); save = setlocale(category, NULL);
if (!save) if (!save)
pg_log(PG_FATAL, "failed to get the current locale\n"); pg_log(PG_FATAL, "failed to get the current locale\n");
/* 'save' may be pointing at a modifiable scratch variable, so copy it. */ /* 'save' may be pointing at a modifiable scratch variable, so copy it. */
save = pg_strdup(save); save = pg_strdup(save);
@ -1006,13 +1004,13 @@ get_canonical_locale_name(int category, const char *locale)
res = setlocale(category, locale); res = setlocale(category, locale);
if (!res) if (!res)
pg_log(PG_FATAL, "failed to get system local name for \"%s\"\n", res); pg_log(PG_FATAL, "failed to get system local name for \"%s\"\n", res);
res = pg_strdup(res); res = pg_strdup(res);
/* restore old value. */ /* restore old value. */
if (!setlocale(category, save)) if (!setlocale(category, save))
pg_log(PG_FATAL, "failed to restore old locale \"%s\"\n", save); pg_log(PG_FATAL, "failed to restore old locale \"%s\"\n", save);
pg_free(save); pg_free(save);

View File

@ -472,10 +472,10 @@ get_control_data(ClusterInfo *cluster, bool live_check)
pg_free(lc_messages); pg_free(lc_messages);
/* /*
* Before 9.3, pg_resetxlog reported the xlogid and segno of the first * Before 9.3, pg_resetxlog reported the xlogid and segno of the first log
* log file after reset as separate lines. Starting with 9.3, it reports * file after reset as separate lines. Starting with 9.3, it reports the
* the WAL file name. If the old cluster is older than 9.3, we construct * WAL file name. If the old cluster is older than 9.3, we construct the
* the WAL file name from the xlogid and segno. * WAL file name from the xlogid and segno.
*/ */
if (GET_MAJOR_VERSION(cluster->major_version) <= 902) if (GET_MAJOR_VERSION(cluster->major_version) <= 902)
{ {
@ -499,8 +499,8 @@ get_control_data(ClusterInfo *cluster, bool live_check)
!got_date_is_int || !got_float8_pass_by_value || !got_data_checksum_version) !got_date_is_int || !got_float8_pass_by_value || !got_data_checksum_version)
{ {
pg_log(PG_REPORT, pg_log(PG_REPORT,
"The %s cluster lacks some required control information:\n", "The %s cluster lacks some required control information:\n",
CLUSTER_NAME(cluster)); CLUSTER_NAME(cluster));
if (!got_xid) if (!got_xid)
pg_log(PG_REPORT, " checkpoint next XID\n"); pg_log(PG_REPORT, " checkpoint next XID\n");
@ -576,7 +576,7 @@ check_control_data(ControlData *oldctrl,
{ {
if (oldctrl->align == 0 || oldctrl->align != newctrl->align) if (oldctrl->align == 0 || oldctrl->align != newctrl->align)
pg_log(PG_FATAL, pg_log(PG_FATAL,
"old and new pg_controldata alignments are invalid or do not match\n" "old and new pg_controldata alignments are invalid or do not match\n"
"Likely one cluster is a 32-bit install, the other 64-bit\n"); "Likely one cluster is a 32-bit install, the other 64-bit\n");
if (oldctrl->blocksz == 0 || oldctrl->blocksz != newctrl->blocksz) if (oldctrl->blocksz == 0 || oldctrl->blocksz != newctrl->blocksz)
@ -621,7 +621,10 @@ check_control_data(ControlData *oldctrl,
"options.\n"); "options.\n");
} }
/* We might eventually allow upgrades from checksum to no-checksum clusters. */ /*
* We might eventually allow upgrades from checksum to no-checksum
* clusters.
*/
if (oldctrl->data_checksum_version != newctrl->data_checksum_version) if (oldctrl->data_checksum_version != newctrl->data_checksum_version)
{ {
pg_log(PG_FATAL, pg_log(PG_FATAL,

View File

@ -44,6 +44,7 @@ exec_prog(const char *log_file, const char *opt_log_file,
{ {
int result; int result;
int written; int written;
#define MAXCMDLEN (2 * MAXPGPATH) #define MAXCMDLEN (2 * MAXPGPATH)
char cmd[MAXCMDLEN]; char cmd[MAXCMDLEN];
mode_t old_umask = 0; mode_t old_umask = 0;
@ -67,15 +68,15 @@ exec_prog(const char *log_file, const char *opt_log_file,
#ifdef WIN32 #ifdef WIN32
{ {
/* /*
* "pg_ctl -w stop" might have reported that the server has * "pg_ctl -w stop" might have reported that the server has stopped
* stopped because the postmaster.pid file has been removed, * because the postmaster.pid file has been removed, but "pg_ctl -w
* but "pg_ctl -w start" might still be in the process of * start" might still be in the process of closing and might still be
* closing and might still be holding its stdout and -l log * holding its stdout and -l log file descriptors open. Therefore,
* file descriptors open. Therefore, try to open the log * try to open the log file a few more times.
* file a few more times.
*/ */
int iter; int iter;
for (iter = 0; iter < 4 && log == NULL; iter++) for (iter = 0; iter < 4 && log == NULL; iter++)
{ {
sleep(1); sleep(1);
@ -122,12 +123,13 @@ exec_prog(const char *log_file, const char *opt_log_file,
} }
#ifndef WIN32 #ifndef WIN32
/*
* We can't do this on Windows because it will keep the "pg_ctl start" /*
* output filename open until the server stops, so we do the \n\n above * We can't do this on Windows because it will keep the "pg_ctl start"
* on that platform. We use a unique filename for "pg_ctl start" that is * output filename open until the server stops, so we do the \n\n above on
* never reused while the server is running, so it works fine. We could * that platform. We use a unique filename for "pg_ctl start" that is
* log these commands to a third file, but that just adds complexity. * never reused while the server is running, so it works fine. We could
* log these commands to a third file, but that just adds complexity.
*/ */
if ((log = fopen_priv(log_file, "a")) == NULL) if ((log = fopen_priv(log_file, "a")) == NULL)
pg_log(PG_FATAL, "cannot write to log file %s\n", log_file); pg_log(PG_FATAL, "cannot write to log file %s\n", log_file);
@ -178,7 +180,6 @@ pid_lock_file_exists(const char *datadir)
void void
verify_directories(void) verify_directories(void)
{ {
#ifndef WIN32 #ifndef WIN32
if (access(".", R_OK | W_OK | X_OK) != 0) if (access(".", R_OK | W_OK | X_OK) != 0)
#else #else

View File

@ -127,14 +127,13 @@ linkAndUpdateFile(pageCnvCtx *pageConverter,
static int static int
copy_file(const char *srcfile, const char *dstfile, bool force) copy_file(const char *srcfile, const char *dstfile, bool force)
{ {
#define COPY_BUF_SIZE (50 * BLCKSZ) #define COPY_BUF_SIZE (50 * BLCKSZ)
int src_fd; int src_fd;
int dest_fd; int dest_fd;
char *buffer; char *buffer;
int ret = 0; int ret = 0;
int save_errno = 0; int save_errno = 0;
if ((srcfile == NULL) || (dstfile == NULL)) if ((srcfile == NULL) || (dstfile == NULL))
return -1; return -1;

View File

@ -60,10 +60,9 @@ gen_db_file_maps(DbInfo *old_db, DbInfo *new_db,
* table names change during ALTER TABLE ALTER COLUMN SET TYPE. In >= * table names change during ALTER TABLE ALTER COLUMN SET TYPE. In >=
* 9.0, TOAST relation names always use heap table oids, hence we * 9.0, TOAST relation names always use heap table oids, hence we
* cannot check relation names when upgrading from pre-9.0. Clusters * cannot check relation names when upgrading from pre-9.0. Clusters
* upgraded to 9.0 will get matching TOAST names. * upgraded to 9.0 will get matching TOAST names. If index names don't
* If index names don't match primary key constraint names, this will * match primary key constraint names, this will fail because pg_dump
* fail because pg_dump dumps constraint names and pg_upgrade checks * dumps constraint names and pg_upgrade checks index names.
* index names.
*/ */
if (strcmp(old_rel->nspname, new_rel->nspname) != 0 || if (strcmp(old_rel->nspname, new_rel->nspname) != 0 ||
((GET_MAJOR_VERSION(old_cluster.major_version) >= 900 || ((GET_MAJOR_VERSION(old_cluster.major_version) >= 900 ||
@ -79,7 +78,10 @@ gen_db_file_maps(DbInfo *old_db, DbInfo *new_db,
num_maps++; num_maps++;
} }
/* Do this check after the loop so hopefully we will produce a clearer error above */ /*
* Do this check after the loop so hopefully we will produce a clearer
* error above
*/
if (old_db->rel_arr.nrels != new_db->rel_arr.nrels) if (old_db->rel_arr.nrels != new_db->rel_arr.nrels)
pg_log(PG_FATAL, "old and new databases \"%s\" have a different number of relations\n", pg_log(PG_FATAL, "old and new databases \"%s\" have a different number of relations\n",
old_db->db_name); old_db->db_name);
@ -285,8 +287,11 @@ get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo)
"LEFT OUTER JOIN pg_catalog.pg_index i " "LEFT OUTER JOIN pg_catalog.pg_index i "
" ON c.oid = i.indexrelid " " ON c.oid = i.indexrelid "
"WHERE relkind IN ('r', 'm', 'i'%s) AND " "WHERE relkind IN ('r', 'm', 'i'%s) AND "
/* pg_dump only dumps valid indexes; testing indisready is
* necessary in 9.2, and harmless in earlier/later versions. */ /*
* pg_dump only dumps valid indexes; testing indisready is necessary in
* 9.2, and harmless in earlier/later versions.
*/
" i.indisvalid IS DISTINCT FROM false AND " " i.indisvalid IS DISTINCT FROM false AND "
" i.indisready IS DISTINCT FROM false AND " " i.indisready IS DISTINCT FROM false AND "
/* exclude possible orphaned temp tables */ /* exclude possible orphaned temp tables */
@ -309,8 +314,8 @@ get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo)
PQclear(executeQueryOrDie(conn, "%s", query)); PQclear(executeQueryOrDie(conn, "%s", query));
/* /*
* Get TOAST tables and indexes; we have to gather the TOAST tables in * Get TOAST tables and indexes; we have to gather the TOAST tables in
* later steps because we can't schema-qualify TOAST tables. * later steps because we can't schema-qualify TOAST tables.
*/ */
PQclear(executeQueryOrDie(conn, PQclear(executeQueryOrDie(conn,
"INSERT INTO info_rels " "INSERT INTO info_rels "
@ -335,8 +340,8 @@ get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo)
/* we preserve pg_class.oid so we sort by it to match old/new */ /* we preserve pg_class.oid so we sort by it to match old/new */
"ORDER BY 1;", "ORDER BY 1;",
/* 9.2 removed the spclocation column */ /* 9.2 removed the spclocation column */
(GET_MAJOR_VERSION(cluster->major_version) <= 901) ? (GET_MAJOR_VERSION(cluster->major_version) <= 901) ?
"t.spclocation" : "pg_catalog.pg_tablespace_location(t.oid) AS spclocation"); "t.spclocation" : "pg_catalog.pg_tablespace_location(t.oid) AS spclocation");
res = executeQueryOrDie(conn, "%s", query); res = executeQueryOrDie(conn, "%s", query);
@ -437,5 +442,5 @@ print_rel_infos(RelInfoArr *rel_arr)
for (relnum = 0; relnum < rel_arr->nrels; relnum++) for (relnum = 0; relnum < rel_arr->nrels; relnum++)
pg_log(PG_VERBOSE, "relname: %s.%s: reloid: %u reltblspace: %s\n", pg_log(PG_VERBOSE, "relname: %s.%s: reloid: %u reltblspace: %s\n",
rel_arr->rels[relnum].nspname, rel_arr->rels[relnum].relname, rel_arr->rels[relnum].nspname, rel_arr->rels[relnum].relname,
rel_arr->rels[relnum].reloid, rel_arr->rels[relnum].tablespace); rel_arr->rels[relnum].reloid, rel_arr->rels[relnum].tablespace);
} }

View File

@ -314,8 +314,8 @@ check_required_directory(char **dirpath, char **configpath,
} }
/* /*
* Trim off any trailing path separators because we construct paths * Trim off any trailing path separators because we construct paths by
* by appending to this path. * appending to this path.
*/ */
#ifndef WIN32 #ifndef WIN32
if ((*dirpath)[strlen(*dirpath) - 1] == '/') if ((*dirpath)[strlen(*dirpath) - 1] == '/')
@ -398,10 +398,10 @@ void
get_sock_dir(ClusterInfo *cluster, bool live_check) get_sock_dir(ClusterInfo *cluster, bool live_check)
{ {
#ifdef HAVE_UNIX_SOCKETS #ifdef HAVE_UNIX_SOCKETS
/* /*
* sockdir and port were added to postmaster.pid in PG 9.1. * sockdir and port were added to postmaster.pid in PG 9.1. Pre-9.1 cannot
* Pre-9.1 cannot process pg_ctl -w for sockets in non-default * process pg_ctl -w for sockets in non-default locations.
* locations.
*/ */
if (GET_MAJOR_VERSION(cluster->major_version) >= 901) if (GET_MAJOR_VERSION(cluster->major_version) >= 901)
{ {
@ -415,26 +415,28 @@ get_sock_dir(ClusterInfo *cluster, bool live_check)
else else
{ {
/* /*
* If we are doing a live check, we will use the old cluster's Unix * If we are doing a live check, we will use the old cluster's
* domain socket directory so we can connect to the live server. * Unix domain socket directory so we can connect to the live
* server.
*/ */
unsigned short orig_port = cluster->port; unsigned short orig_port = cluster->port;
char filename[MAXPGPATH], line[MAXPGPATH]; char filename[MAXPGPATH],
FILE *fp; line[MAXPGPATH];
FILE *fp;
int lineno; int lineno;
snprintf(filename, sizeof(filename), "%s/postmaster.pid", snprintf(filename, sizeof(filename), "%s/postmaster.pid",
cluster->pgdata); cluster->pgdata);
if ((fp = fopen(filename, "r")) == NULL) if ((fp = fopen(filename, "r")) == NULL)
pg_log(PG_FATAL, "Cannot open file %s: %m\n", filename); pg_log(PG_FATAL, "Cannot open file %s: %m\n", filename);
for (lineno = 1; for (lineno = 1;
lineno <= Max(LOCK_FILE_LINE_PORT, LOCK_FILE_LINE_SOCKET_DIR); lineno <= Max(LOCK_FILE_LINE_PORT, LOCK_FILE_LINE_SOCKET_DIR);
lineno++) lineno++)
{ {
if (fgets(line, sizeof(line), fp) == NULL) if (fgets(line, sizeof(line), fp) == NULL)
pg_log(PG_FATAL, "Cannot read line %d from %s: %m\n", lineno, filename); pg_log(PG_FATAL, "Cannot read line %d from %s: %m\n", lineno, filename);
/* potentially overwrite user-supplied value */ /* potentially overwrite user-supplied value */
if (lineno == LOCK_FILE_LINE_PORT) if (lineno == LOCK_FILE_LINE_PORT)
sscanf(line, "%hu", &old_cluster.port); sscanf(line, "%hu", &old_cluster.port);
@ -446,18 +448,21 @@ get_sock_dir(ClusterInfo *cluster, bool live_check)
} }
} }
fclose(fp); fclose(fp);
/* warn of port number correction */ /* warn of port number correction */
if (orig_port != DEF_PGUPORT && old_cluster.port != orig_port) if (orig_port != DEF_PGUPORT && old_cluster.port != orig_port)
pg_log(PG_WARNING, "User-supplied old port number %hu corrected to %hu\n", pg_log(PG_WARNING, "User-supplied old port number %hu corrected to %hu\n",
orig_port, cluster->port); orig_port, cluster->port);
} }
} }
else else
/* Can't get sockdir and pg_ctl -w can't use a non-default, use default */
cluster->sockdir = NULL;
#else /* !HAVE_UNIX_SOCKETS */ /*
* Can't get sockdir and pg_ctl -w can't use a non-default, use
* default
*/
cluster->sockdir = NULL;
#else /* !HAVE_UNIX_SOCKETS */
cluster->sockdir = NULL; cluster->sockdir = NULL;
#endif #endif
} }

View File

@ -59,11 +59,11 @@ setupPageConverter(void)
if (newPageVersion != oldPageVersion) if (newPageVersion != oldPageVersion)
{ {
/* /*
* The clusters use differing page layouts, see if we can find a plugin * The clusters use differing page layouts, see if we can find a
* that knows how to convert from the old page layout to the new page * plugin that knows how to convert from the old page layout to the
* layout. * new page layout.
*/ */
if ((converter = loadConverterPlugin(newPageVersion, oldPageVersion)) == NULL) if ((converter = loadConverterPlugin(newPageVersion, oldPageVersion)) == NULL)
pg_log(PG_FATAL, "could not find plugin to convert from old page layout to new page layout\n"); pg_log(PG_FATAL, "could not find plugin to convert from old page layout to new page layout\n");
@ -161,6 +161,4 @@ loadConverterPlugin(uint16 newPageVersion, uint16 oldPageVersion)
} }
} }
#endif #endif

View File

@ -20,7 +20,7 @@
#include <io.h> #include <io.h>
#endif #endif
static int parallel_jobs; static int parallel_jobs;
#ifdef WIN32 #ifdef WIN32
/* /*
@ -28,31 +28,32 @@ static int parallel_jobs;
* it can be passed to WaitForMultipleObjects(). We use two arrays * it can be passed to WaitForMultipleObjects(). We use two arrays
* so the thread_handles array can be passed to WaitForMultipleObjects(). * so the thread_handles array can be passed to WaitForMultipleObjects().
*/ */
HANDLE *thread_handles; HANDLE *thread_handles;
typedef struct { typedef struct
char log_file[MAXPGPATH]; {
char opt_log_file[MAXPGPATH]; char log_file[MAXPGPATH];
char cmd[MAX_STRING]; char opt_log_file[MAXPGPATH];
char cmd[MAX_STRING];
} exec_thread_arg; } exec_thread_arg;
typedef struct { typedef struct
DbInfoArr *old_db_arr; {
DbInfoArr *new_db_arr; DbInfoArr *old_db_arr;
char old_pgdata[MAXPGPATH]; DbInfoArr *new_db_arr;
char new_pgdata[MAXPGPATH]; char old_pgdata[MAXPGPATH];
char old_tablespace[MAXPGPATH]; char new_pgdata[MAXPGPATH];
char old_tablespace[MAXPGPATH];
} transfer_thread_arg; } transfer_thread_arg;
exec_thread_arg **exec_thread_args; exec_thread_arg **exec_thread_args;
transfer_thread_arg **transfer_thread_args; transfer_thread_arg **transfer_thread_args;
/* track current thread_args struct so reap_child() can be used for all cases */ /* track current thread_args struct so reap_child() can be used for all cases */
void **cur_thread_args; void **cur_thread_args;
DWORD win32_exec_prog(exec_thread_arg *args);
DWORD win32_transfer_all_new_dbs(transfer_thread_arg *args);
DWORD win32_exec_prog(exec_thread_arg *args);
DWORD win32_transfer_all_new_dbs(transfer_thread_arg *args);
#endif #endif
/* /*
@ -67,11 +68,12 @@ parallel_exec_prog(const char *log_file, const char *opt_log_file,
{ {
va_list args; va_list args;
char cmd[MAX_STRING]; char cmd[MAX_STRING];
#ifndef WIN32 #ifndef WIN32
pid_t child; pid_t child;
#else #else
HANDLE child; HANDLE child;
exec_thread_arg *new_arg; exec_thread_arg *new_arg;
#endif #endif
va_start(args, fmt); va_start(args, fmt);
@ -85,8 +87,8 @@ parallel_exec_prog(const char *log_file, const char *opt_log_file,
{ {
/* parallel */ /* parallel */
#ifdef WIN32 #ifdef WIN32
cur_thread_args = (void **)exec_thread_args; cur_thread_args = (void **) exec_thread_args;
#endif #endif
/* harvest any dead children */ /* harvest any dead children */
while (reap_child(false) == true) while (reap_child(false) == true)
; ;
@ -94,10 +96,10 @@ parallel_exec_prog(const char *log_file, const char *opt_log_file,
/* must we wait for a dead child? */ /* must we wait for a dead child? */
if (parallel_jobs >= user_opts.jobs) if (parallel_jobs >= user_opts.jobs)
reap_child(true); reap_child(true);
/* set this before we start the job */ /* set this before we start the job */
parallel_jobs++; parallel_jobs++;
/* Ensure stdio state is quiesced before forking */ /* Ensure stdio state is quiesced before forking */
fflush(NULL); fflush(NULL);
@ -112,22 +114,22 @@ parallel_exec_prog(const char *log_file, const char *opt_log_file,
#else #else
if (thread_handles == NULL) if (thread_handles == NULL)
{ {
int i; int i;
thread_handles = pg_malloc(user_opts.jobs * sizeof(HANDLE)); thread_handles = pg_malloc(user_opts.jobs * sizeof(HANDLE));
exec_thread_args = pg_malloc(user_opts.jobs * sizeof(exec_thread_arg *)); exec_thread_args = pg_malloc(user_opts.jobs * sizeof(exec_thread_arg *));
/* /*
* For safety and performance, we keep the args allocated during * For safety and performance, we keep the args allocated during
* the entire life of the process, and we don't free the args * the entire life of the process, and we don't free the args in a
* in a thread different from the one that allocated it. * thread different from the one that allocated it.
*/ */
for (i = 0; i < user_opts.jobs; i++) for (i = 0; i < user_opts.jobs; i++)
exec_thread_args[i] = pg_malloc(sizeof(exec_thread_arg)); exec_thread_args[i] = pg_malloc(sizeof(exec_thread_arg));
} }
/* use first empty array element */ /* use first empty array element */
new_arg = exec_thread_args[parallel_jobs-1]; new_arg = exec_thread_args[parallel_jobs - 1];
/* Can only pass one pointer into the function, so use a struct */ /* Can only pass one pointer into the function, so use a struct */
strcpy(new_arg->log_file, log_file); strcpy(new_arg->log_file, log_file);
@ -135,11 +137,11 @@ parallel_exec_prog(const char *log_file, const char *opt_log_file,
strcpy(new_arg->cmd, cmd); strcpy(new_arg->cmd, cmd);
child = (HANDLE) _beginthreadex(NULL, 0, (void *) win32_exec_prog, child = (HANDLE) _beginthreadex(NULL, 0, (void *) win32_exec_prog,
new_arg, 0, NULL); new_arg, 0, NULL);
if (child == 0) if (child == 0)
pg_log(PG_FATAL, "could not create worker thread: %s\n", strerror(errno)); pg_log(PG_FATAL, "could not create worker thread: %s\n", strerror(errno));
thread_handles[parallel_jobs-1] = child; thread_handles[parallel_jobs - 1] = child;
#endif #endif
} }
@ -151,7 +153,7 @@ parallel_exec_prog(const char *log_file, const char *opt_log_file,
DWORD DWORD
win32_exec_prog(exec_thread_arg *args) win32_exec_prog(exec_thread_arg *args)
{ {
int ret; int ret;
ret = !exec_prog(args->log_file, args->opt_log_file, true, "%s", args->cmd); ret = !exec_prog(args->log_file, args->opt_log_file, true, "%s", args->cmd);
@ -167,15 +169,16 @@ win32_exec_prog(exec_thread_arg *args)
* This has the same API as transfer_all_new_dbs, except it does parallel execution * This has the same API as transfer_all_new_dbs, except it does parallel execution
* by transfering multiple tablespaces in parallel * by transfering multiple tablespaces in parallel
*/ */
void parallel_transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr, void
char *old_pgdata, char *new_pgdata, parallel_transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
char *old_tablespace) char *old_pgdata, char *new_pgdata,
char *old_tablespace)
{ {
#ifndef WIN32 #ifndef WIN32
pid_t child; pid_t child;
#else #else
HANDLE child; HANDLE child;
transfer_thread_arg *new_arg; transfer_thread_arg *new_arg;
#endif #endif
if (user_opts.jobs <= 1) if (user_opts.jobs <= 1)
@ -185,7 +188,7 @@ void parallel_transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
{ {
/* parallel */ /* parallel */
#ifdef WIN32 #ifdef WIN32
cur_thread_args = (void **)transfer_thread_args; cur_thread_args = (void **) transfer_thread_args;
#endif #endif
/* harvest any dead children */ /* harvest any dead children */
while (reap_child(false) == true) while (reap_child(false) == true)
@ -194,10 +197,10 @@ void parallel_transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
/* must we wait for a dead child? */ /* must we wait for a dead child? */
if (parallel_jobs >= user_opts.jobs) if (parallel_jobs >= user_opts.jobs)
reap_child(true); reap_child(true);
/* set this before we start the job */ /* set this before we start the job */
parallel_jobs++; parallel_jobs++;
/* Ensure stdio state is quiesced before forking */ /* Ensure stdio state is quiesced before forking */
fflush(NULL); fflush(NULL);
@ -217,22 +220,22 @@ void parallel_transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
#else #else
if (thread_handles == NULL) if (thread_handles == NULL)
{ {
int i; int i;
thread_handles = pg_malloc(user_opts.jobs * sizeof(HANDLE)); thread_handles = pg_malloc(user_opts.jobs * sizeof(HANDLE));
transfer_thread_args = pg_malloc(user_opts.jobs * sizeof(transfer_thread_arg *)); transfer_thread_args = pg_malloc(user_opts.jobs * sizeof(transfer_thread_arg *));
/* /*
* For safety and performance, we keep the args allocated during * For safety and performance, we keep the args allocated during
* the entire life of the process, and we don't free the args * the entire life of the process, and we don't free the args in a
* in a thread different from the one that allocated it. * thread different from the one that allocated it.
*/ */
for (i = 0; i < user_opts.jobs; i++) for (i = 0; i < user_opts.jobs; i++)
transfer_thread_args[i] = pg_malloc(sizeof(transfer_thread_arg)); transfer_thread_args[i] = pg_malloc(sizeof(transfer_thread_arg));
} }
/* use first empty array element */ /* use first empty array element */
new_arg = transfer_thread_args[parallel_jobs-1]; new_arg = transfer_thread_args[parallel_jobs - 1];
/* Can only pass one pointer into the function, so use a struct */ /* Can only pass one pointer into the function, so use a struct */
new_arg->old_db_arr = old_db_arr; new_arg->old_db_arr = old_db_arr;
@ -242,11 +245,11 @@ void parallel_transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
strcpy(new_arg->old_tablespace, old_tablespace); strcpy(new_arg->old_tablespace, old_tablespace);
child = (HANDLE) _beginthreadex(NULL, 0, (void *) win32_exec_prog, child = (HANDLE) _beginthreadex(NULL, 0, (void *) win32_exec_prog,
new_arg, 0, NULL); new_arg, 0, NULL);
if (child == 0) if (child == 0)
pg_log(PG_FATAL, "could not create worker thread: %s\n", strerror(errno)); pg_log(PG_FATAL, "could not create worker thread: %s\n", strerror(errno));
thread_handles[parallel_jobs-1] = child; thread_handles[parallel_jobs - 1] = child;
#endif #endif
} }
@ -274,11 +277,11 @@ bool
reap_child(bool wait_for_child) reap_child(bool wait_for_child)
{ {
#ifndef WIN32 #ifndef WIN32
int work_status; int work_status;
int ret; int ret;
#else #else
int thread_num; int thread_num;
DWORD res; DWORD res;
#endif #endif
if (user_opts.jobs <= 1 || parallel_jobs == 0) if (user_opts.jobs <= 1 || parallel_jobs == 0)
@ -293,18 +296,17 @@ reap_child(bool wait_for_child)
if (WEXITSTATUS(work_status) != 0) if (WEXITSTATUS(work_status) != 0)
pg_log(PG_FATAL, "child worker exited abnormally: %s\n", strerror(errno)); pg_log(PG_FATAL, "child worker exited abnormally: %s\n", strerror(errno));
#else #else
/* wait for one to finish */ /* wait for one to finish */
thread_num = WaitForMultipleObjects(parallel_jobs, thread_handles, thread_num = WaitForMultipleObjects(parallel_jobs, thread_handles,
false, wait_for_child ? INFINITE : 0); false, wait_for_child ? INFINITE : 0);
if (thread_num == WAIT_TIMEOUT || thread_num == WAIT_FAILED) if (thread_num == WAIT_TIMEOUT || thread_num == WAIT_FAILED)
return false; return false;
/* compute thread index in active_threads */ /* compute thread index in active_threads */
thread_num -= WAIT_OBJECT_0; thread_num -= WAIT_OBJECT_0;
/* get the result */ /* get the result */
GetExitCodeThread(thread_handles[thread_num], &res); GetExitCodeThread(thread_handles[thread_num], &res);
if (res != 0) if (res != 0)
@ -313,18 +315,18 @@ reap_child(bool wait_for_child)
/* dispose of handle to stop leaks */ /* dispose of handle to stop leaks */
CloseHandle(thread_handles[thread_num]); CloseHandle(thread_handles[thread_num]);
/* Move last slot into dead child's position */ /* Move last slot into dead child's position */
if (thread_num != parallel_jobs - 1) if (thread_num != parallel_jobs - 1)
{ {
void *tmp_args; void *tmp_args;
thread_handles[thread_num] = thread_handles[parallel_jobs - 1]; thread_handles[thread_num] = thread_handles[parallel_jobs - 1];
/* /*
* We must swap the arg struct pointers because the thread we * We must swap the arg struct pointers because the thread we just
* just moved is active, and we must make sure it is not * moved is active, and we must make sure it is not reused by the next
* reused by the next created thread. Instead, the new thread * created thread. Instead, the new thread will use the arg struct of
* will use the arg struct of the thread that just died. * the thread that just died.
*/ */
tmp_args = cur_thread_args[thread_num]; tmp_args = cur_thread_args[thread_num];
cur_thread_args[thread_num] = cur_thread_args[parallel_jobs - 1]; cur_thread_args[thread_num] = cur_thread_args[parallel_jobs - 1];

View File

@ -134,7 +134,7 @@ main(int argc, char **argv)
disable_old_cluster(); disable_old_cluster();
transfer_all_new_tablespaces(&old_cluster.dbarr, &new_cluster.dbarr, transfer_all_new_tablespaces(&old_cluster.dbarr, &new_cluster.dbarr,
old_cluster.pgdata, new_cluster.pgdata); old_cluster.pgdata, new_cluster.pgdata);
/* /*
* Assuming OIDs are only used in system tables, there is no need to * Assuming OIDs are only used in system tables, there is no need to
@ -193,14 +193,13 @@ setup(char *argv0, bool *live_check)
if (pid_lock_file_exists(old_cluster.pgdata)) if (pid_lock_file_exists(old_cluster.pgdata))
{ {
/* /*
* If we have a postmaster.pid file, try to start the server. If * If we have a postmaster.pid file, try to start the server. If it
* it starts, the pid file was stale, so stop the server. If it * starts, the pid file was stale, so stop the server. If it doesn't
* doesn't start, assume the server is running. If the pid file * start, assume the server is running. If the pid file is left over
* is left over from a server crash, this also allows any committed * from a server crash, this also allows any committed transactions
* transactions stored in the WAL to be replayed so they are not * stored in the WAL to be replayed so they are not lost, because WAL
* lost, because WAL files are not transfered from old to new * files are not transfered from old to new servers.
* servers. */
*/
if (start_postmaster(&old_cluster, false)) if (start_postmaster(&old_cluster, false))
stop_postmaster(false); stop_postmaster(false);
else else
@ -220,7 +219,7 @@ setup(char *argv0, bool *live_check)
stop_postmaster(false); stop_postmaster(false);
else else
pg_log(PG_FATAL, "There seems to be a postmaster servicing the new cluster.\n" pg_log(PG_FATAL, "There seems to be a postmaster servicing the new cluster.\n"
"Please shutdown that postmaster and try again.\n"); "Please shutdown that postmaster and try again.\n");
} }
/* get path to pg_upgrade executable */ /* get path to pg_upgrade executable */
@ -312,9 +311,9 @@ create_new_objects(void)
prep_status("Adding support functions to new cluster"); prep_status("Adding support functions to new cluster");
/* /*
* Technically, we only need to install these support functions in new * Technically, we only need to install these support functions in new
* databases that also exist in the old cluster, but for completeness * databases that also exist in the old cluster, but for completeness we
* we process all new databases. * process all new databases.
*/ */
for (dbnum = 0; dbnum < new_cluster.dbarr.ndbs; dbnum++) for (dbnum = 0; dbnum < new_cluster.dbarr.ndbs; dbnum++)
{ {
@ -330,21 +329,22 @@ create_new_objects(void)
for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++) for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
{ {
char sql_file_name[MAXPGPATH], log_file_name[MAXPGPATH]; char sql_file_name[MAXPGPATH],
DbInfo *old_db = &old_cluster.dbarr.dbs[dbnum]; log_file_name[MAXPGPATH];
DbInfo *old_db = &old_cluster.dbarr.dbs[dbnum];
pg_log(PG_STATUS, "%s", old_db->db_name); pg_log(PG_STATUS, "%s", old_db->db_name);
snprintf(sql_file_name, sizeof(sql_file_name), DB_DUMP_FILE_MASK, old_db->db_oid); snprintf(sql_file_name, sizeof(sql_file_name), DB_DUMP_FILE_MASK, old_db->db_oid);
snprintf(log_file_name, sizeof(log_file_name), DB_DUMP_LOG_FILE_MASK, old_db->db_oid); snprintf(log_file_name, sizeof(log_file_name), DB_DUMP_LOG_FILE_MASK, old_db->db_oid);
/* /*
* pg_dump only produces its output at the end, so there is little * pg_dump only produces its output at the end, so there is little
* parallelism if using the pipe. * parallelism if using the pipe.
*/ */
parallel_exec_prog(log_file_name, NULL, parallel_exec_prog(log_file_name, NULL,
"\"%s/pg_restore\" %s --exit-on-error --verbose --dbname \"%s\" \"%s\"", "\"%s/pg_restore\" %s --exit-on-error --verbose --dbname \"%s\" \"%s\"",
new_cluster.bindir, cluster_conn_opts(&new_cluster), new_cluster.bindir, cluster_conn_opts(&new_cluster),
old_db->db_name, sql_file_name); old_db->db_name, sql_file_name);
} }
/* reap all children */ /* reap all children */
@ -418,6 +418,7 @@ copy_clog_xlog_xid(void)
copy_subdir_files("pg_multixact/offsets"); copy_subdir_files("pg_multixact/offsets");
copy_subdir_files("pg_multixact/members"); copy_subdir_files("pg_multixact/members");
prep_status("Setting next multixact ID and offset for new cluster"); prep_status("Setting next multixact ID and offset for new cluster");
/* /*
* we preserve all files and contents, so we must preserve both "next" * we preserve all files and contents, so we must preserve both "next"
* counters here and the oldest multi present on system. * counters here and the oldest multi present on system.
@ -434,6 +435,7 @@ copy_clog_xlog_xid(void)
else if (new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) else if (new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER)
{ {
prep_status("Setting oldest multixact ID on new cluster"); prep_status("Setting oldest multixact ID on new cluster");
/* /*
* We don't preserve files in this case, but it's important that the * We don't preserve files in this case, but it's important that the
* oldest multi is set to the latest value used by the old system, so * oldest multi is set to the latest value used by the old system, so
@ -549,7 +551,6 @@ set_frozenxids(void)
static void static void
cleanup(void) cleanup(void)
{ {
fclose(log_opts.internal); fclose(log_opts.internal);
/* Remove dump and log files? */ /* Remove dump and log files? */
@ -567,8 +568,9 @@ cleanup(void)
if (old_cluster.dbarr.dbs) if (old_cluster.dbarr.dbs)
for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++) for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
{ {
char sql_file_name[MAXPGPATH], log_file_name[MAXPGPATH]; char sql_file_name[MAXPGPATH],
DbInfo *old_db = &old_cluster.dbarr.dbs[dbnum]; log_file_name[MAXPGPATH];
DbInfo *old_db = &old_cluster.dbarr.dbs[dbnum];
snprintf(sql_file_name, sizeof(sql_file_name), DB_DUMP_FILE_MASK, old_db->db_oid); snprintf(sql_file_name, sizeof(sql_file_name), DB_DUMP_FILE_MASK, old_db->db_oid);
unlink(sql_file_name); unlink(sql_file_name);

View File

@ -73,24 +73,24 @@ extern char *output_files[];
#define pg_copy_file copy_file #define pg_copy_file copy_file
#define pg_mv_file rename #define pg_mv_file rename
#define pg_link_file link #define pg_link_file link
#define PATH_SEPARATOR '/' #define PATH_SEPARATOR '/'
#define RM_CMD "rm -f" #define RM_CMD "rm -f"
#define RMDIR_CMD "rm -rf" #define RMDIR_CMD "rm -rf"
#define SCRIPT_EXT "sh" #define SCRIPT_EXT "sh"
#define ECHO_QUOTE "'" #define ECHO_QUOTE "'"
#define ECHO_BLANK "" #define ECHO_BLANK ""
#else #else
#define pg_copy_file CopyFile #define pg_copy_file CopyFile
#define pg_mv_file pgrename #define pg_mv_file pgrename
#define pg_link_file win32_pghardlink #define pg_link_file win32_pghardlink
#define sleep(x) Sleep(x * 1000) #define sleep(x) Sleep(x * 1000)
#define PATH_SEPARATOR '\\' #define PATH_SEPARATOR '\\'
#define RM_CMD "DEL /q" #define RM_CMD "DEL /q"
#define RMDIR_CMD "RMDIR /s/q" #define RMDIR_CMD "RMDIR /s/q"
#define SCRIPT_EXT "bat" #define SCRIPT_EXT "bat"
#define EXE_EXT ".exe" #define EXE_EXT ".exe"
#define ECHO_QUOTE "" #define ECHO_QUOTE ""
#define ECHO_BLANK "." #define ECHO_BLANK "."
#endif #endif
#define CLUSTER_NAME(cluster) ((cluster) == &old_cluster ? "old" : \ #define CLUSTER_NAME(cluster) ((cluster) == &old_cluster ? "old" : \
@ -122,8 +122,8 @@ extern char *output_files[];
typedef struct typedef struct
{ {
/* Can't use NAMEDATALEN; not guaranteed to fit on client */ /* Can't use NAMEDATALEN; not guaranteed to fit on client */
char *nspname; /* namespace name */ char *nspname; /* namespace name */
char *relname; /* relation name */ char *relname; /* relation name */
Oid reloid; /* relation oid */ Oid reloid; /* relation oid */
Oid relfilenode; /* relation relfile node */ Oid relfilenode; /* relation relfile node */
/* relation tablespace path, or "" for the cluster default */ /* relation tablespace path, or "" for the cluster default */
@ -155,8 +155,8 @@ typedef struct
Oid old_relfilenode; Oid old_relfilenode;
Oid new_relfilenode; Oid new_relfilenode;
/* the rest are used only for logging and error reporting */ /* the rest are used only for logging and error reporting */
char *nspname; /* namespaces */ char *nspname; /* namespaces */
char *relname; char *relname;
} FileNameMap; } FileNameMap;
/* /*
@ -165,7 +165,7 @@ typedef struct
typedef struct typedef struct
{ {
Oid db_oid; /* oid of the database */ Oid db_oid; /* oid of the database */
char *db_name; /* database name */ char *db_name; /* database name */
char db_tblspace[MAXPGPATH]; /* database default tablespace path */ char db_tblspace[MAXPGPATH]; /* database default tablespace path */
RelInfoArr rel_arr; /* array of all user relinfos */ RelInfoArr rel_arr; /* array of all user relinfos */
} DbInfo; } DbInfo;
@ -254,8 +254,8 @@ typedef struct
char major_version_str[64]; /* string PG_VERSION of cluster */ char major_version_str[64]; /* string PG_VERSION of cluster */
uint32 bin_version; /* version returned from pg_ctl */ uint32 bin_version; /* version returned from pg_ctl */
Oid pg_database_oid; /* OID of pg_database relation */ Oid pg_database_oid; /* OID of pg_database relation */
Oid install_role_oid; /* OID of connected role */ Oid install_role_oid; /* OID of connected role */
Oid role_count; /* number of roles defined in the cluster */ Oid role_count; /* number of roles defined in the cluster */
char *tablespace_suffix; /* directory specification */ char *tablespace_suffix; /* directory specification */
} ClusterInfo; } ClusterInfo;
@ -312,12 +312,12 @@ extern OSInfo os_info;
/* check.c */ /* check.c */
void output_check_banner(bool live_check); void output_check_banner(bool live_check);
void check_and_dump_old_cluster(bool live_check, void check_and_dump_old_cluster(bool live_check,
char **sequence_script_file_name); char **sequence_script_file_name);
void check_new_cluster(void); void check_new_cluster(void);
void report_clusters_compatible(void); void report_clusters_compatible(void);
void issue_warnings(char *sequence_script_file_name); void issue_warnings(char *sequence_script_file_name);
void output_completion_banner(char *analyze_script_file_name, void output_completion_banner(char *analyze_script_file_name,
char *deletion_script_file_name); char *deletion_script_file_name);
void check_cluster_versions(void); void check_cluster_versions(void);
void check_cluster_compatibility(bool live_check); void check_cluster_compatibility(bool live_check);
@ -413,11 +413,11 @@ void get_sock_dir(ClusterInfo *cluster, bool live_check);
/* relfilenode.c */ /* relfilenode.c */
void get_pg_database_relfilenode(ClusterInfo *cluster); void get_pg_database_relfilenode(ClusterInfo *cluster);
void transfer_all_new_tablespaces(DbInfoArr *old_db_arr, void transfer_all_new_tablespaces(DbInfoArr *old_db_arr,
DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata); DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata);
void transfer_all_new_dbs(DbInfoArr *old_db_arr, void transfer_all_new_dbs(DbInfoArr *old_db_arr,
DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata, DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata,
char *old_tablespace); char *old_tablespace);
/* tablespace.c */ /* tablespace.c */
@ -477,11 +477,11 @@ void old_8_3_invalidate_bpchar_pattern_ops_indexes(ClusterInfo *cluster,
char *old_8_3_create_sequence_script(ClusterInfo *cluster); char *old_8_3_create_sequence_script(ClusterInfo *cluster);
/* parallel.c */ /* parallel.c */
void parallel_exec_prog(const char *log_file, const char *opt_log_file, void
const char *fmt,...) parallel_exec_prog(const char *log_file, const char *opt_log_file,
const char *fmt,...)
__attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4))); __attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4)));
void parallel_transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr, void parallel_transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
char *old_pgdata, char *new_pgdata, char *old_pgdata, char *new_pgdata,
char *old_tablespace); char *old_tablespace);
bool reap_child(bool wait_for_child); bool reap_child(bool wait_for_child);

View File

@ -18,7 +18,7 @@
static void transfer_single_new_db(pageCnvCtx *pageConverter, static void transfer_single_new_db(pageCnvCtx *pageConverter,
FileNameMap *maps, int size, char *old_tablespace); FileNameMap *maps, int size, char *old_tablespace);
static void transfer_relfile(pageCnvCtx *pageConverter, FileNameMap *map, static void transfer_relfile(pageCnvCtx *pageConverter, FileNameMap *map,
const char *suffix); const char *suffix);
/* /*
@ -29,32 +29,32 @@ static void transfer_relfile(pageCnvCtx *pageConverter, FileNameMap *map,
*/ */
void void
transfer_all_new_tablespaces(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr, transfer_all_new_tablespaces(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
char *old_pgdata, char *new_pgdata) char *old_pgdata, char *new_pgdata)
{ {
pg_log(PG_REPORT, "%s user relation files\n", pg_log(PG_REPORT, "%s user relation files\n",
user_opts.transfer_mode == TRANSFER_MODE_LINK ? "Linking" : "Copying"); user_opts.transfer_mode == TRANSFER_MODE_LINK ? "Linking" : "Copying");
/* /*
* Transfering files by tablespace is tricky because a single database * Transfering files by tablespace is tricky because a single database can
* can use multiple tablespaces. For non-parallel mode, we just pass a * use multiple tablespaces. For non-parallel mode, we just pass a NULL
* NULL tablespace path, which matches all tablespaces. In parallel mode, * tablespace path, which matches all tablespaces. In parallel mode, we
* we pass the default tablespace and all user-created tablespaces * pass the default tablespace and all user-created tablespaces and let
* and let those operations happen in parallel. * those operations happen in parallel.
*/ */
if (user_opts.jobs <= 1) if (user_opts.jobs <= 1)
parallel_transfer_all_new_dbs(old_db_arr, new_db_arr, old_pgdata, parallel_transfer_all_new_dbs(old_db_arr, new_db_arr, old_pgdata,
new_pgdata, NULL); new_pgdata, NULL);
else else
{ {
int tblnum; int tblnum;
/* transfer default tablespace */ /* transfer default tablespace */
parallel_transfer_all_new_dbs(old_db_arr, new_db_arr, old_pgdata, parallel_transfer_all_new_dbs(old_db_arr, new_db_arr, old_pgdata,
new_pgdata, old_pgdata); new_pgdata, old_pgdata);
for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++) for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
parallel_transfer_all_new_dbs(old_db_arr, new_db_arr, old_pgdata, parallel_transfer_all_new_dbs(old_db_arr, new_db_arr, old_pgdata,
new_pgdata, os_info.old_tablespaces[tblnum]); new_pgdata, os_info.old_tablespaces[tblnum]);
/* reap all children */ /* reap all children */
while (reap_child(true) == true) while (reap_child(true) == true)
; ;
@ -75,7 +75,7 @@ transfer_all_new_tablespaces(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
*/ */
void void
transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr, transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
char *old_pgdata, char *new_pgdata, char *old_tablespace) char *old_pgdata, char *new_pgdata, char *old_tablespace)
{ {
int old_dbnum, int old_dbnum,
new_dbnum; new_dbnum;
@ -170,11 +170,11 @@ transfer_single_new_db(pageCnvCtx *pageConverter,
{ {
int mapnum; int mapnum;
bool vm_crashsafe_match = true; bool vm_crashsafe_match = true;
/* /*
* Do the old and new cluster disagree on the crash-safetiness of the vm * Do the old and new cluster disagree on the crash-safetiness of the vm
* files? If so, do not copy them. * files? If so, do not copy them.
*/ */
if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_CRASHSAFE_CAT_VER && if (old_cluster.controldata.cat_ver < VISIBILITY_MAP_CRASHSAFE_CAT_VER &&
new_cluster.controldata.cat_ver >= VISIBILITY_MAP_CRASHSAFE_CAT_VER) new_cluster.controldata.cat_ver >= VISIBILITY_MAP_CRASHSAFE_CAT_VER)
vm_crashsafe_match = false; vm_crashsafe_match = false;
@ -186,7 +186,7 @@ transfer_single_new_db(pageCnvCtx *pageConverter,
{ {
/* transfer primary file */ /* transfer primary file */
transfer_relfile(pageConverter, &maps[mapnum], ""); transfer_relfile(pageConverter, &maps[mapnum], "");
/* fsm/vm files added in PG 8.4 */ /* fsm/vm files added in PG 8.4 */
if (GET_MAJOR_VERSION(old_cluster.major_version) >= 804) if (GET_MAJOR_VERSION(old_cluster.major_version) >= 804)
{ {
@ -217,13 +217,11 @@ transfer_relfile(pageCnvCtx *pageConverter, FileNameMap *map,
int fd; int fd;
int segno; int segno;
char extent_suffix[65]; char extent_suffix[65];
/* /*
* Now copy/link any related segments as well. Remember, PG breaks * Now copy/link any related segments as well. Remember, PG breaks large
* large files into 1GB segments, the first segment has no extension, * files into 1GB segments, the first segment has no extension, subsequent
* subsequent segments are named relfilenode.1, relfilenode.2, * segments are named relfilenode.1, relfilenode.2, relfilenode.3. copied.
* relfilenode.3.
* copied.
*/ */
for (segno = 0;; segno++) for (segno = 0;; segno++)
{ {
@ -233,12 +231,12 @@ transfer_relfile(pageCnvCtx *pageConverter, FileNameMap *map,
snprintf(extent_suffix, sizeof(extent_suffix), ".%d", segno); snprintf(extent_suffix, sizeof(extent_suffix), ".%d", segno);
snprintf(old_file, sizeof(old_file), "%s%s/%u/%u%s%s", map->old_tablespace, snprintf(old_file, sizeof(old_file), "%s%s/%u/%u%s%s", map->old_tablespace,
map->old_tablespace_suffix, map->old_db_oid, map->old_relfilenode, map->old_tablespace_suffix, map->old_db_oid, map->old_relfilenode,
type_suffix, extent_suffix); type_suffix, extent_suffix);
snprintf(new_file, sizeof(new_file), "%s%s/%u/%u%s%s", map->new_tablespace, snprintf(new_file, sizeof(new_file), "%s%s/%u/%u%s%s", map->new_tablespace,
map->new_tablespace_suffix, map->new_db_oid, map->new_relfilenode, map->new_tablespace_suffix, map->new_db_oid, map->new_relfilenode,
type_suffix, extent_suffix); type_suffix, extent_suffix);
/* Is it an extent, fsm, or vm file? */ /* Is it an extent, fsm, or vm file? */
if (type_suffix[0] != '\0' || segno != 0) if (type_suffix[0] != '\0' || segno != 0)
{ {
@ -257,18 +255,18 @@ transfer_relfile(pageCnvCtx *pageConverter, FileNameMap *map,
} }
unlink(new_file); unlink(new_file);
/* Copying files might take some time, so give feedback. */ /* Copying files might take some time, so give feedback. */
pg_log(PG_STATUS, "%s", old_file); pg_log(PG_STATUS, "%s", old_file);
if ((user_opts.transfer_mode == TRANSFER_MODE_LINK) && (pageConverter != NULL)) if ((user_opts.transfer_mode == TRANSFER_MODE_LINK) && (pageConverter != NULL))
pg_log(PG_FATAL, "This upgrade requires page-by-page conversion, " pg_log(PG_FATAL, "This upgrade requires page-by-page conversion, "
"you must use copy mode instead of link mode.\n"); "you must use copy mode instead of link mode.\n");
if (user_opts.transfer_mode == TRANSFER_MODE_COPY) if (user_opts.transfer_mode == TRANSFER_MODE_COPY)
{ {
pg_log(PG_VERBOSE, "copying \"%s\" to \"%s\"\n", old_file, new_file); pg_log(PG_VERBOSE, "copying \"%s\" to \"%s\"\n", old_file, new_file);
if ((msg = copyAndUpdateFile(pageConverter, old_file, new_file, true)) != NULL) if ((msg = copyAndUpdateFile(pageConverter, old_file, new_file, true)) != NULL)
pg_log(PG_FATAL, "error while copying relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n", pg_log(PG_FATAL, "error while copying relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n",
map->nspname, map->relname, old_file, new_file, msg); map->nspname, map->relname, old_file, new_file, msg);
@ -276,14 +274,13 @@ transfer_relfile(pageCnvCtx *pageConverter, FileNameMap *map,
else else
{ {
pg_log(PG_VERBOSE, "linking \"%s\" to \"%s\"\n", old_file, new_file); pg_log(PG_VERBOSE, "linking \"%s\" to \"%s\"\n", old_file, new_file);
if ((msg = linkAndUpdateFile(pageConverter, old_file, new_file)) != NULL) if ((msg = linkAndUpdateFile(pageConverter, old_file, new_file)) != NULL)
pg_log(PG_FATAL, pg_log(PG_FATAL,
"error while creating link for relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n", "error while creating link for relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n",
map->nspname, map->relname, old_file, new_file, msg); map->nspname, map->relname, old_file, new_file, msg);
} }
} }
return; return;
} }

View File

@ -79,7 +79,7 @@ get_db_conn(ClusterInfo *cluster, const char *db_name)
char * char *
cluster_conn_opts(ClusterInfo *cluster) cluster_conn_opts(ClusterInfo *cluster)
{ {
static char conn_opts[MAXPGPATH + NAMEDATALEN + 100]; static char conn_opts[MAXPGPATH + NAMEDATALEN + 100];
if (cluster->sockdir) if (cluster->sockdir)
snprintf(conn_opts, sizeof(conn_opts), snprintf(conn_opts, sizeof(conn_opts),
@ -192,7 +192,7 @@ start_postmaster(ClusterInfo *cluster, bool throw_error)
strcat(socket_string, strcat(socket_string,
" -c listen_addresses='' -c unix_socket_permissions=0700"); " -c listen_addresses='' -c unix_socket_permissions=0700");
/* Have a sockdir? Tell the postmaster. */ /* Have a sockdir? Tell the postmaster. */
if (cluster->sockdir) if (cluster->sockdir)
snprintf(socket_string + strlen(socket_string), snprintf(socket_string + strlen(socket_string),
sizeof(socket_string) - strlen(socket_string), sizeof(socket_string) - strlen(socket_string),
@ -215,13 +215,13 @@ start_postmaster(ClusterInfo *cluster, bool throw_error)
* win on ext4. * win on ext4.
*/ */
snprintf(cmd, sizeof(cmd), snprintf(cmd, sizeof(cmd),
"\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" -o \"-p %d%s%s %s%s\" start", "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" -o \"-p %d%s%s %s%s\" start",
cluster->bindir, SERVER_LOG_FILE, cluster->pgconfig, cluster->port, cluster->bindir, SERVER_LOG_FILE, cluster->pgconfig, cluster->port,
(cluster->controldata.cat_ver >= (cluster->controldata.cat_ver >=
BINARY_UPGRADE_SERVER_FLAG_CAT_VER) ? " -b" : BINARY_UPGRADE_SERVER_FLAG_CAT_VER) ? " -b" :
" -c autovacuum=off -c autovacuum_freeze_max_age=2000000000", " -c autovacuum=off -c autovacuum_freeze_max_age=2000000000",
(cluster == &new_cluster) ? (cluster == &new_cluster) ?
" -c synchronous_commit=off -c fsync=off -c full_page_writes=off" : "", " -c synchronous_commit=off -c fsync=off -c full_page_writes=off" : "",
cluster->pgopts ? cluster->pgopts : "", socket_string); cluster->pgopts ? cluster->pgopts : "", socket_string);
/* /*
@ -229,7 +229,7 @@ start_postmaster(ClusterInfo *cluster, bool throw_error)
* it might supply a reason for the failure. * it might supply a reason for the failure.
*/ */
pg_ctl_return = exec_prog(SERVER_START_LOG_FILE, pg_ctl_return = exec_prog(SERVER_START_LOG_FILE,
/* pass both file names if they differ */ /* pass both file names if they differ */
(strcmp(SERVER_LOG_FILE, (strcmp(SERVER_LOG_FILE,
SERVER_START_LOG_FILE) != 0) ? SERVER_START_LOG_FILE) != 0) ?
SERVER_LOG_FILE : NULL, SERVER_LOG_FILE : NULL,
@ -238,7 +238,7 @@ start_postmaster(ClusterInfo *cluster, bool throw_error)
if (!pg_ctl_return && !throw_error) if (!pg_ctl_return && !throw_error)
return false; return false;
/* Check to see if we can connect to the server; if not, report it. */ /* Check to see if we can connect to the server; if not, report it. */
if ((conn = get_db_conn(cluster, "template1")) == NULL || if ((conn = get_db_conn(cluster, "template1")) == NULL ||
PQstatus(conn) != CONNECTION_OK) PQstatus(conn) != CONNECTION_OK)

View File

@ -59,7 +59,7 @@ get_tablespace_paths(void)
if ((os_info.num_old_tablespaces = PQntuples(res)) != 0) if ((os_info.num_old_tablespaces = PQntuples(res)) != 0)
os_info.old_tablespaces = (char **) pg_malloc( os_info.old_tablespaces = (char **) pg_malloc(
os_info.num_old_tablespaces * sizeof(char *)); os_info.num_old_tablespaces * sizeof(char *));
else else
os_info.old_tablespaces = NULL; os_info.old_tablespaces = NULL;

View File

@ -40,8 +40,8 @@ void
end_progress_output(void) end_progress_output(void)
{ {
/* /*
* In case nothing printed; pass a space so gcc doesn't complain about * In case nothing printed; pass a space so gcc doesn't complain about
* empty format string. * empty format string.
*/ */
prep_status(" "); prep_status(" ");
} }
@ -114,13 +114,13 @@ pg_log(eLogType type, char *fmt,...)
/* for output to a display, do leading truncation and append \r */ /* for output to a display, do leading truncation and append \r */
if (isatty(fileno(stdout))) if (isatty(fileno(stdout)))
/* -2 because we use a 2-space indent */ /* -2 because we use a 2-space indent */
printf(" %s%-*.*s\r", printf(" %s%-*.*s\r",
/* prefix with "..." if we do leading truncation */ /* prefix with "..." if we do leading truncation */
strlen(message) <= MESSAGE_WIDTH - 2 ? "" : "...", strlen(message) <= MESSAGE_WIDTH - 2 ? "" : "...",
MESSAGE_WIDTH - 2, MESSAGE_WIDTH - 2, MESSAGE_WIDTH - 2, MESSAGE_WIDTH - 2,
/* optional leading truncation */ /* optional leading truncation */
strlen(message) <= MESSAGE_WIDTH - 2 ? message : strlen(message) <= MESSAGE_WIDTH - 2 ? message :
message + strlen(message) - MESSAGE_WIDTH + 3 + 2); message + strlen(message) - MESSAGE_WIDTH + 3 + 2);
else else
printf(" %s\n", _(message)); printf(" %s\n", _(message));
break; break;

View File

@ -41,7 +41,7 @@ timestamptz_to_time_t(TimestampTz t)
/* /*
* Stopgap implementation of timestamptz_to_str that doesn't depend on backend * Stopgap implementation of timestamptz_to_str that doesn't depend on backend
* infrastructure. This will work for timestamps that are within the range * infrastructure. This will work for timestamps that are within the range
* of the platform time_t type. (pg_time_t is compatible except for possibly * of the platform time_t type. (pg_time_t is compatible except for possibly
* being wider.) * being wider.)
* *
@ -77,7 +77,7 @@ timestamptz_to_str(TimestampTz dt)
* be linked/called. * be linked/called.
*/ */
void void
appendStringInfo(StringInfo str, const char *fmt, ...) appendStringInfo(StringInfo str, const char *fmt,...)
{ {
va_list args; va_list args;

View File

@ -73,7 +73,7 @@ fatal_error(const char *fmt,...)
static void static void
print_rmgr_list(void) print_rmgr_list(void)
{ {
int i; int i;
for (i = 0; i < RM_MAX_ID + 1; i++) for (i = 0; i < RM_MAX_ID + 1; i++)
{ {
@ -88,7 +88,8 @@ print_rmgr_list(void)
static bool static bool
verify_directory(const char *directory) verify_directory(const char *directory)
{ {
DIR *dir = opendir(directory); DIR *dir = opendir(directory);
if (dir == NULL) if (dir == NULL)
return false; return false;
closedir(dir); closedir(dir);
@ -113,7 +114,7 @@ split_path(const char *path, char **dir, char **fname)
if (sep != NULL) if (sep != NULL)
{ {
*dir = pg_strdup(path); *dir = pg_strdup(path);
(*dir)[(sep - path) + 1] = '\0'; /* no strndup */ (*dir)[(sep - path) + 1] = '\0'; /* no strndup */
*fname = pg_strdup(sep + 1); *fname = pg_strdup(sep + 1);
} }
/* local directory */ /* local directory */
@ -596,7 +597,7 @@ main(int argc, char **argv)
else if (!XLByteInSeg(private.startptr, segno)) else if (!XLByteInSeg(private.startptr, segno))
{ {
fprintf(stderr, fprintf(stderr,
"%s: start log position %X/%X is not inside file \"%s\"\n", "%s: start log position %X/%X is not inside file \"%s\"\n",
progname, progname,
(uint32) (private.startptr >> 32), (uint32) (private.startptr >> 32),
(uint32) private.startptr, (uint32) private.startptr,
@ -672,9 +673,9 @@ main(int argc, char **argv)
(uint32) private.startptr); (uint32) private.startptr);
/* /*
* Display a message that we're skipping data if `from` wasn't a pointer to * Display a message that we're skipping data if `from` wasn't a pointer
* the start of a record and also wasn't a pointer to the beginning of a * to the start of a record and also wasn't a pointer to the beginning of
* segment (e.g. we were used in file mode). * a segment (e.g. we were used in file mode).
*/ */
if (first_record != private.startptr && (private.startptr % XLogSegSize) != 0) if (first_record != private.startptr && (private.startptr % XLogSegSize) != 0)
printf("first record is after %X/%X, at %X/%X, skipping over %u bytes\n", printf("first record is after %X/%X, at %X/%X, skipping over %u bytes\n",

View File

@ -33,4 +33,3 @@
const RmgrDescData RmgrDescTable[RM_MAX_ID + 1] = { const RmgrDescData RmgrDescTable[RM_MAX_ID + 1] = {
#include "access/rmgrlist.h" #include "access/rmgrlist.h"
}; };

View File

@ -13,9 +13,9 @@
typedef struct RmgrDescData typedef struct RmgrDescData
{ {
const char *rm_name; const char *rm_name;
void (*rm_desc) (StringInfo buf, uint8 xl_info, char *rec); void (*rm_desc) (StringInfo buf, uint8 xl_info, char *rec);
} RmgrDescData; } RmgrDescData;
extern const RmgrDescData RmgrDescTable[]; extern const RmgrDescData RmgrDescTable[];
#endif /* RMGRDESC_H */ #endif /* RMGRDESC_H */

View File

@ -162,7 +162,8 @@ char *index_tablespace = NULL;
bool use_log; /* log transaction latencies to a file */ bool use_log; /* log transaction latencies to a file */
bool use_quiet; /* quiet logging onto stderr */ bool use_quiet; /* quiet logging onto stderr */
int agg_interval; /* log aggregates instead of individual transactions */ int agg_interval; /* log aggregates instead of individual
* transactions */
bool is_connect; /* establish connection for each transaction */ bool is_connect; /* establish connection for each transaction */
bool is_latencies; /* report per-command latencies */ bool is_latencies; /* report per-command latencies */
int main_pid; /* main process id used in log filename */ int main_pid; /* main process id used in log filename */
@ -261,13 +262,14 @@ typedef struct
typedef struct typedef struct
{ {
long start_time; /* when does the interval start */ long start_time; /* when does the interval start */
int cnt; /* number of transactions */ int cnt; /* number of transactions */
double min_duration; /* min/max durations */ double min_duration; /* min/max durations */
double max_duration; double max_duration;
double sum; /* sum(duration), sum(duration^2) - for estimates */ double sum; /* sum(duration), sum(duration^2) - for
double sum2; * estimates */
double sum2;
} AggVals; } AggVals;
static Command **sql_files[MAX_FILES]; /* SQL script files */ static Command **sql_files[MAX_FILES]; /* SQL script files */
@ -874,12 +876,13 @@ clientDone(CState *st, bool ok)
} }
static static
void agg_vals_init(AggVals * aggs, instr_time start) void
agg_vals_init(AggVals *aggs, instr_time start)
{ {
/* basic counters */ /* basic counters */
aggs->cnt = 0; /* number of transactions */ aggs->cnt = 0; /* number of transactions */
aggs->sum = 0; /* SUM(duration) */ aggs->sum = 0; /* SUM(duration) */
aggs->sum2 = 0; /* SUM(duration*duration) */ aggs->sum2 = 0; /* SUM(duration*duration) */
/* min and max transaction duration */ /* min and max transaction duration */
aggs->min_duration = 0; aggs->min_duration = 0;
@ -891,7 +894,7 @@ void agg_vals_init(AggVals * aggs, instr_time start)
/* return false iff client should be disconnected */ /* return false iff client should be disconnected */
static bool static bool
doCustom(TState *thread, CState *st, instr_time *conn_time, FILE *logfile, AggVals * agg) doCustom(TState *thread, CState *st, instr_time *conn_time, FILE *logfile, AggVals *agg)
{ {
PGresult *res; PGresult *res;
Command **commands; Command **commands;
@ -964,31 +967,39 @@ top:
/* should we aggregate the results or not? */ /* should we aggregate the results or not? */
if (agg_interval > 0) if (agg_interval > 0)
{ {
/* are we still in the same interval? if yes, accumulate the /*
* values (print them otherwise) */ * are we still in the same interval? if yes, accumulate
* the values (print them otherwise)
*/
if (agg->start_time + agg_interval >= INSTR_TIME_GET_DOUBLE(now)) if (agg->start_time + agg_interval >= INSTR_TIME_GET_DOUBLE(now))
{ {
agg->cnt += 1; agg->cnt += 1;
agg->sum += usec; agg->sum += usec;
agg->sum2 += usec * usec; agg->sum2 += usec * usec;
/* first in this aggregation interval */ /* first in this aggregation interval */
if ((agg->cnt == 1) || (usec < agg->min_duration)) if ((agg->cnt == 1) || (usec < agg->min_duration))
agg->min_duration = usec; agg->min_duration = usec;
if ((agg->cnt == 1) || (usec > agg->max_duration)) if ((agg->cnt == 1) || (usec > agg->max_duration))
agg->max_duration = usec; agg->max_duration = usec;
} }
else else
{ {
/* Loop until we reach the interval of the current transaction (and /*
* print all the empty intervals in between). */ * Loop until we reach the interval of the current
* transaction (and print all the empty intervals in
* between).
*/
while (agg->start_time + agg_interval < INSTR_TIME_GET_DOUBLE(now)) while (agg->start_time + agg_interval < INSTR_TIME_GET_DOUBLE(now))
{ {
/* This is a non-Windows branch (thanks to the ifdef in usage), so /*
* we don't need to handle this in a special way (see below). */ * This is a non-Windows branch (thanks to the
* ifdef in usage), so we don't need to handle
* this in a special way (see below).
*/
fprintf(logfile, "%ld %d %.0f %.0f %.0f %.0f\n", fprintf(logfile, "%ld %d %.0f %.0f %.0f %.0f\n",
agg->start_time, agg->cnt, agg->sum, agg->sum2, agg->start_time, agg->cnt, agg->sum, agg->sum2,
agg->min_duration, agg->max_duration); agg->min_duration, agg->max_duration);
/* move to the next inteval */ /* move to the next inteval */
@ -1002,7 +1013,10 @@ top:
agg->sum2 = 0; agg->sum2 = 0;
} }
/* and now update the reset values (include the current) */ /*
* and now update the reset values (include the
* current)
*/
agg->cnt = 1; agg->cnt = 1;
agg->min_duration = usec; agg->min_duration = usec;
agg->max_duration = usec; agg->max_duration = usec;
@ -1014,12 +1028,20 @@ top:
{ {
/* no, print raw transactions */ /* no, print raw transactions */
#ifndef WIN32 #ifndef WIN32
/* This is more than we really ought to know about instr_time */
/*
* This is more than we really ought to know about
* instr_time
*/
fprintf(logfile, "%d %d %.0f %d %ld %ld\n", fprintf(logfile, "%d %d %.0f %d %ld %ld\n",
st->id, st->cnt, usec, st->use_file, st->id, st->cnt, usec, st->use_file,
(long) now.tv_sec, (long) now.tv_usec); (long) now.tv_sec, (long) now.tv_usec);
#else #else
/* On Windows, instr_time doesn't provide a timestamp anyway */
/*
* On Windows, instr_time doesn't provide a timestamp
* anyway
*/
fprintf(logfile, "%d %d %.0f %d 0 0\n", fprintf(logfile, "%d %d %.0f %d 0 0\n",
st->id, st->cnt, usec, st->use_file); st->id, st->cnt, usec, st->use_file);
#endif #endif
@ -1234,11 +1256,11 @@ top:
} }
/* /*
* getrand() needs to be able to subtract max from min and add * getrand() needs to be able to subtract max from min and add one
* one to the result without overflowing. Since we know max > min, * to the result without overflowing. Since we know max > min, we
* we can detect overflow just by checking for a negative result. * can detect overflow just by checking for a negative result. But
* But we must check both that the subtraction doesn't overflow, * we must check both that the subtraction doesn't overflow, and
* and that adding one to the result doesn't overflow either. * that adding one to the result doesn't overflow either.
*/ */
if (max - min < 0 || (max - min) + 1 < 0) if (max - min < 0 || (max - min) + 1 < 0)
{ {
@ -1418,7 +1440,6 @@ disconnect_all(CState *state, int length)
static void static void
init(bool is_no_vacuum) init(bool is_no_vacuum)
{ {
/* The scale factor at/beyond which 32bit integers are incapable of storing /* The scale factor at/beyond which 32bit integers are incapable of storing
* 64bit values. * 64bit values.
* *
@ -1446,8 +1467,8 @@ init(bool is_no_vacuum)
{ {
"pgbench_history", "pgbench_history",
scale >= SCALE_32BIT_THRESHOLD scale >= SCALE_32BIT_THRESHOLD
? "tid int,bid int,aid bigint,delta int,mtime timestamp,filler char(22)" ? "tid int,bid int,aid bigint,delta int,mtime timestamp,filler char(22)"
: "tid int,bid int,aid int,delta int,mtime timestamp,filler char(22)", : "tid int,bid int,aid int,delta int,mtime timestamp,filler char(22)",
0 0
}, },
{ {
@ -1458,8 +1479,8 @@ init(bool is_no_vacuum)
{ {
"pgbench_accounts", "pgbench_accounts",
scale >= SCALE_32BIT_THRESHOLD scale >= SCALE_32BIT_THRESHOLD
? "aid bigint not null,bid int,abalance int,filler char(84)" ? "aid bigint not null,bid int,abalance int,filler char(84)"
: "aid int not null,bid int,abalance int,filler char(84)", : "aid int not null,bid int,abalance int,filler char(84)",
1 1
}, },
{ {
@ -1488,8 +1509,10 @@ init(bool is_no_vacuum)
int64 k; int64 k;
/* used to track elapsed time and estimate of the remaining time */ /* used to track elapsed time and estimate of the remaining time */
instr_time start, diff; instr_time start,
double elapsed_sec, remaining_sec; diff;
double elapsed_sec,
remaining_sec;
int log_interval = 1; int log_interval = 1;
if ((con = doConnect()) == NULL) if ((con = doConnect()) == NULL)
@ -1573,9 +1596,11 @@ init(bool is_no_vacuum)
exit(1); exit(1);
} }
/* If we want to stick with the original logging, print a message each /*
* 100k inserted rows. */ * If we want to stick with the original logging, print a message each
if ((! use_quiet) && (j % 100000 == 0)) * 100k inserted rows.
*/
if ((!use_quiet) && (j % 100000 == 0))
{ {
INSTR_TIME_SET_CURRENT(diff); INSTR_TIME_SET_CURRENT(diff);
INSTR_TIME_SUBTRACT(diff, start); INSTR_TIME_SUBTRACT(diff, start);
@ -1584,9 +1609,9 @@ init(bool is_no_vacuum)
remaining_sec = (scale * naccounts - j) * elapsed_sec / j; remaining_sec = (scale * naccounts - j) * elapsed_sec / j;
fprintf(stderr, INT64_FORMAT " of " INT64_FORMAT " tuples (%d%%) done (elapsed %.2f s, remaining %.2f s).\n", fprintf(stderr, INT64_FORMAT " of " INT64_FORMAT " tuples (%d%%) done (elapsed %.2f s, remaining %.2f s).\n",
j, (int64)naccounts * scale, j, (int64) naccounts * scale,
(int) (((int64) j * 100) / (naccounts * scale)), (int) (((int64) j * 100) / (naccounts * scale)),
elapsed_sec, remaining_sec); elapsed_sec, remaining_sec);
} }
/* let's not call the timing for each row, but only each 100 rows */ /* let's not call the timing for each row, but only each 100 rows */
else if (use_quiet && (j % 100 == 0)) else if (use_quiet && (j % 100 == 0))
@ -1598,14 +1623,15 @@ init(bool is_no_vacuum)
remaining_sec = (scale * naccounts - j) * elapsed_sec / j; remaining_sec = (scale * naccounts - j) * elapsed_sec / j;
/* have we reached the next interval (or end)? */ /* have we reached the next interval (or end)? */
if ((j == scale * naccounts) || (elapsed_sec >= log_interval * LOG_STEP_SECONDS)) { if ((j == scale * naccounts) || (elapsed_sec >= log_interval * LOG_STEP_SECONDS))
{
fprintf(stderr, INT64_FORMAT " of " INT64_FORMAT " tuples (%d%%) done (elapsed %.2f s, remaining %.2f s).\n", fprintf(stderr, INT64_FORMAT " of " INT64_FORMAT " tuples (%d%%) done (elapsed %.2f s, remaining %.2f s).\n",
j, (int64)naccounts * scale, j, (int64) naccounts * scale,
(int) (((int64) j * 100) / (naccounts * scale)), elapsed_sec, remaining_sec); (int) (((int64) j * 100) / (naccounts * scale)), elapsed_sec, remaining_sec);
/* skip to the next interval */ /* skip to the next interval */
log_interval = (int)ceil(elapsed_sec/LOG_STEP_SECONDS); log_interval = (int) ceil(elapsed_sec / LOG_STEP_SECONDS);
} }
} }
@ -2393,17 +2419,20 @@ main(int argc, char **argv)
exit(1); exit(1);
} }
if (agg_interval > 0 && (! use_log)) { if (agg_interval > 0 && (!use_log))
{
fprintf(stderr, "log aggregation is allowed only when actually logging transactions\n"); fprintf(stderr, "log aggregation is allowed only when actually logging transactions\n");
exit(1); exit(1);
} }
if ((duration > 0) && (agg_interval > duration)) { if ((duration > 0) && (agg_interval > duration))
{
fprintf(stderr, "number of seconds for aggregation (%d) must not be higher that test duration (%d)\n", agg_interval, duration); fprintf(stderr, "number of seconds for aggregation (%d) must not be higher that test duration (%d)\n", agg_interval, duration);
exit(1); exit(1);
} }
if ((duration > 0) && (agg_interval > 0) && (duration % agg_interval != 0)) { if ((duration > 0) && (agg_interval > 0) && (duration % agg_interval != 0))
{
fprintf(stderr, "duration (%d) must be a multiple of aggregation interval (%d)\n", duration, agg_interval); fprintf(stderr, "duration (%d) must be a multiple of aggregation interval (%d)\n", duration, agg_interval);
exit(1); exit(1);
} }
@ -2670,7 +2699,7 @@ threadRun(void *arg)
AggVals aggs; AggVals aggs;
result = pg_malloc(sizeof(TResult)); result = pg_malloc(sizeof(TResult));
INSTR_TIME_SET_ZERO(result->conn_time); INSTR_TIME_SET_ZERO(result->conn_time);
/* open log file if requested */ /* open log file if requested */
@ -2706,7 +2735,7 @@ threadRun(void *arg)
INSTR_TIME_SUBTRACT(result->conn_time, thread->start_time); INSTR_TIME_SUBTRACT(result->conn_time, thread->start_time);
agg_vals_init(&aggs, thread->start_time); agg_vals_init(&aggs, thread->start_time);
/* send start up queries in async manner */ /* send start up queries in async manner */
for (i = 0; i < nstate; i++) for (i = 0; i < nstate; i++)
{ {

View File

@ -117,14 +117,11 @@ mp_result mp_int_mul_value(mp_int a, int value, mp_int c);
mp_result mp_int_mul_pow2(mp_int a, int p2, mp_int c); mp_result mp_int_mul_pow2(mp_int a, int p2, mp_int c);
mp_result mp_int_sqr(mp_int a, mp_int c); /* c = a * a */ mp_result mp_int_sqr(mp_int a, mp_int c); /* c = a * a */
mp_result mp_result mp_int_div(mp_int a, mp_int b, /* q = a / b */
mp_int_div(mp_int a, mp_int b, /* q = a / b */
mp_int q, mp_int r); /* r = a % b */ mp_int q, mp_int r); /* r = a % b */
mp_result mp_result mp_int_div_value(mp_int a, int value, /* q = a / value */
mp_int_div_value(mp_int a, int value, /* q = a / value */
mp_int q, int *r); /* r = a % value */ mp_int q, int *r); /* r = a % value */
mp_result mp_result mp_int_div_pow2(mp_int a, int p2, /* q = a / 2^p2 */
mp_int_div_pow2(mp_int a, int p2, /* q = a / 2^p2 */
mp_int q, mp_int r); /* r = q % 2^p2 */ mp_int q, mp_int r); /* r = q % 2^p2 */
mp_result mp_int_mod(mp_int a, mp_int m, mp_int c); /* c = a % m */ mp_result mp_int_mod(mp_int a, mp_int m, mp_int c); /* c = a % m */
@ -143,17 +140,13 @@ int mp_int_divisible_value(mp_int a, int v);
/* Returns k >= 0 such that z = 2^k, if one exists; otherwise < 0 */ /* Returns k >= 0 such that z = 2^k, if one exists; otherwise < 0 */
int mp_int_is_pow2(mp_int z); int mp_int_is_pow2(mp_int z);
mp_result mp_result mp_int_exptmod(mp_int a, mp_int b, mp_int m,
mp_int_exptmod(mp_int a, mp_int b, mp_int m,
mp_int c); /* c = a^b (mod m) */ mp_int c); /* c = a^b (mod m) */
mp_result mp_result mp_int_exptmod_evalue(mp_int a, int value,
mp_int_exptmod_evalue(mp_int a, int value,
mp_int m, mp_int c); /* c = a^v (mod m) */ mp_int m, mp_int c); /* c = a^v (mod m) */
mp_result mp_result mp_int_exptmod_bvalue(int value, mp_int b,
mp_int_exptmod_bvalue(int value, mp_int b,
mp_int m, mp_int c); /* c = v^b (mod m) */ mp_int m, mp_int c); /* c = v^b (mod m) */
mp_result mp_result mp_int_exptmod_known(mp_int a, mp_int b,
mp_int_exptmod_known(mp_int a, mp_int b,
mp_int m, mp_int mu, mp_int m, mp_int mu,
mp_int c); /* c = a^b (mod m) */ mp_int c); /* c = a^b (mod m) */
mp_result mp_int_redux_const(mp_int m, mp_int c); mp_result mp_int_redux_const(mp_int m, mp_int c);
@ -162,8 +155,7 @@ mp_result mp_int_invmod(mp_int a, mp_int m, mp_int c); /* c = 1/a (mod m) */
mp_result mp_int_gcd(mp_int a, mp_int b, mp_int c); /* c = gcd(a, b) */ mp_result mp_int_gcd(mp_int a, mp_int b, mp_int c); /* c = gcd(a, b) */
mp_result mp_result mp_int_egcd(mp_int a, mp_int b, mp_int c, /* c = gcd(a, b) */
mp_int_egcd(mp_int a, mp_int b, mp_int c, /* c = gcd(a, b) */
mp_int x, mp_int y); /* c = ax + by */ mp_int x, mp_int y); /* c = ax + by */
mp_result mp_int_sqrt(mp_int a, mp_int c); /* c = floor(sqrt(q)) */ mp_result mp_int_sqrt(mp_int a, mp_int c); /* c = floor(sqrt(q)) */

View File

@ -265,8 +265,7 @@ int pgp_s2k_read(PullFilter *src, PGP_S2K *s2k);
int pgp_s2k_process(PGP_S2K *s2k, int cipher, const uint8 *key, int klen); int pgp_s2k_process(PGP_S2K *s2k, int cipher, const uint8 *key, int klen);
typedef struct PGP_CFB PGP_CFB; typedef struct PGP_CFB PGP_CFB;
int int pgp_cfb_create(PGP_CFB **ctx_p, int algo,
pgp_cfb_create(PGP_CFB **ctx_p, int algo,
const uint8 *key, int key_len, int recync, uint8 *iv); const uint8 *key, int key_len, int recync, uint8 *iv);
void pgp_cfb_free(PGP_CFB *ctx); void pgp_cfb_free(PGP_CFB *ctx);
int pgp_cfb_encrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst); int pgp_cfb_encrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst);

View File

@ -124,7 +124,7 @@ pgrowlocks(PG_FUNCTION_ARGS)
/* scan the relation */ /* scan the relation */
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
{ {
HTSU_Result htsu; HTSU_Result htsu;
TransactionId xmax; TransactionId xmax;
uint16 infomask; uint16 infomask;
@ -152,7 +152,7 @@ pgrowlocks(PG_FUNCTION_ARGS)
values = (char **) palloc(mydata->ncolumns * sizeof(char *)); values = (char **) palloc(mydata->ncolumns * sizeof(char *));
values[Atnum_tid] = (char *) DirectFunctionCall1(tidout, values[Atnum_tid] = (char *) DirectFunctionCall1(tidout,
PointerGetDatum(&tuple->t_self)); PointerGetDatum(&tuple->t_self));
values[Atnum_xmax] = palloc(NCHARS * sizeof(char)); values[Atnum_xmax] = palloc(NCHARS * sizeof(char));
snprintf(values[Atnum_xmax], NCHARS, "%d", xmax); snprintf(values[Atnum_xmax], NCHARS, "%d", xmax);
@ -166,7 +166,7 @@ pgrowlocks(PG_FUNCTION_ARGS)
values[Atnum_ismulti] = pstrdup("true"); values[Atnum_ismulti] = pstrdup("true");
allow_old = !(infomask & HEAP_LOCK_MASK) && allow_old = !(infomask & HEAP_LOCK_MASK) &&
(infomask & HEAP_XMAX_LOCK_ONLY); (infomask & HEAP_XMAX_LOCK_ONLY);
nmembers = GetMultiXactIdMembers(xmax, &members, allow_old); nmembers = GetMultiXactIdMembers(xmax, &members, allow_old);
if (nmembers == -1) if (nmembers == -1)
{ {
@ -280,8 +280,8 @@ pgrowlocks(PG_FUNCTION_ARGS)
result = HeapTupleGetDatum(tuple); result = HeapTupleGetDatum(tuple);
/* /*
* no need to pfree what we allocated; it's on a short-lived memory * no need to pfree what we allocated; it's on a short-lived
* context anyway * memory context anyway
*/ */
SRF_RETURN_NEXT(funcctx, result); SRF_RETURN_NEXT(funcctx, result);

View File

@ -93,7 +93,7 @@ typedef struct GinIndexStat
{ {
int32 version; int32 version;
BlockNumber pending_pages; BlockNumber pending_pages;
int64 pending_tuples; int64 pending_tuples;
} GinIndexStat; } GinIndexStat;
@ -324,7 +324,7 @@ pgstatginindex(PG_FUNCTION_ARGS)
Relation rel; Relation rel;
Buffer buffer; Buffer buffer;
Page page; Page page;
GinMetaPageData *metadata; GinMetaPageData *metadata;
GinIndexStat stats; GinIndexStat stats;
HeapTuple tuple; HeapTuple tuple;
TupleDesc tupleDesc; TupleDesc tupleDesc;
@ -351,7 +351,7 @@ pgstatginindex(PG_FUNCTION_ARGS)
if (RELATION_IS_OTHER_TEMP(rel)) if (RELATION_IS_OTHER_TEMP(rel))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot access temporary indexes of other sessions"))); errmsg("cannot access temporary indexes of other sessions")));
/* /*
* Read metapage * Read metapage

View File

@ -326,7 +326,7 @@ configure_remote_session(PGconn *conn)
* anyway. However it makes the regression test outputs more predictable. * anyway. However it makes the regression test outputs more predictable.
* *
* We don't risk setting remote zone equal to ours, since the remote * We don't risk setting remote zone equal to ours, since the remote
* server might use a different timezone database. Instead, use UTC * server might use a different timezone database. Instead, use UTC
* (quoted, because very old servers are picky about case). * (quoted, because very old servers are picky about case).
*/ */
do_sql_command(conn, "SET timezone = 'UTC'"); do_sql_command(conn, "SET timezone = 'UTC'");

View File

@ -133,7 +133,7 @@ typedef struct PgFdwScanState
/* extracted fdw_private data */ /* extracted fdw_private data */
char *query; /* text of SELECT command */ char *query; /* text of SELECT command */
List *retrieved_attrs; /* list of retrieved attribute numbers */ List *retrieved_attrs; /* list of retrieved attribute numbers */
/* for remote query execution */ /* for remote query execution */
PGconn *conn; /* connection for the scan */ PGconn *conn; /* connection for the scan */
@ -174,7 +174,7 @@ typedef struct PgFdwModifyState
char *query; /* text of INSERT/UPDATE/DELETE command */ char *query; /* text of INSERT/UPDATE/DELETE command */
List *target_attrs; /* list of target attribute numbers */ List *target_attrs; /* list of target attribute numbers */
bool has_returning; /* is there a RETURNING clause? */ bool has_returning; /* is there a RETURNING clause? */
List *retrieved_attrs; /* attr numbers retrieved by RETURNING */ List *retrieved_attrs; /* attr numbers retrieved by RETURNING */
/* info about parameters for prepared statement */ /* info about parameters for prepared statement */
AttrNumber ctidAttno; /* attnum of input resjunk ctid column */ AttrNumber ctidAttno; /* attnum of input resjunk ctid column */
@ -192,7 +192,7 @@ typedef struct PgFdwAnalyzeState
{ {
Relation rel; /* relcache entry for the foreign table */ Relation rel; /* relcache entry for the foreign table */
AttInMetadata *attinmeta; /* attribute datatype conversion metadata */ AttInMetadata *attinmeta; /* attribute datatype conversion metadata */
List *retrieved_attrs; /* attr numbers retrieved by query */ List *retrieved_attrs; /* attr numbers retrieved by query */
/* collected sample rows */ /* collected sample rows */
HeapTuple *rows; /* array of size targrows */ HeapTuple *rows; /* array of size targrows */
@ -424,8 +424,8 @@ postgresGetForeignRelSize(PlannerInfo *root,
/* /*
* If the table or the server is configured to use remote estimates, * If the table or the server is configured to use remote estimates,
* identify which user to do remote access as during planning. This * identify which user to do remote access as during planning. This
* should match what ExecCheckRTEPerms() does. If we fail due to lack of * should match what ExecCheckRTEPerms() does. If we fail due to lack of
* permissions, the query would have failed at runtime anyway. * permissions, the query would have failed at runtime anyway.
*/ */
if (fpinfo->use_remote_estimate) if (fpinfo->use_remote_estimate)
@ -447,7 +447,7 @@ postgresGetForeignRelSize(PlannerInfo *root,
/* /*
* Identify which attributes will need to be retrieved from the remote * Identify which attributes will need to be retrieved from the remote
* server. These include all attrs needed for joins or final output, plus * server. These include all attrs needed for joins or final output, plus
* all attrs used in the local_conds. (Note: if we end up using a * all attrs used in the local_conds. (Note: if we end up using a
* parameterized scan, it's possible that some of the join clauses will be * parameterized scan, it's possible that some of the join clauses will be
* sent to the remote and thus we wouldn't really need to retrieve the * sent to the remote and thus we wouldn't really need to retrieve the
@ -921,7 +921,7 @@ postgresBeginForeignScan(ForeignScanState *node, int eflags)
fsstate->query = strVal(list_nth(fsplan->fdw_private, fsstate->query = strVal(list_nth(fsplan->fdw_private,
FdwScanPrivateSelectSql)); FdwScanPrivateSelectSql));
fsstate->retrieved_attrs = (List *) list_nth(fsplan->fdw_private, fsstate->retrieved_attrs = (List *) list_nth(fsplan->fdw_private,
FdwScanPrivateRetrievedAttrs); FdwScanPrivateRetrievedAttrs);
/* Create contexts for batches of tuples and per-tuple temp workspace. */ /* Create contexts for batches of tuples and per-tuple temp workspace. */
fsstate->batch_cxt = AllocSetContextCreate(estate->es_query_cxt, fsstate->batch_cxt = AllocSetContextCreate(estate->es_query_cxt,
@ -1305,7 +1305,7 @@ postgresBeginForeignModify(ModifyTableState *mtstate,
fmstate->has_returning = intVal(list_nth(fdw_private, fmstate->has_returning = intVal(list_nth(fdw_private,
FdwModifyPrivateHasReturning)); FdwModifyPrivateHasReturning));
fmstate->retrieved_attrs = (List *) list_nth(fdw_private, fmstate->retrieved_attrs = (List *) list_nth(fdw_private,
FdwModifyPrivateRetrievedAttrs); FdwModifyPrivateRetrievedAttrs);
/* Create context for per-tuple temp workspace. */ /* Create context for per-tuple temp workspace. */
fmstate->temp_cxt = AllocSetContextCreate(estate->es_query_cxt, fmstate->temp_cxt = AllocSetContextCreate(estate->es_query_cxt,
@ -1903,7 +1903,7 @@ create_cursor(ForeignScanState *node)
* Notice that we pass NULL for paramTypes, thus forcing the remote server * Notice that we pass NULL for paramTypes, thus forcing the remote server
* to infer types for all parameters. Since we explicitly cast every * to infer types for all parameters. Since we explicitly cast every
* parameter (see deparse.c), the "inference" is trivial and will produce * parameter (see deparse.c), the "inference" is trivial and will produce
* the desired result. This allows us to avoid assuming that the remote * the desired result. This allows us to avoid assuming that the remote
* server has the same OIDs we do for the parameters' types. * server has the same OIDs we do for the parameters' types.
* *
* We don't use a PG_TRY block here, so be careful not to throw error * We don't use a PG_TRY block here, so be careful not to throw error
@ -2488,7 +2488,7 @@ analyze_row_processor(PGresult *res, int row, PgFdwAnalyzeState *astate)
astate->rows[pos] = make_tuple_from_result_row(res, row, astate->rows[pos] = make_tuple_from_result_row(res, row,
astate->rel, astate->rel,
astate->attinmeta, astate->attinmeta,
astate->retrieved_attrs, astate->retrieved_attrs,
astate->temp_cxt); astate->temp_cxt);
MemoryContextSwitchTo(oldcontext); MemoryContextSwitchTo(oldcontext);

View File

@ -71,6 +71,6 @@ extern void deparseDeleteSql(StringInfo buf, PlannerInfo *root,
List **retrieved_attrs); List **retrieved_attrs);
extern void deparseAnalyzeSizeSql(StringInfo buf, Relation rel); extern void deparseAnalyzeSizeSql(StringInfo buf, Relation rel);
extern void deparseAnalyzeSql(StringInfo buf, Relation rel, extern void deparseAnalyzeSql(StringInfo buf, Relation rel,
List **retrieved_attrs); List **retrieved_attrs);
#endif /* POSTGRES_FDW_H */ #endif /* POSTGRES_FDW_H */

View File

@ -98,7 +98,7 @@ sepgsql_object_access(ObjectAccessType access,
case OAT_POST_CREATE: case OAT_POST_CREATE:
{ {
ObjectAccessPostCreate *pc_arg = arg; ObjectAccessPostCreate *pc_arg = arg;
bool is_internal; bool is_internal;
is_internal = pc_arg ? pc_arg->is_internal : false; is_internal = pc_arg ? pc_arg->is_internal : false;
@ -107,7 +107,7 @@ sepgsql_object_access(ObjectAccessType access,
case DatabaseRelationId: case DatabaseRelationId:
Assert(!is_internal); Assert(!is_internal);
sepgsql_database_post_create(objectId, sepgsql_database_post_create(objectId,
sepgsql_context_info.createdb_dtemplate); sepgsql_context_info.createdb_dtemplate);
break; break;
case NamespaceRelationId: case NamespaceRelationId:
@ -190,8 +190,8 @@ sepgsql_object_access(ObjectAccessType access,
case OAT_POST_ALTER: case OAT_POST_ALTER:
{ {
ObjectAccessPostAlter *pa_arg = arg; ObjectAccessPostAlter *pa_arg = arg;
bool is_internal = pa_arg->is_internal; bool is_internal = pa_arg->is_internal;
switch (classId) switch (classId)
{ {
@ -207,21 +207,21 @@ sepgsql_object_access(ObjectAccessType access,
case RelationRelationId: case RelationRelationId:
if (subId == 0) if (subId == 0)
{ {
/* /*
* A case when we don't want to apply permission * A case when we don't want to apply permission
* check is that relation is internally altered * check is that relation is internally altered
* without user's intention. E.g, no need to * without user's intention. E.g, no need to check
* check on toast table/index to be renamed at * on toast table/index to be renamed at end of
* end of the table rewrites. * the table rewrites.
*/ */
if (is_internal) if (is_internal)
break; break;
sepgsql_relation_setattr(objectId); sepgsql_relation_setattr(objectId);
} }
else else
sepgsql_attribute_setattr(objectId, subId); sepgsql_attribute_setattr(objectId, subId);
break; break;
case ProcedureRelationId: case ProcedureRelationId:
@ -238,11 +238,11 @@ sepgsql_object_access(ObjectAccessType access,
case OAT_NAMESPACE_SEARCH: case OAT_NAMESPACE_SEARCH:
{ {
ObjectAccessNamespaceSearch *ns_arg = arg; ObjectAccessNamespaceSearch *ns_arg = arg;
/* /*
* If stacked extension already decided not to allow users * If stacked extension already decided not to allow users to
* to search this schema, we just stick with that decision. * search this schema, we just stick with that decision.
*/ */
if (!ns_arg->result) if (!ns_arg->result)
break; break;

View File

@ -351,9 +351,8 @@ sepgsql_fmgr_hook(FmgrHookEventType event,
* *
* Also, db_procedure:entrypoint permission should be checked * Also, db_procedure:entrypoint permission should be checked
* whether this procedure can perform as an entrypoint of the * whether this procedure can perform as an entrypoint of the
* trusted procedure, or not. * trusted procedure, or not. Note that db_procedure:execute
* Note that db_procedure:execute permission shall be checked * permission shall be checked individually.
* individually.
*/ */
if (stack->new_label) if (stack->new_label)
{ {

View File

@ -236,16 +236,16 @@ sepgsql_proc_relabel(Oid functionId, const char *seclabel)
void void
sepgsql_proc_setattr(Oid functionId) sepgsql_proc_setattr(Oid functionId)
{ {
Relation rel; Relation rel;
ScanKeyData skey; ScanKeyData skey;
SysScanDesc sscan; SysScanDesc sscan;
HeapTuple oldtup; HeapTuple oldtup;
HeapTuple newtup; HeapTuple newtup;
Form_pg_proc oldform; Form_pg_proc oldform;
Form_pg_proc newform; Form_pg_proc newform;
uint32 required; uint32 required;
ObjectAddress object; ObjectAddress object;
char *audit_name; char *audit_name;
/* /*
* Fetch newer catalog * Fetch newer catalog
@ -297,7 +297,7 @@ sepgsql_proc_setattr(Oid functionId)
sepgsql_avc_check_perms(&object, sepgsql_avc_check_perms(&object,
SEPG_CLASS_DB_PROCEDURE, SEPG_CLASS_DB_PROCEDURE,
required, required,
audit_name, audit_name,
true); true);
/* cleanups */ /* cleanups */

View File

@ -31,7 +31,7 @@
#include "sepgsql.h" #include "sepgsql.h"
static void sepgsql_index_modify(Oid indexOid); static void sepgsql_index_modify(Oid indexOid);
/* /*
* sepgsql_attribute_post_create * sepgsql_attribute_post_create
@ -571,13 +571,13 @@ sepgsql_relation_relabel(Oid relOid, const char *seclabel)
void void
sepgsql_relation_setattr(Oid relOid) sepgsql_relation_setattr(Oid relOid)
{ {
Relation rel; Relation rel;
ScanKeyData skey; ScanKeyData skey;
SysScanDesc sscan; SysScanDesc sscan;
HeapTuple oldtup; HeapTuple oldtup;
HeapTuple newtup; HeapTuple newtup;
Form_pg_class oldform; Form_pg_class oldform;
Form_pg_class newform; Form_pg_class newform;
ObjectAddress object; ObjectAddress object;
char *audit_name; char *audit_name;
uint16_t tclass; uint16_t tclass;
@ -680,8 +680,8 @@ sepgsql_relation_setattr_extra(Relation catalog,
AttrNumber anum_relation_id, AttrNumber anum_relation_id,
AttrNumber anum_extra_id) AttrNumber anum_extra_id)
{ {
ScanKeyData skey; ScanKeyData skey;
SysScanDesc sscan; SysScanDesc sscan;
HeapTuple tuple; HeapTuple tuple;
Datum datum; Datum datum;
bool isnull; bool isnull;
@ -708,7 +708,7 @@ sepgsql_relation_setattr_extra(Relation catalog,
/* /*
* sepgsql_index_modify * sepgsql_index_modify
* Handle index create, update, drop * Handle index create, update, drop
* *
* Unlike other relation kinds, indexes do not have their own security labels, * Unlike other relation kinds, indexes do not have their own security labels,
* so instead of doing checks directly, treat them as extra attributes of their * so instead of doing checks directly, treat them as extra attributes of their

View File

@ -81,6 +81,7 @@ sepgsql_schema_post_create(Oid namespaceId)
tcontext, tcontext,
SEPG_CLASS_DB_SCHEMA, SEPG_CLASS_DB_SCHEMA,
nsp_name); nsp_name);
/* /*
* check db_schema:{create} * check db_schema:{create}
*/ */

View File

@ -40,7 +40,7 @@ typedef struct TrieChar
static TrieChar * static TrieChar *
placeChar(TrieChar *node, unsigned char *str, int lenstr, char *replaceTo, int replacelen) placeChar(TrieChar *node, unsigned char *str, int lenstr, char *replaceTo, int replacelen)
{ {
TrieChar *curnode; TrieChar *curnode;
if (!node) if (!node)
{ {
@ -77,7 +77,7 @@ placeChar(TrieChar *node, unsigned char *str, int lenstr, char *replaceTo, int r
static TrieChar * static TrieChar *
initTrie(char *filename) initTrie(char *filename)
{ {
TrieChar *volatile rootTrie = NULL; TrieChar *volatile rootTrie = NULL;
MemoryContext ccxt = CurrentMemoryContext; MemoryContext ccxt = CurrentMemoryContext;
tsearch_readline_state trst; tsearch_readline_state trst;
volatile bool skip; volatile bool skip;
@ -162,8 +162,8 @@ initTrie(char *filename)
if (state >= 3) if (state >= 3)
rootTrie = placeChar(rootTrie, rootTrie = placeChar(rootTrie,
(unsigned char *) src, srclen, (unsigned char *) src, srclen,
trg, trglen); trg, trglen);
pfree(line); pfree(line);
} }

View File

@ -82,7 +82,7 @@ vacuumlo(const char *database, const struct _param * param)
*/ */
do do
{ {
#define PARAMS_ARRAY_SIZE 7 #define PARAMS_ARRAY_SIZE 7
const char *keywords[PARAMS_ARRAY_SIZE]; const char *keywords[PARAMS_ARRAY_SIZE];
const char *values[PARAMS_ARRAY_SIZE]; const char *values[PARAMS_ARRAY_SIZE];

View File

@ -43,27 +43,27 @@
PG_MODULE_MAGIC; PG_MODULE_MAGIC;
void _PG_init(void); void _PG_init(void);
/* flags set by signal handlers */ /* flags set by signal handlers */
static volatile sig_atomic_t got_sighup = false; static volatile sig_atomic_t got_sighup = false;
static volatile sig_atomic_t got_sigterm = false; static volatile sig_atomic_t got_sigterm = false;
/* GUC variables */ /* GUC variables */
static int worker_spi_naptime = 10; static int worker_spi_naptime = 10;
static int worker_spi_total_workers = 2; static int worker_spi_total_workers = 2;
typedef struct worktable typedef struct worktable
{ {
const char *schema; const char *schema;
const char *name; const char *name;
} worktable; } worktable;
/* /*
* Signal handler for SIGTERM * Signal handler for SIGTERM
* Set a flag to let the main loop to terminate, and set our latch to wake * Set a flag to let the main loop to terminate, and set our latch to wake
* it up. * it up.
*/ */
static void static void
worker_spi_sigterm(SIGNAL_ARGS) worker_spi_sigterm(SIGNAL_ARGS)
@ -79,8 +79,8 @@ worker_spi_sigterm(SIGNAL_ARGS)
/* /*
* Signal handler for SIGHUP * Signal handler for SIGHUP
* Set a flag to let the main loop to reread the config file, and set * Set a flag to let the main loop to reread the config file, and set
* our latch to wake it up. * our latch to wake it up.
*/ */
static void static void
worker_spi_sighup(SIGNAL_ARGS) worker_spi_sighup(SIGNAL_ARGS)
@ -97,10 +97,10 @@ worker_spi_sighup(SIGNAL_ARGS)
static void static void
initialize_worker_spi(worktable *table) initialize_worker_spi(worktable *table)
{ {
int ret; int ret;
int ntup; int ntup;
bool isnull; bool isnull;
StringInfoData buf; StringInfoData buf;
SetCurrentStatementStartTimestamp(); SetCurrentStatementStartTimestamp();
StartTransactionCommand(); StartTransactionCommand();
@ -132,11 +132,11 @@ initialize_worker_spi(worktable *table)
appendStringInfo(&buf, appendStringInfo(&buf,
"CREATE SCHEMA \"%s\" " "CREATE SCHEMA \"%s\" "
"CREATE TABLE \"%s\" (" "CREATE TABLE \"%s\" ("
" type text CHECK (type IN ('total', 'delta')), " " type text CHECK (type IN ('total', 'delta')), "
" value integer)" " value integer)"
"CREATE UNIQUE INDEX \"%s_unique_total\" ON \"%s\" (type) " "CREATE UNIQUE INDEX \"%s_unique_total\" ON \"%s\" (type) "
"WHERE type = 'total'", "WHERE type = 'total'",
table->schema, table->name, table->name, table->name); table->schema, table->name, table->name, table->name);
/* set statement start time */ /* set statement start time */
SetCurrentStatementStartTimestamp(); SetCurrentStatementStartTimestamp();
@ -156,8 +156,8 @@ initialize_worker_spi(worktable *table)
static void static void
worker_spi_main(void *main_arg) worker_spi_main(void *main_arg)
{ {
worktable *table = (worktable *) main_arg; worktable *table = (worktable *) main_arg;
StringInfoData buf; StringInfoData buf;
/* We're now ready to receive signals */ /* We're now ready to receive signals */
BackgroundWorkerUnblockSignals(); BackgroundWorkerUnblockSignals();
@ -170,7 +170,7 @@ worker_spi_main(void *main_arg)
initialize_worker_spi(table); initialize_worker_spi(table);
/* /*
* Quote identifiers passed to us. Note that this must be done after * Quote identifiers passed to us. Note that this must be done after
* initialize_worker_spi, because that routine assumes the names are not * initialize_worker_spi, because that routine assumes the names are not
* quoted. * quoted.
* *
@ -200,8 +200,8 @@ worker_spi_main(void *main_arg)
*/ */
while (!got_sigterm) while (!got_sigterm)
{ {
int ret; int ret;
int rc; int rc;
/* /*
* Background workers mustn't call usleep() or any direct equivalent: * Background workers mustn't call usleep() or any direct equivalent:
@ -221,27 +221,27 @@ worker_spi_main(void *main_arg)
/* /*
* In case of a SIGHUP, just reload the configuration. * In case of a SIGHUP, just reload the configuration.
*/ */
if (got_sighup) if (got_sighup)
{ {
got_sighup = false; got_sighup = false;
ProcessConfigFile(PGC_SIGHUP); ProcessConfigFile(PGC_SIGHUP);
} }
/* /*
* Start a transaction on which we can run queries. Note that each * Start a transaction on which we can run queries. Note that each
* StartTransactionCommand() call should be preceded by a * StartTransactionCommand() call should be preceded by a
* SetCurrentStatementStartTimestamp() call, which sets both the time * SetCurrentStatementStartTimestamp() call, which sets both the time
* for the statement we're about the run, and also the transaction * for the statement we're about the run, and also the transaction
* start time. Also, each other query sent to SPI should probably be * start time. Also, each other query sent to SPI should probably be
* preceded by SetCurrentStatementStartTimestamp(), so that statement * preceded by SetCurrentStatementStartTimestamp(), so that statement
* start time is always up to date. * start time is always up to date.
* *
* The SPI_connect() call lets us run queries through the SPI manager, * The SPI_connect() call lets us run queries through the SPI manager,
* and the PushActiveSnapshot() call creates an "active" snapshot which * and the PushActiveSnapshot() call creates an "active" snapshot
* is necessary for queries to have MVCC data to work on. * which is necessary for queries to have MVCC data to work on.
* *
* The pgstat_report_activity() call makes our activity visible through * The pgstat_report_activity() call makes our activity visible
* the pgstat views. * through the pgstat views.
*/ */
SetCurrentStatementStartTimestamp(); SetCurrentStatementStartTimestamp();
StartTransactionCommand(); StartTransactionCommand();
@ -258,12 +258,12 @@ worker_spi_main(void *main_arg)
if (SPI_processed > 0) if (SPI_processed > 0)
{ {
bool isnull; bool isnull;
int32 val; int32 val;
val = DatumGetInt32(SPI_getbinval(SPI_tuptable->vals[0], val = DatumGetInt32(SPI_getbinval(SPI_tuptable->vals[0],
SPI_tuptable->tupdesc, SPI_tuptable->tupdesc,
1, &isnull)); 1, &isnull));
if (!isnull) if (!isnull)
elog(LOG, "%s: count in %s.%s is now %d", elog(LOG, "%s: count in %s.%s is now %d",
MyBgworkerEntry->bgw_name, MyBgworkerEntry->bgw_name,
@ -291,36 +291,36 @@ worker_spi_main(void *main_arg)
void void
_PG_init(void) _PG_init(void)
{ {
BackgroundWorker worker; BackgroundWorker worker;
worktable *table; worktable *table;
unsigned int i; unsigned int i;
char name[20]; char name[20];
/* get the configuration */ /* get the configuration */
DefineCustomIntVariable("worker_spi.naptime", DefineCustomIntVariable("worker_spi.naptime",
"Duration between each check (in seconds).", "Duration between each check (in seconds).",
NULL, NULL,
&worker_spi_naptime, &worker_spi_naptime,
10, 10,
1, 1,
INT_MAX, INT_MAX,
PGC_SIGHUP, PGC_SIGHUP,
0, 0,
NULL, NULL,
NULL, NULL,
NULL); NULL);
DefineCustomIntVariable("worker_spi.total_workers", DefineCustomIntVariable("worker_spi.total_workers",
"Number of workers.", "Number of workers.",
NULL, NULL,
&worker_spi_total_workers, &worker_spi_total_workers,
2, 2,
1, 1,
100, 100,
PGC_POSTMASTER, PGC_POSTMASTER,
0, 0,
NULL, NULL,
NULL, NULL,
NULL); NULL);
/* set up common data for all our workers */ /* set up common data for all our workers */
worker.bgw_flags = BGWORKER_SHMEM_ACCESS | worker.bgw_flags = BGWORKER_SHMEM_ACCESS |

View File

@ -173,7 +173,6 @@ void
ginFindParents(GinBtree btree, GinBtreeStack *stack, ginFindParents(GinBtree btree, GinBtreeStack *stack,
BlockNumber rootBlkno) BlockNumber rootBlkno)
{ {
Page page; Page page;
Buffer buffer; Buffer buffer;
BlockNumber blkno, BlockNumber blkno,

View File

@ -610,9 +610,9 @@ gistProcessItup(GISTBuildState *buildstate, IndexTuple itup,
newtup = gistgetadjusted(indexrel, idxtuple, itup, giststate); newtup = gistgetadjusted(indexrel, idxtuple, itup, giststate);
if (newtup) if (newtup)
{ {
blkno = gistbufferinginserttuples(buildstate, buffer, level, blkno = gistbufferinginserttuples(buildstate, buffer, level,
&newtup, 1, childoffnum, &newtup, 1, childoffnum,
InvalidBlockNumber, InvalidOffsetNumber); InvalidBlockNumber, InvalidOffsetNumber);
/* gistbufferinginserttuples() released the buffer */ /* gistbufferinginserttuples() released the buffer */
} }
else else
@ -680,7 +680,7 @@ gistbufferinginserttuples(GISTBuildState *buildstate, Buffer buffer, int level,
GISTBuildBuffers *gfbb = buildstate->gfbb; GISTBuildBuffers *gfbb = buildstate->gfbb;
List *splitinfo; List *splitinfo;
bool is_split; bool is_split;
BlockNumber placed_to_blk = InvalidBlockNumber; BlockNumber placed_to_blk = InvalidBlockNumber;
is_split = gistplacetopage(buildstate->indexrel, is_split = gistplacetopage(buildstate->indexrel,
buildstate->freespace, buildstate->freespace,

View File

@ -364,8 +364,9 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
item->blkno = ItemPointerGetBlockNumber(&it->t_tid); item->blkno = ItemPointerGetBlockNumber(&it->t_tid);
/* /*
* LSN of current page is lsn of parent page for child. We only * LSN of current page is lsn of parent page for child. We
* have a shared lock, so we need to get the LSN atomically. * only have a shared lock, so we need to get the LSN
* atomically.
*/ */
item->data.parentlsn = BufferGetLSNAtomic(buffer); item->data.parentlsn = BufferGetLSNAtomic(buffer);
} }

View File

@ -414,7 +414,7 @@ gistchoose(Relation r, Page p, IndexTuple it, /* it has compressed entry */
* some inserts to go to other equally-good subtrees. * some inserts to go to other equally-good subtrees.
* *
* keep_current_best is -1 if we haven't yet had to make a random choice * keep_current_best is -1 if we haven't yet had to make a random choice
* whether to keep the current best tuple. If we have done so, and * whether to keep the current best tuple. If we have done so, and
* decided to keep it, keep_current_best is 1; if we've decided to * decided to keep it, keep_current_best is 1; if we've decided to
* replace, keep_current_best is 0. (This state will be reset to -1 as * replace, keep_current_best is 0. (This state will be reset to -1 as
* soon as we've made the replacement, but sometimes we make the choice in * soon as we've made the replacement, but sometimes we make the choice in
@ -810,8 +810,8 @@ gistGetFakeLSN(Relation rel)
if (rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP) if (rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP)
{ {
/* /*
* Temporary relations are only accessible in our session, so a * Temporary relations are only accessible in our session, so a simple
* simple backend-local counter will do. * backend-local counter will do.
*/ */
return counter++; return counter++;
} }

View File

@ -38,7 +38,7 @@ static MemoryContext opCtx; /* working memory for operations */
* follow-right flag, because that change is not included in the full-page * follow-right flag, because that change is not included in the full-page
* image. To be sure that the intermediate state with the wrong flag value is * image. To be sure that the intermediate state with the wrong flag value is
* not visible to concurrent Hot Standby queries, this function handles * not visible to concurrent Hot Standby queries, this function handles
* restoring the full-page image as well as updating the flag. (Note that * restoring the full-page image as well as updating the flag. (Note that
* we never need to do anything else to the child page in the current WAL * we never need to do anything else to the child page in the current WAL
* action.) * action.)
*/ */
@ -89,7 +89,7 @@ gistRedoPageUpdateRecord(XLogRecPtr lsn, XLogRecord *record)
/* /*
* We need to acquire and hold lock on target page while updating the left * We need to acquire and hold lock on target page while updating the left
* child page. If we have a full-page image of target page, getting the * child page. If we have a full-page image of target page, getting the
* lock is a side-effect of restoring that image. Note that even if the * lock is a side-effect of restoring that image. Note that even if the
* target page no longer exists, we'll still attempt to replay the change * target page no longer exists, we'll still attempt to replay the change
* on the child page. * on the child page.

View File

@ -90,7 +90,7 @@ _hash_doinsert(Relation rel, IndexTuple itup)
/* /*
* If the previous iteration of this loop locked what is still the * If the previous iteration of this loop locked what is still the
* correct target bucket, we are done. Otherwise, drop any old lock * correct target bucket, we are done. Otherwise, drop any old lock
* and lock what now appears to be the correct bucket. * and lock what now appears to be the correct bucket.
*/ */
if (retry) if (retry)

View File

@ -210,7 +210,7 @@ _hash_first(IndexScanDesc scan, ScanDirection dir)
/* /*
* If the previous iteration of this loop locked what is still the * If the previous iteration of this loop locked what is still the
* correct target bucket, we are done. Otherwise, drop any old lock * correct target bucket, we are done. Otherwise, drop any old lock
* and lock what now appears to be the correct bucket. * and lock what now appears to be the correct bucket.
*/ */
if (retry) if (retry)

View File

@ -120,32 +120,34 @@ static bool ConditionalMultiXactIdWait(MultiXactId multi,
static const struct static const struct
{ {
LOCKMODE hwlock; LOCKMODE hwlock;
MultiXactStatus lockstatus; MultiXactStatus lockstatus;
MultiXactStatus updstatus; MultiXactStatus updstatus;
} }
tupleLockExtraInfo[MaxLockTupleMode + 1] =
tupleLockExtraInfo[MaxLockTupleMode + 1] =
{ {
{ /* LockTupleKeyShare */ { /* LockTupleKeyShare */
AccessShareLock, AccessShareLock,
MultiXactStatusForKeyShare, MultiXactStatusForKeyShare,
-1 /* KeyShare does not allow updating tuples */ -1 /* KeyShare does not allow updating tuples */
}, },
{ /* LockTupleShare */ { /* LockTupleShare */
RowShareLock, RowShareLock,
MultiXactStatusForShare, MultiXactStatusForShare,
-1 /* Share does not allow updating tuples */ -1 /* Share does not allow updating tuples */
}, },
{ /* LockTupleNoKeyExclusive */ { /* LockTupleNoKeyExclusive */
ExclusiveLock, ExclusiveLock,
MultiXactStatusForNoKeyUpdate, MultiXactStatusForNoKeyUpdate,
MultiXactStatusNoKeyUpdate MultiXactStatusNoKeyUpdate
}, },
{ /* LockTupleExclusive */ { /* LockTupleExclusive */
AccessExclusiveLock, AccessExclusiveLock,
MultiXactStatusForUpdate, MultiXactStatusForUpdate,
MultiXactStatusUpdate MultiXactStatusUpdate
} }
}; };
/* Get the LOCKMODE for a given MultiXactStatus */ /* Get the LOCKMODE for a given MultiXactStatus */
#define LOCKMODE_from_mxstatus(status) \ #define LOCKMODE_from_mxstatus(status) \
(tupleLockExtraInfo[TUPLOCK_from_mxstatus((status))].hwlock) (tupleLockExtraInfo[TUPLOCK_from_mxstatus((status))].hwlock)
@ -168,12 +170,12 @@ tupleLockExtraInfo[MaxLockTupleMode + 1] =
*/ */
static const int MultiXactStatusLock[MaxMultiXactStatus + 1] = static const int MultiXactStatusLock[MaxMultiXactStatus + 1] =
{ {
LockTupleKeyShare, /* ForKeyShare */ LockTupleKeyShare, /* ForKeyShare */
LockTupleShare, /* ForShare */ LockTupleShare, /* ForShare */
LockTupleNoKeyExclusive, /* ForNoKeyUpdate */ LockTupleNoKeyExclusive, /* ForNoKeyUpdate */
LockTupleExclusive, /* ForUpdate */ LockTupleExclusive, /* ForUpdate */
LockTupleNoKeyExclusive, /* NoKeyUpdate */ LockTupleNoKeyExclusive, /* NoKeyUpdate */
LockTupleExclusive /* Update */ LockTupleExclusive /* Update */
}; };
/* Get the LockTupleMode for a given MultiXactStatus */ /* Get the LockTupleMode for a given MultiXactStatus */
@ -365,10 +367,10 @@ heapgetpage(HeapScanDesc scan, BlockNumber page)
* page. That's how index-only scans work fine in hot standby. A crucial * page. That's how index-only scans work fine in hot standby. A crucial
* difference between index-only scans and heap scans is that the * difference between index-only scans and heap scans is that the
* index-only scan completely relies on the visibility map where as heap * index-only scan completely relies on the visibility map where as heap
* scan looks at the page-level PD_ALL_VISIBLE flag. We are not sure if the * scan looks at the page-level PD_ALL_VISIBLE flag. We are not sure if
* page-level flag can be trusted in the same way, because it might get * the page-level flag can be trusted in the same way, because it might
* propagated somehow without being explicitly WAL-logged, e.g. via a full * get propagated somehow without being explicitly WAL-logged, e.g. via a
* page write. Until we can prove that beyond doubt, let's check each * full page write. Until we can prove that beyond doubt, let's check each
* tuple for visibility the hard way. * tuple for visibility the hard way.
*/ */
all_visible = PageIsAllVisible(dp) && !snapshot->takenDuringRecovery; all_visible = PageIsAllVisible(dp) && !snapshot->takenDuringRecovery;
@ -1880,7 +1882,7 @@ heap_get_latest_tid(Relation relation,
* tuple. Check for XMIN match. * tuple. Check for XMIN match.
*/ */
if (TransactionIdIsValid(priorXmax) && if (TransactionIdIsValid(priorXmax) &&
!TransactionIdEquals(priorXmax, HeapTupleHeaderGetXmin(tp.t_data))) !TransactionIdEquals(priorXmax, HeapTupleHeaderGetXmin(tp.t_data)))
{ {
UnlockReleaseBuffer(buffer); UnlockReleaseBuffer(buffer);
break; break;
@ -2488,7 +2490,7 @@ compute_infobits(uint16 infomask, uint16 infomask2)
((infomask & HEAP_XMAX_IS_MULTI) != 0 ? XLHL_XMAX_IS_MULTI : 0) | ((infomask & HEAP_XMAX_IS_MULTI) != 0 ? XLHL_XMAX_IS_MULTI : 0) |
((infomask & HEAP_XMAX_LOCK_ONLY) != 0 ? XLHL_XMAX_LOCK_ONLY : 0) | ((infomask & HEAP_XMAX_LOCK_ONLY) != 0 ? XLHL_XMAX_LOCK_ONLY : 0) |
((infomask & HEAP_XMAX_EXCL_LOCK) != 0 ? XLHL_XMAX_EXCL_LOCK : 0) | ((infomask & HEAP_XMAX_EXCL_LOCK) != 0 ? XLHL_XMAX_EXCL_LOCK : 0) |
/* note we ignore HEAP_XMAX_SHR_LOCK here */ /* note we ignore HEAP_XMAX_SHR_LOCK here */
((infomask & HEAP_XMAX_KEYSHR_LOCK) != 0 ? XLHL_XMAX_KEYSHR_LOCK : 0) | ((infomask & HEAP_XMAX_KEYSHR_LOCK) != 0 ? XLHL_XMAX_KEYSHR_LOCK : 0) |
((infomask2 & HEAP_KEYS_UPDATED) != 0 ? ((infomask2 & HEAP_KEYS_UPDATED) != 0 ?
XLHL_KEYS_UPDATED : 0); XLHL_KEYS_UPDATED : 0);
@ -2730,13 +2732,12 @@ l1:
} }
/* /*
* If this is the first possibly-multixact-able operation in the * If this is the first possibly-multixact-able operation in the current
* current transaction, set my per-backend OldestMemberMXactId setting. * transaction, set my per-backend OldestMemberMXactId setting. We can be
* We can be certain that the transaction will never become a member of * certain that the transaction will never become a member of any older
* any older MultiXactIds than that. (We have to do this even if we * MultiXactIds than that. (We have to do this even if we end up just
* end up just using our own TransactionId below, since some other * using our own TransactionId below, since some other backend could
* backend could incorporate our XID into a MultiXact immediately * incorporate our XID into a MultiXact immediately afterwards.)
* afterwards.)
*/ */
MultiXactIdSetOldestMember(); MultiXactIdSetOldestMember();
@ -2846,7 +2847,7 @@ simple_heap_delete(Relation relation, ItemPointer tid)
result = heap_delete(relation, tid, result = heap_delete(relation, tid,
GetCurrentCommandId(true), InvalidSnapshot, GetCurrentCommandId(true), InvalidSnapshot,
true /* wait for commit */, true /* wait for commit */ ,
&hufd); &hufd);
switch (result) switch (result)
{ {
@ -2936,7 +2937,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
bool checked_lockers; bool checked_lockers;
bool locker_remains; bool locker_remains;
TransactionId xmax_new_tuple, TransactionId xmax_new_tuple,
xmax_old_tuple; xmax_old_tuple;
uint16 infomask_old_tuple, uint16 infomask_old_tuple,
infomask2_old_tuple, infomask2_old_tuple,
infomask_new_tuple, infomask_new_tuple,
@ -3006,13 +3007,13 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
/* /*
* If we're not updating any "key" column, we can grab a weaker lock type. * If we're not updating any "key" column, we can grab a weaker lock type.
* This allows for more concurrency when we are running simultaneously with * This allows for more concurrency when we are running simultaneously
* foreign key checks. * with foreign key checks.
* *
* Note that if a column gets detoasted while executing the update, but the * Note that if a column gets detoasted while executing the update, but
* value ends up being the same, this test will fail and we will use the * the value ends up being the same, this test will fail and we will use
* stronger lock. This is acceptable; the important case to optimize is * the stronger lock. This is acceptable; the important case to optimize
* updates that don't manipulate key columns, not those that * is updates that don't manipulate key columns, not those that
* serendipitiously arrive at the same key values. * serendipitiously arrive at the same key values.
*/ */
HeapSatisfiesHOTandKeyUpdate(relation, hot_attrs, key_attrs, HeapSatisfiesHOTandKeyUpdate(relation, hot_attrs, key_attrs,
@ -3026,12 +3027,12 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
/* /*
* If this is the first possibly-multixact-able operation in the * If this is the first possibly-multixact-able operation in the
* current transaction, set my per-backend OldestMemberMXactId setting. * current transaction, set my per-backend OldestMemberMXactId
* We can be certain that the transaction will never become a member of * setting. We can be certain that the transaction will never become a
* any older MultiXactIds than that. (We have to do this even if we * member of any older MultiXactIds than that. (We have to do this
* end up just using our own TransactionId below, since some other * even if we end up just using our own TransactionId below, since
* backend could incorporate our XID into a MultiXact immediately * some other backend could incorporate our XID into a MultiXact
* afterwards.) * immediately afterwards.)
*/ */
MultiXactIdSetOldestMember(); MultiXactIdSetOldestMember();
} }
@ -3064,7 +3065,7 @@ l2:
} }
else if (result == HeapTupleBeingUpdated && wait) else if (result == HeapTupleBeingUpdated && wait)
{ {
TransactionId xwait; TransactionId xwait;
uint16 infomask; uint16 infomask;
bool can_continue = false; bool can_continue = false;
@ -3073,13 +3074,14 @@ l2:
/* /*
* XXX note that we don't consider the "no wait" case here. This * XXX note that we don't consider the "no wait" case here. This
* isn't a problem currently because no caller uses that case, but it * isn't a problem currently because no caller uses that case, but it
* should be fixed if such a caller is introduced. It wasn't a problem * should be fixed if such a caller is introduced. It wasn't a
* previously because this code would always wait, but now that some * problem previously because this code would always wait, but now
* tuple locks do not conflict with one of the lock modes we use, it is * that some tuple locks do not conflict with one of the lock modes we
* possible that this case is interesting to handle specially. * use, it is possible that this case is interesting to handle
* specially.
* *
* This may cause failures with third-party code that calls heap_update * This may cause failures with third-party code that calls
* directly. * heap_update directly.
*/ */
/* must copy state data before unlocking buffer */ /* must copy state data before unlocking buffer */
@ -3109,15 +3111,15 @@ l2:
* gone (or even not sleep at all in some cases); we need to preserve * gone (or even not sleep at all in some cases); we need to preserve
* it as locker, unless it is gone completely. * it as locker, unless it is gone completely.
* *
* If it's not a multi, we need to check for sleeping conditions before * If it's not a multi, we need to check for sleeping conditions
* actually going to sleep. If the update doesn't conflict with the * before actually going to sleep. If the update doesn't conflict
* locks, we just continue without sleeping (but making sure it is * with the locks, we just continue without sleeping (but making sure
* preserved). * it is preserved).
*/ */
if (infomask & HEAP_XMAX_IS_MULTI) if (infomask & HEAP_XMAX_IS_MULTI)
{ {
TransactionId update_xact; TransactionId update_xact;
int remain; int remain;
/* wait for multixact */ /* wait for multixact */
MultiXactIdWait((MultiXactId) xwait, mxact_status, &remain, MultiXactIdWait((MultiXactId) xwait, mxact_status, &remain,
@ -3135,18 +3137,18 @@ l2:
goto l2; goto l2;
/* /*
* Note that the multixact may not be done by now. It could have * Note that the multixact may not be done by now. It could have
* surviving members; our own xact or other subxacts of this * surviving members; our own xact or other subxacts of this
* backend, and also any other concurrent transaction that locked * backend, and also any other concurrent transaction that locked
* the tuple with KeyShare if we only got TupleLockUpdate. If this * the tuple with KeyShare if we only got TupleLockUpdate. If
* is the case, we have to be careful to mark the updated tuple * this is the case, we have to be careful to mark the updated
* with the surviving members in Xmax. * tuple with the surviving members in Xmax.
* *
* Note that there could have been another update in the MultiXact. * Note that there could have been another update in the
* In that case, we need to check whether it committed or aborted. * MultiXact. In that case, we need to check whether it committed
* If it aborted we are safe to update it again; otherwise there is * or aborted. If it aborted we are safe to update it again;
* an update conflict, and we have to return HeapTupleUpdated * otherwise there is an update conflict, and we have to return
* below. * HeapTupleUpdated below.
* *
* In the LockTupleExclusive case, we still need to preserve the * In the LockTupleExclusive case, we still need to preserve the
* surviving members: those would include the tuple locks we had * surviving members: those would include the tuple locks we had
@ -3167,21 +3169,21 @@ l2:
else else
{ {
/* /*
* If it's just a key-share locker, and we're not changing the * If it's just a key-share locker, and we're not changing the key
* key columns, we don't need to wait for it to end; but we * columns, we don't need to wait for it to end; but we need to
* need to preserve it as locker. * preserve it as locker.
*/ */
if (HEAP_XMAX_IS_KEYSHR_LOCKED(infomask) && key_intact) if (HEAP_XMAX_IS_KEYSHR_LOCKED(infomask) && key_intact)
{ {
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE); LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
/* /*
* recheck the locker; if someone else changed the tuple while we * recheck the locker; if someone else changed the tuple while
* weren't looking, start over. * we weren't looking, start over.
*/ */
if ((oldtup.t_data->t_infomask & HEAP_XMAX_IS_MULTI) || if ((oldtup.t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
!TransactionIdEquals(HeapTupleHeaderGetRawXmax(oldtup.t_data), !TransactionIdEquals(HeapTupleHeaderGetRawXmax(oldtup.t_data),
xwait)) xwait))
goto l2; goto l2;
can_continue = true; can_continue = true;
@ -3194,13 +3196,13 @@ l2:
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE); LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
/* /*
* xwait is done, but if xwait had just locked the tuple then some * xwait is done, but if xwait had just locked the tuple then
* other xact could update this tuple before we get to this point. * some other xact could update this tuple before we get to
* Check for xmax change, and start over if so. * this point. Check for xmax change, and start over if so.
*/ */
if ((oldtup.t_data->t_infomask & HEAP_XMAX_IS_MULTI) || if ((oldtup.t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
!TransactionIdEquals(HeapTupleHeaderGetRawXmax(oldtup.t_data), !TransactionIdEquals(HeapTupleHeaderGetRawXmax(oldtup.t_data),
xwait)) xwait))
goto l2; goto l2;
/* Otherwise check if it committed or aborted */ /* Otherwise check if it committed or aborted */
@ -3247,8 +3249,8 @@ l2:
* visible while we were busy locking the buffer, or during some * visible while we were busy locking the buffer, or during some
* subsequent window during which we had it unlocked, we'll have to unlock * subsequent window during which we had it unlocked, we'll have to unlock
* and re-lock, to avoid holding the buffer lock across an I/O. That's a * and re-lock, to avoid holding the buffer lock across an I/O. That's a
* bit unfortunate, especially since we'll now have to recheck whether * bit unfortunate, especially since we'll now have to recheck whether the
* the tuple has been locked or updated under us, but hopefully it won't * tuple has been locked or updated under us, but hopefully it won't
* happen very often. * happen very often.
*/ */
if (vmbuffer == InvalidBuffer && PageIsAllVisible(page)) if (vmbuffer == InvalidBuffer && PageIsAllVisible(page))
@ -3656,9 +3658,9 @@ heap_tuple_attr_equals(TupleDesc tupdesc, int attrnum,
/* /*
* Extract the corresponding values. XXX this is pretty inefficient if * Extract the corresponding values. XXX this is pretty inefficient if
* there are many indexed columns. Should HeapSatisfiesHOTandKeyUpdate do a * there are many indexed columns. Should HeapSatisfiesHOTandKeyUpdate do
* single heap_deform_tuple call on each tuple, instead? But that doesn't * a single heap_deform_tuple call on each tuple, instead? But that
* work for system columns ... * doesn't work for system columns ...
*/ */
value1 = heap_getattr(tup1, attrnum, tupdesc, &isnull1); value1 = heap_getattr(tup1, attrnum, tupdesc, &isnull1);
value2 = heap_getattr(tup2, attrnum, tupdesc, &isnull2); value2 = heap_getattr(tup2, attrnum, tupdesc, &isnull2);
@ -3720,12 +3722,12 @@ HeapSatisfiesHOTandKeyUpdate(Relation relation,
bool *satisfies_hot, bool *satisfies_key, bool *satisfies_hot, bool *satisfies_key,
HeapTuple oldtup, HeapTuple newtup) HeapTuple oldtup, HeapTuple newtup)
{ {
int next_hot_attnum; int next_hot_attnum;
int next_key_attnum; int next_key_attnum;
bool hot_result = true; bool hot_result = true;
bool key_result = true; bool key_result = true;
bool key_done = false; bool key_done = false;
bool hot_done = false; bool hot_done = false;
next_hot_attnum = bms_first_member(hot_attrs); next_hot_attnum = bms_first_member(hot_attrs);
if (next_hot_attnum == -1) if (next_hot_attnum == -1)
@ -3743,8 +3745,8 @@ HeapSatisfiesHOTandKeyUpdate(Relation relation,
for (;;) for (;;)
{ {
int check_now; int check_now;
bool changed; bool changed;
/* both bitmapsets are now empty */ /* both bitmapsets are now empty */
if (key_done && hot_done) if (key_done && hot_done)
@ -3813,7 +3815,7 @@ simple_heap_update(Relation relation, ItemPointer otid, HeapTuple tup)
result = heap_update(relation, otid, tup, result = heap_update(relation, otid, tup,
GetCurrentCommandId(true), InvalidSnapshot, GetCurrentCommandId(true), InvalidSnapshot,
true /* wait for commit */, true /* wait for commit */ ,
&hufd, &lockmode); &hufd, &lockmode);
switch (result) switch (result)
{ {
@ -3843,7 +3845,7 @@ simple_heap_update(Relation relation, ItemPointer otid, HeapTuple tup)
static MultiXactStatus static MultiXactStatus
get_mxact_status_for_lock(LockTupleMode mode, bool is_update) get_mxact_status_for_lock(LockTupleMode mode, bool is_update)
{ {
MultiXactStatus retval; MultiXactStatus retval;
if (is_update) if (is_update)
retval = tupleLockExtraInfo[mode].updstatus; retval = tupleLockExtraInfo[mode].updstatus;
@ -3933,7 +3935,7 @@ l3:
uint16 infomask; uint16 infomask;
uint16 infomask2; uint16 infomask2;
bool require_sleep; bool require_sleep;
ItemPointerData t_ctid; ItemPointerData t_ctid;
/* must copy state data before unlocking buffer */ /* must copy state data before unlocking buffer */
xwait = HeapTupleHeaderGetRawXmax(tuple->t_data); xwait = HeapTupleHeaderGetRawXmax(tuple->t_data);
@ -3944,22 +3946,22 @@ l3:
LockBuffer(*buffer, BUFFER_LOCK_UNLOCK); LockBuffer(*buffer, BUFFER_LOCK_UNLOCK);
/* /*
* If any subtransaction of the current top transaction already holds a * If any subtransaction of the current top transaction already holds
* lock as strong or stronger than what we're requesting, we * a lock as strong or stronger than what we're requesting, we
* effectively hold the desired lock already. We *must* succeed * effectively hold the desired lock already. We *must* succeed
* without trying to take the tuple lock, else we will deadlock against * without trying to take the tuple lock, else we will deadlock
* anyone wanting to acquire a stronger lock. * against anyone wanting to acquire a stronger lock.
*/ */
if (infomask & HEAP_XMAX_IS_MULTI) if (infomask & HEAP_XMAX_IS_MULTI)
{ {
int i; int i;
int nmembers; int nmembers;
MultiXactMember *members; MultiXactMember *members;
/* /*
* We don't need to allow old multixacts here; if that had been the * We don't need to allow old multixacts here; if that had been
* case, HeapTupleSatisfiesUpdate would have returned MayBeUpdated * the case, HeapTupleSatisfiesUpdate would have returned
* and we wouldn't be here. * MayBeUpdated and we wouldn't be here.
*/ */
nmembers = GetMultiXactIdMembers(xwait, &members, false); nmembers = GetMultiXactIdMembers(xwait, &members, false);
@ -3967,7 +3969,7 @@ l3:
{ {
if (TransactionIdIsCurrentTransactionId(members[i].xid)) if (TransactionIdIsCurrentTransactionId(members[i].xid))
{ {
LockTupleMode membermode; LockTupleMode membermode;
membermode = TUPLOCK_from_mxstatus(members[i].status); membermode = TUPLOCK_from_mxstatus(members[i].status);
@ -4001,8 +4003,8 @@ l3:
if (!ConditionalLockTupleTuplock(relation, tid, mode)) if (!ConditionalLockTupleTuplock(relation, tid, mode))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_LOCK_NOT_AVAILABLE), (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
errmsg("could not obtain lock on row in relation \"%s\"", errmsg("could not obtain lock on row in relation \"%s\"",
RelationGetRelationName(relation)))); RelationGetRelationName(relation))));
} }
else else
LockTupleTuplock(relation, tid, mode); LockTupleTuplock(relation, tid, mode);
@ -4023,34 +4025,34 @@ l3:
* continue if the key hasn't been modified. * continue if the key hasn't been modified.
* *
* However, if there are updates, we need to walk the update chain * However, if there are updates, we need to walk the update chain
* to mark future versions of the row as locked, too. That way, if * to mark future versions of the row as locked, too. That way,
* somebody deletes that future version, we're protected against * if somebody deletes that future version, we're protected
* the key going away. This locking of future versions could block * against the key going away. This locking of future versions
* momentarily, if a concurrent transaction is deleting a key; or * could block momentarily, if a concurrent transaction is
* it could return a value to the effect that the transaction * deleting a key; or it could return a value to the effect that
* deleting the key has already committed. So we do this before * the transaction deleting the key has already committed. So we
* re-locking the buffer; otherwise this would be prone to * do this before re-locking the buffer; otherwise this would be
* deadlocks. * prone to deadlocks.
* *
* Note that the TID we're locking was grabbed before we unlocked * Note that the TID we're locking was grabbed before we unlocked
* the buffer. For it to change while we're not looking, the other * the buffer. For it to change while we're not looking, the
* properties we're testing for below after re-locking the buffer * other properties we're testing for below after re-locking the
* would also change, in which case we would restart this loop * buffer would also change, in which case we would restart this
* above. * loop above.
*/ */
if (!(infomask2 & HEAP_KEYS_UPDATED)) if (!(infomask2 & HEAP_KEYS_UPDATED))
{ {
bool updated; bool updated;
updated = !HEAP_XMAX_IS_LOCKED_ONLY(infomask); updated = !HEAP_XMAX_IS_LOCKED_ONLY(infomask);
/* /*
* If there are updates, follow the update chain; bail out * If there are updates, follow the update chain; bail out if
* if that cannot be done. * that cannot be done.
*/ */
if (follow_updates && updated) if (follow_updates && updated)
{ {
HTSU_Result res; HTSU_Result res;
res = heap_lock_updated_tuple(relation, tuple, &t_ctid, res = heap_lock_updated_tuple(relation, tuple, &t_ctid,
GetCurrentTransactionId(), GetCurrentTransactionId(),
@ -4069,8 +4071,9 @@ l3:
/* /*
* Make sure it's still an appropriate lock, else start over. * Make sure it's still an appropriate lock, else start over.
* Also, if it wasn't updated before we released the lock, but * Also, if it wasn't updated before we released the lock, but
* is updated now, we start over too; the reason is that we now * is updated now, we start over too; the reason is that we
* need to follow the update chain to lock the new versions. * now need to follow the update chain to lock the new
* versions.
*/ */
if (!HeapTupleHeaderIsOnlyLocked(tuple->t_data) && if (!HeapTupleHeaderIsOnlyLocked(tuple->t_data) &&
((tuple->t_data->t_infomask2 & HEAP_KEYS_UPDATED) || ((tuple->t_data->t_infomask2 & HEAP_KEYS_UPDATED) ||
@ -4114,20 +4117,20 @@ l3:
{ {
/* /*
* If we're requesting NoKeyExclusive, we might also be able to * If we're requesting NoKeyExclusive, we might also be able to
* avoid sleeping; just ensure that there's no other lock type than * avoid sleeping; just ensure that there's no other lock type
* KeyShare. Note that this is a bit more involved than just * than KeyShare. Note that this is a bit more involved than just
* checking hint bits -- we need to expand the multixact to figure * checking hint bits -- we need to expand the multixact to figure
* out lock modes for each one (unless there was only one such * out lock modes for each one (unless there was only one such
* locker). * locker).
*/ */
if (infomask & HEAP_XMAX_IS_MULTI) if (infomask & HEAP_XMAX_IS_MULTI)
{ {
int nmembers; int nmembers;
MultiXactMember *members; MultiXactMember *members;
/* /*
* We don't need to allow old multixacts here; if that had been * We don't need to allow old multixacts here; if that had
* the case, HeapTupleSatisfiesUpdate would have returned * been the case, HeapTupleSatisfiesUpdate would have returned
* MayBeUpdated and we wouldn't be here. * MayBeUpdated and we wouldn't be here.
*/ */
nmembers = GetMultiXactIdMembers(xwait, &members, false); nmembers = GetMultiXactIdMembers(xwait, &members, false);
@ -4135,15 +4138,15 @@ l3:
if (nmembers <= 0) if (nmembers <= 0)
{ {
/* /*
* No need to keep the previous xmax here. This is unlikely * No need to keep the previous xmax here. This is
* to happen. * unlikely to happen.
*/ */
require_sleep = false; require_sleep = false;
} }
else else
{ {
int i; int i;
bool allowed = true; bool allowed = true;
for (i = 0; i < nmembers; i++) for (i = 0; i < nmembers; i++)
{ {
@ -4180,8 +4183,8 @@ l3:
/* if the xmax changed in the meantime, start over */ /* if the xmax changed in the meantime, start over */
if ((tuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI) || if ((tuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
!TransactionIdEquals(HeapTupleHeaderGetRawXmax(tuple->t_data), !TransactionIdEquals(HeapTupleHeaderGetRawXmax(tuple->t_data),
xwait)) xwait))
goto l3; goto l3;
/* otherwise, we're good */ /* otherwise, we're good */
require_sleep = false; require_sleep = false;
@ -4221,7 +4224,7 @@ l3:
if (follow_updates && if (follow_updates &&
!HEAP_XMAX_IS_LOCKED_ONLY(infomask)) !HEAP_XMAX_IS_LOCKED_ONLY(infomask))
{ {
HTSU_Result res; HTSU_Result res;
res = heap_lock_updated_tuple(relation, tuple, &t_ctid, res = heap_lock_updated_tuple(relation, tuple, &t_ctid,
GetCurrentTransactionId(), GetCurrentTransactionId(),
@ -4243,15 +4246,15 @@ l3:
* for xmax change, and start over if so. * for xmax change, and start over if so.
*/ */
if (!(tuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI) || if (!(tuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
!TransactionIdEquals(HeapTupleHeaderGetRawXmax(tuple->t_data), !TransactionIdEquals(HeapTupleHeaderGetRawXmax(tuple->t_data),
xwait)) xwait))
goto l3; goto l3;
/* /*
* Of course, the multixact might not be done here: if we're * Of course, the multixact might not be done here: if we're
* requesting a light lock mode, other transactions with light * requesting a light lock mode, other transactions with light
* locks could still be alive, as well as locks owned by our * locks could still be alive, as well as locks owned by our
* own xact or other subxacts of this backend. We need to * own xact or other subxacts of this backend. We need to
* preserve the surviving MultiXact members. Note that it * preserve the surviving MultiXact members. Note that it
* isn't absolutely necessary in the latter case, but doing so * isn't absolutely necessary in the latter case, but doing so
* is simpler. * is simpler.
@ -4275,7 +4278,7 @@ l3:
if (follow_updates && if (follow_updates &&
!HEAP_XMAX_IS_LOCKED_ONLY(infomask)) !HEAP_XMAX_IS_LOCKED_ONLY(infomask))
{ {
HTSU_Result res; HTSU_Result res;
res = heap_lock_updated_tuple(relation, tuple, &t_ctid, res = heap_lock_updated_tuple(relation, tuple, &t_ctid,
GetCurrentTransactionId(), GetCurrentTransactionId(),
@ -4294,15 +4297,15 @@ l3:
/* /*
* xwait is done, but if xwait had just locked the tuple then * xwait is done, but if xwait had just locked the tuple then
* some other xact could update this tuple before we get to * some other xact could update this tuple before we get to
* this point. Check for xmax change, and start over if so. * this point. Check for xmax change, and start over if so.
*/ */
if ((tuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI) || if ((tuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
!TransactionIdEquals(HeapTupleHeaderGetRawXmax(tuple->t_data), !TransactionIdEquals(HeapTupleHeaderGetRawXmax(tuple->t_data),
xwait)) xwait))
goto l3; goto l3;
/* /*
* Otherwise check if it committed or aborted. Note we cannot * Otherwise check if it committed or aborted. Note we cannot
* be here if the tuple was only locked by somebody who didn't * be here if the tuple was only locked by somebody who didn't
* conflict with us; that should have been handled above. So * conflict with us; that should have been handled above. So
* that transaction must necessarily be gone by now. * that transaction must necessarily be gone by now.
@ -4355,8 +4358,8 @@ failed:
* for cases where it is a plain TransactionId. * for cases where it is a plain TransactionId.
* *
* Note in particular that this covers the case where we already hold * Note in particular that this covers the case where we already hold
* exclusive lock on the tuple and the caller only wants key share or share * exclusive lock on the tuple and the caller only wants key share or
* lock. It would certainly not do to give up the exclusive lock. * share lock. It would certainly not do to give up the exclusive lock.
*/ */
if (!(old_infomask & (HEAP_XMAX_INVALID | if (!(old_infomask & (HEAP_XMAX_INVALID |
HEAP_XMAX_COMMITTED | HEAP_XMAX_COMMITTED |
@ -4379,13 +4382,12 @@ failed:
} }
/* /*
* If this is the first possibly-multixact-able operation in the * If this is the first possibly-multixact-able operation in the current
* current transaction, set my per-backend OldestMemberMXactId setting. * transaction, set my per-backend OldestMemberMXactId setting. We can be
* We can be certain that the transaction will never become a member of * certain that the transaction will never become a member of any older
* any older MultiXactIds than that. (We have to do this even if we * MultiXactIds than that. (We have to do this even if we end up just
* end up just using our own TransactionId below, since some other * using our own TransactionId below, since some other backend could
* backend could incorporate our XID into a MultiXact immediately * incorporate our XID into a MultiXact immediately afterwards.)
* afterwards.)
*/ */
MultiXactIdSetOldestMember(); MultiXactIdSetOldestMember();
@ -4419,11 +4421,11 @@ failed:
HeapTupleHeaderSetXmax(tuple->t_data, xid); HeapTupleHeaderSetXmax(tuple->t_data, xid);
/* /*
* Make sure there is no forward chain link in t_ctid. Note that in the * Make sure there is no forward chain link in t_ctid. Note that in the
* cases where the tuple has been updated, we must not overwrite t_ctid, * cases where the tuple has been updated, we must not overwrite t_ctid,
* because it was set by the updater. Moreover, if the tuple has been * because it was set by the updater. Moreover, if the tuple has been
* updated, we need to follow the update chain to lock the new versions * updated, we need to follow the update chain to lock the new versions of
* of the tuple as well. * the tuple as well.
*/ */
if (HEAP_XMAX_IS_LOCKED_ONLY(new_infomask)) if (HEAP_XMAX_IS_LOCKED_ONLY(new_infomask))
tuple->t_data->t_ctid = *tid; tuple->t_data->t_ctid = *tid;
@ -4514,9 +4516,9 @@ compute_new_xmax_infomask(TransactionId xmax, uint16 old_infomask,
TransactionId *result_xmax, uint16 *result_infomask, TransactionId *result_xmax, uint16 *result_infomask,
uint16 *result_infomask2) uint16 *result_infomask2)
{ {
TransactionId new_xmax; TransactionId new_xmax;
uint16 new_infomask, uint16 new_infomask,
new_infomask2; new_infomask2;
l5: l5:
new_infomask = 0; new_infomask = 0;
@ -4562,11 +4564,11 @@ l5:
} }
else if (old_infomask & HEAP_XMAX_IS_MULTI) else if (old_infomask & HEAP_XMAX_IS_MULTI)
{ {
MultiXactStatus new_status; MultiXactStatus new_status;
/* /*
* Currently we don't allow XMAX_COMMITTED to be set for multis, * Currently we don't allow XMAX_COMMITTED to be set for multis, so
* so cross-check. * cross-check.
*/ */
Assert(!(old_infomask & HEAP_XMAX_COMMITTED)); Assert(!(old_infomask & HEAP_XMAX_COMMITTED));
@ -4587,10 +4589,11 @@ l5:
/* /*
* If the XMAX is already a MultiXactId, then we need to expand it to * If the XMAX is already a MultiXactId, then we need to expand it to
* include add_to_xmax; but if all the members were lockers and are all * include add_to_xmax; but if all the members were lockers and are
* gone, we can do away with the IS_MULTI bit and just set add_to_xmax * all gone, we can do away with the IS_MULTI bit and just set
* as the only locker/updater. If all lockers are gone and we have an * add_to_xmax as the only locker/updater. If all lockers are gone
* updater that aborted, we can also do without a multi. * and we have an updater that aborted, we can also do without a
* multi.
* *
* The cost of doing GetMultiXactIdMembers would be paid by * The cost of doing GetMultiXactIdMembers would be paid by
* MultiXactIdExpand if we weren't to do this, so this check is not * MultiXactIdExpand if we weren't to do this, so this check is not
@ -4624,8 +4627,8 @@ l5:
* It's a committed update, so we need to preserve him as updater of * It's a committed update, so we need to preserve him as updater of
* the tuple. * the tuple.
*/ */
MultiXactStatus status; MultiXactStatus status;
MultiXactStatus new_status; MultiXactStatus new_status;
if (old_infomask2 & HEAP_KEYS_UPDATED) if (old_infomask2 & HEAP_KEYS_UPDATED)
status = MultiXactStatusUpdate; status = MultiXactStatusUpdate;
@ -4633,6 +4636,7 @@ l5:
status = MultiXactStatusNoKeyUpdate; status = MultiXactStatusNoKeyUpdate;
new_status = get_mxact_status_for_lock(mode, is_update); new_status = get_mxact_status_for_lock(mode, is_update);
/* /*
* since it's not running, it's obviously impossible for the old * since it's not running, it's obviously impossible for the old
* updater to be identical to the current one, so we need not check * updater to be identical to the current one, so we need not check
@ -4648,8 +4652,8 @@ l5:
* create a new MultiXactId that includes both the old locker or * create a new MultiXactId that includes both the old locker or
* updater and our own TransactionId. * updater and our own TransactionId.
*/ */
MultiXactStatus status; MultiXactStatus status;
MultiXactStatus new_status; MultiXactStatus new_status;
if (HEAP_XMAX_IS_LOCKED_ONLY(old_infomask)) if (HEAP_XMAX_IS_LOCKED_ONLY(old_infomask))
{ {
@ -4668,8 +4672,8 @@ l5:
{ {
/* /*
* LOCK_ONLY can be present alone only when a page has been * LOCK_ONLY can be present alone only when a page has been
* upgraded by pg_upgrade. But in that case, * upgraded by pg_upgrade. But in that case,
* TransactionIdIsInProgress() should have returned false. We * TransactionIdIsInProgress() should have returned false. We
* assume it's no longer locked in this case. * assume it's no longer locked in this case.
*/ */
elog(WARNING, "LOCK_ONLY found for Xid in progress %u", xmax); elog(WARNING, "LOCK_ONLY found for Xid in progress %u", xmax);
@ -4696,8 +4700,8 @@ l5:
*/ */
if (xmax == add_to_xmax) if (xmax == add_to_xmax)
{ {
LockTupleMode old_mode = TUPLOCK_from_mxstatus(status); LockTupleMode old_mode = TUPLOCK_from_mxstatus(status);
bool old_isupd = ISUPDATE_from_mxstatus(status); bool old_isupd = ISUPDATE_from_mxstatus(status);
/* /*
* We can do this if the new LockTupleMode is higher or equal than * We can do this if the new LockTupleMode is higher or equal than
@ -4728,8 +4732,8 @@ l5:
* It's a committed update, so we gotta preserve him as updater of the * It's a committed update, so we gotta preserve him as updater of the
* tuple. * tuple.
*/ */
MultiXactStatus status; MultiXactStatus status;
MultiXactStatus new_status; MultiXactStatus new_status;
if (old_infomask2 & HEAP_KEYS_UPDATED) if (old_infomask2 & HEAP_KEYS_UPDATED)
status = MultiXactStatusUpdate; status = MultiXactStatusUpdate;
@ -4737,6 +4741,7 @@ l5:
status = MultiXactStatusNoKeyUpdate; status = MultiXactStatusNoKeyUpdate;
new_status = get_mxact_status_for_lock(mode, is_update); new_status = get_mxact_status_for_lock(mode, is_update);
/* /*
* since it's not running, it's obviously impossible for the old * since it's not running, it's obviously impossible for the old
* updater to be identical to the current one, so we need not check * updater to be identical to the current one, so we need not check
@ -4774,14 +4779,14 @@ static HTSU_Result
heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid, heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid,
LockTupleMode mode) LockTupleMode mode)
{ {
ItemPointerData tupid; ItemPointerData tupid;
HeapTupleData mytup; HeapTupleData mytup;
Buffer buf; Buffer buf;
uint16 new_infomask, uint16 new_infomask,
new_infomask2, new_infomask2,
old_infomask; old_infomask;
TransactionId xmax, TransactionId xmax,
new_xmax; new_xmax;
ItemPointerCopy(tid, &tupid); ItemPointerCopy(tid, &tupid);
@ -4802,16 +4807,17 @@ l4:
xmax = HeapTupleHeaderGetRawXmax(mytup.t_data); xmax = HeapTupleHeaderGetRawXmax(mytup.t_data);
/* /*
* If this tuple is updated and the key has been modified (or deleted), * If this tuple is updated and the key has been modified (or
* what we do depends on the status of the updating transaction: if * deleted), what we do depends on the status of the updating
* it's live, we sleep until it finishes; if it has committed, we have * transaction: if it's live, we sleep until it finishes; if it has
* to fail (i.e. return HeapTupleUpdated); if it aborted, we ignore it. * committed, we have to fail (i.e. return HeapTupleUpdated); if it
* For updates that didn't touch the key, we can just plough ahead. * aborted, we ignore it. For updates that didn't touch the key, we
* can just plough ahead.
*/ */
if (!(old_infomask & HEAP_XMAX_INVALID) && if (!(old_infomask & HEAP_XMAX_INVALID) &&
(mytup.t_data->t_infomask2 & HEAP_KEYS_UPDATED)) (mytup.t_data->t_infomask2 & HEAP_KEYS_UPDATED))
{ {
TransactionId update_xid; TransactionId update_xid;
/* /*
* Note: we *must* check TransactionIdIsInProgress before * Note: we *must* check TransactionIdIsInProgress before
@ -4832,7 +4838,7 @@ l4:
goto l4; goto l4;
} }
else if (TransactionIdDidAbort(update_xid)) else if (TransactionIdDidAbort(update_xid))
; /* okay to proceed */ ; /* okay to proceed */
else if (TransactionIdDidCommit(update_xid)) else if (TransactionIdDidCommit(update_xid))
{ {
UnlockReleaseBuffer(buf); UnlockReleaseBuffer(buf);
@ -4861,7 +4867,7 @@ l4:
{ {
xl_heap_lock_updated xlrec; xl_heap_lock_updated xlrec;
XLogRecPtr recptr; XLogRecPtr recptr;
XLogRecData rdata[2]; XLogRecData rdata[2];
Page page = BufferGetPage(buf); Page page = BufferGetPage(buf);
xlrec.target.node = rel->rd_node; xlrec.target.node = rel->rd_node;
@ -4889,7 +4895,7 @@ l4:
/* if we find the end of update chain, we're done. */ /* if we find the end of update chain, we're done. */
if (mytup.t_data->t_infomask & HEAP_XMAX_INVALID || if (mytup.t_data->t_infomask & HEAP_XMAX_INVALID ||
ItemPointerEquals(&mytup.t_self, &mytup.t_data->t_ctid) || ItemPointerEquals(&mytup.t_self, &mytup.t_data->t_ctid) ||
HeapTupleHeaderIsOnlyLocked(mytup.t_data)) HeapTupleHeaderIsOnlyLocked(mytup.t_data))
{ {
UnlockReleaseBuffer(buf); UnlockReleaseBuffer(buf);
@ -4904,13 +4910,13 @@ l4:
/* /*
* heap_lock_updated_tuple * heap_lock_updated_tuple
* Follow update chain when locking an updated tuple, acquiring locks (row * Follow update chain when locking an updated tuple, acquiring locks (row
* marks) on the updated versions. * marks) on the updated versions.
* *
* The initial tuple is assumed to be already locked. * The initial tuple is assumed to be already locked.
* *
* This function doesn't check visibility, it just inconditionally marks the * This function doesn't check visibility, it just inconditionally marks the
* tuple(s) as locked. If any tuple in the updated chain is being deleted * tuple(s) as locked. If any tuple in the updated chain is being deleted
* concurrently (or updated with the key being modified), sleep until the * concurrently (or updated with the key being modified), sleep until the
* transaction doing it is finished. * transaction doing it is finished.
* *
@ -4932,12 +4938,12 @@ heap_lock_updated_tuple(Relation rel, HeapTuple tuple, ItemPointer ctid,
{ {
/* /*
* If this is the first possibly-multixact-able operation in the * If this is the first possibly-multixact-able operation in the
* current transaction, set my per-backend OldestMemberMXactId setting. * current transaction, set my per-backend OldestMemberMXactId
* We can be certain that the transaction will never become a member of * setting. We can be certain that the transaction will never become a
* any older MultiXactIds than that. (We have to do this even if we * member of any older MultiXactIds than that. (We have to do this
* end up just using our own TransactionId below, since some other * even if we end up just using our own TransactionId below, since
* backend could incorporate our XID into a MultiXact immediately * some other backend could incorporate our XID into a MultiXact
* afterwards.) * immediately afterwards.)
*/ */
MultiXactIdSetOldestMember(); MultiXactIdSetOldestMember();
@ -5117,9 +5123,9 @@ heap_freeze_tuple(HeapTupleHeader tuple, TransactionId cutoff_xid,
HeapTupleHeaderSetXmax(tuple, InvalidTransactionId); HeapTupleHeaderSetXmax(tuple, InvalidTransactionId);
/* /*
* The tuple might be marked either XMAX_INVALID or XMAX_COMMITTED * The tuple might be marked either XMAX_INVALID or XMAX_COMMITTED +
* + LOCKED. Normalize to INVALID just to be sure no one gets * LOCKED. Normalize to INVALID just to be sure no one gets confused.
* confused. Also get rid of the HEAP_KEYS_UPDATED bit. * Also get rid of the HEAP_KEYS_UPDATED bit.
*/ */
tuple->t_infomask &= ~HEAP_XMAX_BITS; tuple->t_infomask &= ~HEAP_XMAX_BITS;
tuple->t_infomask |= HEAP_XMAX_INVALID; tuple->t_infomask |= HEAP_XMAX_INVALID;
@ -5172,13 +5178,13 @@ static void
GetMultiXactIdHintBits(MultiXactId multi, uint16 *new_infomask, GetMultiXactIdHintBits(MultiXactId multi, uint16 *new_infomask,
uint16 *new_infomask2) uint16 *new_infomask2)
{ {
int nmembers; int nmembers;
MultiXactMember *members; MultiXactMember *members;
int i; int i;
uint16 bits = HEAP_XMAX_IS_MULTI; uint16 bits = HEAP_XMAX_IS_MULTI;
uint16 bits2 = 0; uint16 bits2 = 0;
bool has_update = false; bool has_update = false;
LockTupleMode strongest = LockTupleKeyShare; LockTupleMode strongest = LockTupleKeyShare;
/* /*
* We only use this in multis we just created, so they cannot be values * We only use this in multis we just created, so they cannot be values
@ -5188,7 +5194,7 @@ GetMultiXactIdHintBits(MultiXactId multi, uint16 *new_infomask,
for (i = 0; i < nmembers; i++) for (i = 0; i < nmembers; i++)
{ {
LockTupleMode mode; LockTupleMode mode;
/* /*
* Remember the strongest lock mode held by any member of the * Remember the strongest lock mode held by any member of the
@ -5249,22 +5255,22 @@ GetMultiXactIdHintBits(MultiXactId multi, uint16 *new_infomask,
static TransactionId static TransactionId
MultiXactIdGetUpdateXid(TransactionId xmax, uint16 t_infomask) MultiXactIdGetUpdateXid(TransactionId xmax, uint16 t_infomask)
{ {
TransactionId update_xact = InvalidTransactionId; TransactionId update_xact = InvalidTransactionId;
MultiXactMember *members; MultiXactMember *members;
int nmembers; int nmembers;
Assert(!(t_infomask & HEAP_XMAX_LOCK_ONLY)); Assert(!(t_infomask & HEAP_XMAX_LOCK_ONLY));
Assert(t_infomask & HEAP_XMAX_IS_MULTI); Assert(t_infomask & HEAP_XMAX_IS_MULTI);
/* /*
* Since we know the LOCK_ONLY bit is not set, this cannot be a * Since we know the LOCK_ONLY bit is not set, this cannot be a multi from
* multi from pre-pg_upgrade. * pre-pg_upgrade.
*/ */
nmembers = GetMultiXactIdMembers(xmax, &members, false); nmembers = GetMultiXactIdMembers(xmax, &members, false);
if (nmembers > 0) if (nmembers > 0)
{ {
int i; int i;
for (i = 0; i < nmembers; i++) for (i = 0; i < nmembers; i++)
{ {
@ -5284,6 +5290,7 @@ MultiXactIdGetUpdateXid(TransactionId xmax, uint16 t_infomask)
members[i].status == MultiXactStatusUpdate); members[i].status == MultiXactStatusUpdate);
update_xact = members[i].xid; update_xact = members[i].xid;
#ifndef USE_ASSERT_CHECKING #ifndef USE_ASSERT_CHECKING
/* /*
* in an assert-enabled build, walk the whole array to ensure * in an assert-enabled build, walk the whole array to ensure
* there's no other updater. * there's no other updater.
@ -5300,7 +5307,7 @@ MultiXactIdGetUpdateXid(TransactionId xmax, uint16 t_infomask)
/* /*
* HeapTupleGetUpdateXid * HeapTupleGetUpdateXid
* As above, but use a HeapTupleHeader * As above, but use a HeapTupleHeader
* *
* See also HeapTupleHeaderGetUpdateXid, which can be used without previously * See also HeapTupleHeaderGetUpdateXid, which can be used without previously
* checking the hint bits. * checking the hint bits.
@ -5314,7 +5321,7 @@ HeapTupleGetUpdateXid(HeapTupleHeader tuple)
/* /*
* Do_MultiXactIdWait * Do_MultiXactIdWait
* Actual implementation for the two functions below. * Actual implementation for the two functions below.
* *
* We do this by sleeping on each member using XactLockTableWait. Any * We do this by sleeping on each member using XactLockTableWait. Any
* members that belong to the current backend are *not* waited for, however; * members that belong to the current backend are *not* waited for, however;
@ -5432,7 +5439,7 @@ ConditionalMultiXactIdWait(MultiXactId multi, MultiXactStatus status,
* heap_tuple_needs_freeze * heap_tuple_needs_freeze
* *
* Check to see whether any of the XID fields of a tuple (xmin, xmax, xvac) * Check to see whether any of the XID fields of a tuple (xmin, xmax, xvac)
* are older than the specified cutoff XID or MultiXactId. If so, return TRUE. * are older than the specified cutoff XID or MultiXactId. If so, return TRUE.
* *
* It doesn't matter whether the tuple is alive or dead, we are checking * It doesn't matter whether the tuple is alive or dead, we are checking
* to see if a tuple needs to be removed or frozen to avoid wraparound. * to see if a tuple needs to be removed or frozen to avoid wraparound.
@ -6091,7 +6098,7 @@ heap_xlog_freeze(XLogRecPtr lsn, XLogRecord *record)
{ {
xl_heap_freeze *xlrec = (xl_heap_freeze *) XLogRecGetData(record); xl_heap_freeze *xlrec = (xl_heap_freeze *) XLogRecGetData(record);
TransactionId cutoff_xid = xlrec->cutoff_xid; TransactionId cutoff_xid = xlrec->cutoff_xid;
MultiXactId cutoff_multi = xlrec->cutoff_multi; MultiXactId cutoff_multi = xlrec->cutoff_multi;
Buffer buffer; Buffer buffer;
Page page; Page page;
@ -6361,7 +6368,7 @@ heap_xlog_delete(XLogRecPtr lsn, XLogRecord *record)
return; return;
page = (Page) BufferGetPage(buffer); page = (Page) BufferGetPage(buffer);
if (lsn <= PageGetLSN(page)) /* changes are applied */ if (lsn <= PageGetLSN(page)) /* changes are applied */
{ {
UnlockReleaseBuffer(buffer); UnlockReleaseBuffer(buffer);
return; return;
@ -6729,7 +6736,7 @@ heap_xlog_update(XLogRecPtr lsn, XLogRecord *record, bool hot_update)
goto newt; goto newt;
page = (Page) BufferGetPage(obuffer); page = (Page) BufferGetPage(obuffer);
if (lsn <= PageGetLSN(page)) /* changes are applied */ if (lsn <= PageGetLSN(page)) /* changes are applied */
{ {
if (samepage) if (samepage)
{ {
@ -6931,7 +6938,7 @@ heap_xlog_lock(XLogRecPtr lsn, XLogRecord *record)
return; return;
page = (Page) BufferGetPage(buffer); page = (Page) BufferGetPage(buffer);
if (lsn <= PageGetLSN(page)) /* changes are applied */ if (lsn <= PageGetLSN(page)) /* changes are applied */
{ {
UnlockReleaseBuffer(buffer); UnlockReleaseBuffer(buffer);
return; return;
@ -6962,7 +6969,7 @@ static void
heap_xlog_lock_updated(XLogRecPtr lsn, XLogRecord *record) heap_xlog_lock_updated(XLogRecPtr lsn, XLogRecord *record)
{ {
xl_heap_lock_updated *xlrec = xl_heap_lock_updated *xlrec =
(xl_heap_lock_updated *) XLogRecGetData(record); (xl_heap_lock_updated *) XLogRecGetData(record);
Buffer buffer; Buffer buffer;
Page page; Page page;
OffsetNumber offnum; OffsetNumber offnum;
@ -6983,7 +6990,7 @@ heap_xlog_lock_updated(XLogRecPtr lsn, XLogRecord *record)
return; return;
page = (Page) BufferGetPage(buffer); page = (Page) BufferGetPage(buffer);
if (lsn <= PageGetLSN(page)) /* changes are applied */ if (lsn <= PageGetLSN(page)) /* changes are applied */
{ {
UnlockReleaseBuffer(buffer); UnlockReleaseBuffer(buffer);
return; return;
@ -7033,7 +7040,7 @@ heap_xlog_inplace(XLogRecPtr lsn, XLogRecord *record)
return; return;
page = (Page) BufferGetPage(buffer); page = (Page) BufferGetPage(buffer);
if (lsn <= PageGetLSN(page)) /* changes are applied */ if (lsn <= PageGetLSN(page)) /* changes are applied */
{ {
UnlockReleaseBuffer(buffer); UnlockReleaseBuffer(buffer);
return; return;

View File

@ -129,7 +129,7 @@ typedef struct RewriteStateData
* determine tuple visibility */ * determine tuple visibility */
TransactionId rs_freeze_xid;/* Xid that will be used as freeze cutoff TransactionId rs_freeze_xid;/* Xid that will be used as freeze cutoff
* point */ * point */
MultiXactId rs_freeze_multi;/* MultiXactId that will be used as freeze MultiXactId rs_freeze_multi;/* MultiXactId that will be used as freeze
* cutoff point for multixacts */ * cutoff point for multixacts */
MemoryContext rs_cxt; /* for hash tables and entries and tuples in MemoryContext rs_cxt; /* for hash tables and entries and tuples in
* them */ * them */

View File

@ -292,7 +292,7 @@ visibilitymap_set(Relation rel, BlockNumber heapBlk, Buffer heapBuf,
*/ */
if (DataChecksumsEnabled()) if (DataChecksumsEnabled())
{ {
Page heapPage = BufferGetPage(heapBuf); Page heapPage = BufferGetPage(heapBuf);
/* caller is expected to set PD_ALL_VISIBLE first */ /* caller is expected to set PD_ALL_VISIBLE first */
Assert(PageIsAllVisible(heapPage)); Assert(PageIsAllVisible(heapPage));

View File

@ -532,8 +532,8 @@ _bt_log_reuse_page(Relation rel, BlockNumber blkno, TransactionId latestRemovedX
START_CRIT_SECTION(); START_CRIT_SECTION();
/* /*
* We don't do MarkBufferDirty here because we're about to initialise * We don't do MarkBufferDirty here because we're about to initialise the
* the page, and nobody else can see it yet. * page, and nobody else can see it yet.
*/ */
/* XLOG stuff */ /* XLOG stuff */
@ -552,8 +552,8 @@ _bt_log_reuse_page(Relation rel, BlockNumber blkno, TransactionId latestRemovedX
XLogInsert(RM_BTREE_ID, XLOG_BTREE_REUSE_PAGE, rdata); XLogInsert(RM_BTREE_ID, XLOG_BTREE_REUSE_PAGE, rdata);
/* /*
* We don't do PageSetLSN here because we're about to initialise * We don't do PageSetLSN here because we're about to initialise the
* the page, so no need. * page, so no need.
*/ */
} }

View File

@ -373,7 +373,7 @@ btree_xlog_split(bool onleft, bool isroot,
* Note that this code ensures that the items remaining on the * Note that this code ensures that the items remaining on the
* left page are in the correct item number order, but it does not * left page are in the correct item number order, but it does not
* reproduce the physical order they would have had. Is this * reproduce the physical order they would have had. Is this
* worth changing? See also _bt_restore_page(). * worth changing? See also _bt_restore_page().
*/ */
Page lpage = (Page) BufferGetPage(lbuf); Page lpage = (Page) BufferGetPage(lbuf);
BTPageOpaque lopaque = (BTPageOpaque) PageGetSpecialPointer(lpage); BTPageOpaque lopaque = (BTPageOpaque) PageGetSpecialPointer(lpage);
@ -606,18 +606,18 @@ btree_xlog_delete_get_latestRemovedXid(xl_btree_delete *xlrec)
/* /*
* In what follows, we have to examine the previous state of the index * In what follows, we have to examine the previous state of the index
* page, as well as the heap page(s) it points to. This is only valid if * page, as well as the heap page(s) it points to. This is only valid if
* WAL replay has reached a consistent database state; which means that * WAL replay has reached a consistent database state; which means that
* the preceding check is not just an optimization, but is *necessary*. * the preceding check is not just an optimization, but is *necessary*. We
* We won't have let in any user sessions before we reach consistency. * won't have let in any user sessions before we reach consistency.
*/ */
if (!reachedConsistency) if (!reachedConsistency)
elog(PANIC, "btree_xlog_delete_get_latestRemovedXid: cannot operate with inconsistent data"); elog(PANIC, "btree_xlog_delete_get_latestRemovedXid: cannot operate with inconsistent data");
/* /*
* Get index page. If the DB is consistent, this should not fail, nor * Get index page. If the DB is consistent, this should not fail, nor
* should any of the heap page fetches below. If one does, we return * should any of the heap page fetches below. If one does, we return
* InvalidTransactionId to cancel all HS transactions. That's probably * InvalidTransactionId to cancel all HS transactions. That's probably
* overkill, but it's safe, and certainly better than panicking here. * overkill, but it's safe, and certainly better than panicking here.
*/ */
ibuffer = XLogReadBuffer(xlrec->node, xlrec->block, false); ibuffer = XLogReadBuffer(xlrec->node, xlrec->block, false);
@ -701,10 +701,10 @@ btree_xlog_delete_get_latestRemovedXid(xl_btree_delete *xlrec)
/* /*
* XXX If all heap tuples were LP_DEAD then we will be returning * XXX If all heap tuples were LP_DEAD then we will be returning
* InvalidTransactionId here, causing conflict for all HS * InvalidTransactionId here, causing conflict for all HS transactions.
* transactions. That should happen very rarely (reasoning please?). Also * That should happen very rarely (reasoning please?). Also note that
* note that caller can't tell the difference between this case and the * caller can't tell the difference between this case and the fast path
* fast path exit above. May need to change that in future. * exit above. May need to change that in future.
*/ */
return latestRemovedXid; return latestRemovedXid;
} }
@ -721,7 +721,7 @@ btree_xlog_delete(XLogRecPtr lsn, XLogRecord *record)
* If we have any conflict processing to do, it must happen before we * If we have any conflict processing to do, it must happen before we
* update the page. * update the page.
* *
* Btree delete records can conflict with standby queries. You might * Btree delete records can conflict with standby queries. You might
* think that vacuum records would conflict as well, but we've handled * think that vacuum records would conflict as well, but we've handled
* that already. XLOG_HEAP2_CLEANUP_INFO records provide the highest xid * that already. XLOG_HEAP2_CLEANUP_INFO records provide the highest xid
* cleaned by the vacuum of the heap and so we can resolve any conflicts * cleaned by the vacuum of the heap and so we can resolve any conflicts

View File

@ -1,14 +1,14 @@
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* clogdesc.c * clogdesc.c
* rmgr descriptor routines for access/transam/clog.c * rmgr descriptor routines for access/transam/clog.c
* *
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* *
* IDENTIFICATION * IDENTIFICATION
* src/backend/access/rmgrdesc/clogdesc.c * src/backend/access/rmgrdesc/clogdesc.c
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

View File

@ -1,14 +1,14 @@
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* dbasedesc.c * dbasedesc.c
* rmgr descriptor routines for commands/dbcommands.c * rmgr descriptor routines for commands/dbcommands.c
* *
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* *
* IDENTIFICATION * IDENTIFICATION
* src/backend/access/rmgrdesc/dbasedesc.c * src/backend/access/rmgrdesc/dbasedesc.c
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

View File

@ -1,14 +1,14 @@
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* gindesc.c * gindesc.c
* rmgr descriptor routines for access/transam/gin/ginxlog.c * rmgr descriptor routines for access/transam/gin/ginxlog.c
* *
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* *
* IDENTIFICATION * IDENTIFICATION
* src/backend/access/rmgrdesc/gindesc.c * src/backend/access/rmgrdesc/gindesc.c
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

View File

@ -1,14 +1,14 @@
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* gistdesc.c * gistdesc.c
* rmgr descriptor routines for access/gist/gistxlog.c * rmgr descriptor routines for access/gist/gistxlog.c
* *
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* *
* IDENTIFICATION * IDENTIFICATION
* src/backend/access/rmgrdesc/gistdesc.c * src/backend/access/rmgrdesc/gistdesc.c
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

View File

@ -1,14 +1,14 @@
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* hashdesc.c * hashdesc.c
* rmgr descriptor routines for access/hash/hash.c * rmgr descriptor routines for access/hash/hash.c
* *
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* *
* IDENTIFICATION * IDENTIFICATION
* src/backend/access/rmgrdesc/hashdesc.c * src/backend/access/rmgrdesc/hashdesc.c
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

View File

@ -1,14 +1,14 @@
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* heapdesc.c * heapdesc.c
* rmgr descriptor routines for access/heap/heapam.c * rmgr descriptor routines for access/heap/heapam.c
* *
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* *
* IDENTIFICATION * IDENTIFICATION
* src/backend/access/rmgrdesc/heapdesc.c * src/backend/access/rmgrdesc/heapdesc.c
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

View File

@ -1,14 +1,14 @@
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* mxactdesc.c * mxactdesc.c
* rmgr descriptor routines for access/transam/multixact.c * rmgr descriptor routines for access/transam/multixact.c
* *
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* *
* IDENTIFICATION * IDENTIFICATION
* src/backend/access/rmgrdesc/mxactdesc.c * src/backend/access/rmgrdesc/mxactdesc.c
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

View File

@ -1,14 +1,14 @@
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* nbtdesc.c * nbtdesc.c
* rmgr descriptor routines for access/nbtree/nbtxlog.c * rmgr descriptor routines for access/nbtree/nbtxlog.c
* *
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* *
* IDENTIFICATION * IDENTIFICATION
* src/backend/access/rmgrdesc/nbtdesc.c * src/backend/access/rmgrdesc/nbtdesc.c
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

View File

@ -1,14 +1,14 @@
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* relmapdesc.c * relmapdesc.c
* rmgr descriptor routines for utils/cache/relmapper.c * rmgr descriptor routines for utils/cache/relmapper.c
* *
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* *
* IDENTIFICATION * IDENTIFICATION
* src/backend/access/rmgrdesc/relmapdesc.c * src/backend/access/rmgrdesc/relmapdesc.c
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

View File

@ -1,14 +1,14 @@
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* seqdesc.c * seqdesc.c
* rmgr descriptor routines for commands/sequence.c * rmgr descriptor routines for commands/sequence.c
* *
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* *
* IDENTIFICATION * IDENTIFICATION
* src/backend/access/rmgrdesc/seqdesc.c * src/backend/access/rmgrdesc/seqdesc.c
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

View File

@ -1,14 +1,14 @@
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* smgrdesc.c * smgrdesc.c
* rmgr descriptor routines for catalog/storage.c * rmgr descriptor routines for catalog/storage.c
* *
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* *
* IDENTIFICATION * IDENTIFICATION
* src/backend/access/rmgrdesc/smgrdesc.c * src/backend/access/rmgrdesc/smgrdesc.c
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

View File

@ -1,14 +1,14 @@
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* spgdesc.c * spgdesc.c
* rmgr descriptor routines for access/spgist/spgxlog.c * rmgr descriptor routines for access/spgist/spgxlog.c
* *
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* *
* IDENTIFICATION * IDENTIFICATION
* src/backend/access/rmgrdesc/spgdesc.c * src/backend/access/rmgrdesc/spgdesc.c
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

View File

@ -1,14 +1,14 @@
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* standbydesc.c * standbydesc.c
* rmgr descriptor routines for storage/ipc/standby.c * rmgr descriptor routines for storage/ipc/standby.c
* *
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* *
* IDENTIFICATION * IDENTIFICATION
* src/backend/access/rmgrdesc/standbydesc.c * src/backend/access/rmgrdesc/standbydesc.c
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

View File

@ -1,14 +1,14 @@
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* tblspcdesc.c * tblspcdesc.c
* rmgr descriptor routines for commands/tablespace.c * rmgr descriptor routines for commands/tablespace.c
* *
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* *
* IDENTIFICATION * IDENTIFICATION
* src/backend/access/rmgrdesc/tblspcdesc.c * src/backend/access/rmgrdesc/tblspcdesc.c
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

View File

@ -1,14 +1,14 @@
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* xactdesc.c * xactdesc.c
* rmgr descriptor routines for access/transam/xact.c * rmgr descriptor routines for access/transam/xact.c
* *
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* *
* IDENTIFICATION * IDENTIFICATION
* src/backend/access/rmgrdesc/xactdesc.c * src/backend/access/rmgrdesc/xactdesc.c
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */

View File

@ -1,14 +1,14 @@
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* xlogdesc.c * xlogdesc.c
* rmgr descriptor routines for access/transam/xlog.c * rmgr descriptor routines for access/transam/xlog.c
* *
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* *
* IDENTIFICATION * IDENTIFICATION
* src/backend/access/rmgrdesc/xlogdesc.c * src/backend/access/rmgrdesc/xlogdesc.c
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -45,7 +45,7 @@ xlog_desc(StringInfo buf, uint8 xl_info, char *rec)
"tli %u; prev tli %u; fpw %s; xid %u/%u; oid %u; multi %u; offset %u; " "tli %u; prev tli %u; fpw %s; xid %u/%u; oid %u; multi %u; offset %u; "
"oldest xid %u in DB %u; oldest multi %u in DB %u; " "oldest xid %u in DB %u; oldest multi %u in DB %u; "
"oldest running xid %u; %s", "oldest running xid %u; %s",
(uint32) (checkpoint->redo >> 32), (uint32) checkpoint->redo, (uint32) (checkpoint->redo >> 32), (uint32) checkpoint->redo,
checkpoint->ThisTimeLineID, checkpoint->ThisTimeLineID,
checkpoint->PrevTimeLineID, checkpoint->PrevTimeLineID,
checkpoint->fullPageWrites ? "true" : "false", checkpoint->fullPageWrites ? "true" : "false",
@ -84,7 +84,8 @@ xlog_desc(StringInfo buf, uint8 xl_info, char *rec)
} }
else if (info == XLOG_HINT) else if (info == XLOG_HINT)
{ {
BkpBlock *bkp = (BkpBlock *) rec; BkpBlock *bkp = (BkpBlock *) rec;
appendStringInfo(buf, "page hint: %s block %u", appendStringInfo(buf, "page hint: %s block %u",
relpathperm(bkp->node, bkp->fork), relpathperm(bkp->node, bkp->fork),
bkp->block); bkp->block);

View File

@ -30,7 +30,7 @@
* imposed by page headers, tuple headers, etc, we leave 100 bytes for that * imposed by page headers, tuple headers, etc, we leave 100 bytes for that
* (the actual overhead should be no more than 56 bytes at this writing, so * (the actual overhead should be no more than 56 bytes at this writing, so
* there is slop in this number). So we can safely create prefixes up to * there is slop in this number). So we can safely create prefixes up to
* BLCKSZ - 256 * 16 - 100 bytes long. Unfortunately, because 256 * 16 is * BLCKSZ - 256 * 16 - 100 bytes long. Unfortunately, because 256 * 16 is
* already 4K, there is no safe prefix length when BLCKSZ is less than 8K; * already 4K, there is no safe prefix length when BLCKSZ is less than 8K;
* it is always possible to get "SPGiST inner tuple size exceeds maximum" * it is always possible to get "SPGiST inner tuple size exceeds maximum"
* if there are too many distinct next-byte values at a given place in the * if there are too many distinct next-byte values at a given place in the

View File

@ -5,7 +5,7 @@
* *
* The pg_multixact manager is a pg_clog-like manager that stores an array of * The pg_multixact manager is a pg_clog-like manager that stores an array of
* MultiXactMember for each MultiXactId. It is a fundamental part of the * MultiXactMember for each MultiXactId. It is a fundamental part of the
* shared-row-lock implementation. Each MultiXactMember is comprised of a * shared-row-lock implementation. Each MultiXactMember is comprised of a
* TransactionId and a set of flag bits. The name is a bit historical: * TransactionId and a set of flag bits. The name is a bit historical:
* originally, a MultiXactId consisted of more than one TransactionId (except * originally, a MultiXactId consisted of more than one TransactionId (except
* in rare corner cases), hence "multi". Nowadays, however, it's perfectly * in rare corner cases), hence "multi". Nowadays, however, it's perfectly
@ -50,7 +50,7 @@
* The minimum value in each database is stored in pg_database, and the * The minimum value in each database is stored in pg_database, and the
* global minimum is part of pg_control. Any vacuum that is able to * global minimum is part of pg_control. Any vacuum that is able to
* advance its database's minimum value also computes a new global minimum, * advance its database's minimum value also computes a new global minimum,
* and uses this value to truncate older segments. When new multixactid * and uses this value to truncate older segments. When new multixactid
* values are to be created, care is taken that the counter does not * values are to be created, care is taken that the counter does not
* fall within the wraparound horizon considering the global minimum value. * fall within the wraparound horizon considering the global minimum value.
* *
@ -108,7 +108,7 @@
* additional flag bits for each TransactionId. To do this without getting * additional flag bits for each TransactionId. To do this without getting
* into alignment issues, we store four bytes of flags, and then the * into alignment issues, we store four bytes of flags, and then the
* corresponding 4 Xids. Each such 5-word (20-byte) set we call a "group", and * corresponding 4 Xids. Each such 5-word (20-byte) set we call a "group", and
* are stored as a whole in pages. Thus, with 8kB BLCKSZ, we keep 409 groups * are stored as a whole in pages. Thus, with 8kB BLCKSZ, we keep 409 groups
* per page. This wastes 12 bytes per page, but that's OK -- simplicity (and * per page. This wastes 12 bytes per page, but that's OK -- simplicity (and
* performance) trumps space efficiency here. * performance) trumps space efficiency here.
* *
@ -177,17 +177,17 @@ typedef struct MultiXactStateData
MultiXactId lastTruncationPoint; MultiXactId lastTruncationPoint;
/* /*
* oldest multixact that is still on disk. Anything older than this should * oldest multixact that is still on disk. Anything older than this
* not be consulted. * should not be consulted.
*/ */
MultiXactId oldestMultiXactId; MultiXactId oldestMultiXactId;
Oid oldestMultiXactDB; Oid oldestMultiXactDB;
/* support for anti-wraparound measures */ /* support for anti-wraparound measures */
MultiXactId multiVacLimit; MultiXactId multiVacLimit;
MultiXactId multiWarnLimit; MultiXactId multiWarnLimit;
MultiXactId multiStopLimit; MultiXactId multiStopLimit;
MultiXactId multiWrapLimit; MultiXactId multiWrapLimit;
/* /*
* Per-backend data starts here. We have two arrays stored in the area * Per-backend data starts here. We have two arrays stored in the area
@ -252,7 +252,7 @@ static MultiXactId *OldestVisibleMXactId;
* so they will be uninteresting by the time our next transaction starts. * so they will be uninteresting by the time our next transaction starts.
* (XXX not clear that this is correct --- other members of the MultiXact * (XXX not clear that this is correct --- other members of the MultiXact
* could hang around longer than we did. However, it's not clear what a * could hang around longer than we did. However, it's not clear what a
* better policy for flushing old cache entries would be.) FIXME actually * better policy for flushing old cache entries would be.) FIXME actually
* this is plain wrong now that multixact's may contain update Xids. * this is plain wrong now that multixact's may contain update Xids.
* *
* We allocate the cache entries in a memory context that is deleted at * We allocate the cache entries in a memory context that is deleted at
@ -291,7 +291,7 @@ static void RecordNewMultiXact(MultiXactId multi, MultiXactOffset offset,
static MultiXactId GetNewMultiXactId(int nmembers, MultiXactOffset *offset); static MultiXactId GetNewMultiXactId(int nmembers, MultiXactOffset *offset);
/* MultiXact cache management */ /* MultiXact cache management */
static int mxactMemberComparator(const void *arg1, const void *arg2); static int mxactMemberComparator(const void *arg1, const void *arg2);
static MultiXactId mXactCacheGetBySet(int nmembers, MultiXactMember *members); static MultiXactId mXactCacheGetBySet(int nmembers, MultiXactMember *members);
static int mXactCacheGetById(MultiXactId multi, MultiXactMember **members); static int mXactCacheGetById(MultiXactId multi, MultiXactMember **members);
static void mXactCachePut(MultiXactId multi, int nmembers, static void mXactCachePut(MultiXactId multi, int nmembers,
@ -387,15 +387,15 @@ MultiXactIdExpand(MultiXactId multi, TransactionId xid, MultiXactStatus status)
multi, xid, mxstatus_to_string(status)); multi, xid, mxstatus_to_string(status));
/* /*
* Note: we don't allow for old multis here. The reason is that the * Note: we don't allow for old multis here. The reason is that the only
* only caller of this function does a check that the multixact is * caller of this function does a check that the multixact is no longer
* no longer running. * running.
*/ */
nmembers = GetMultiXactIdMembers(multi, &members, false); nmembers = GetMultiXactIdMembers(multi, &members, false);
if (nmembers < 0) if (nmembers < 0)
{ {
MultiXactMember member; MultiXactMember member;
/* /*
* The MultiXactId is obsolete. This can only happen if all the * The MultiXactId is obsolete. This can only happen if all the
@ -430,14 +430,14 @@ MultiXactIdExpand(MultiXactId multi, TransactionId xid, MultiXactStatus status)
} }
/* /*
* Determine which of the members of the MultiXactId are still of interest. * Determine which of the members of the MultiXactId are still of
* This is any running transaction, and also any transaction that grabbed * interest. This is any running transaction, and also any transaction
* something stronger than just a lock and was committed. (An update that * that grabbed something stronger than just a lock and was committed.
* aborted is of no interest here.) * (An update that aborted is of no interest here.)
* *
* (Removing dead members is just an optimization, but a useful one. * (Removing dead members is just an optimization, but a useful one. Note
* Note we have the same race condition here as above: j could be 0 at the * we have the same race condition here as above: j could be 0 at the end
* end of the loop.) * of the loop.)
*/ */
newMembers = (MultiXactMember *) newMembers = (MultiXactMember *)
palloc(sizeof(MultiXactMember) * (nmembers + 1)); palloc(sizeof(MultiXactMember) * (nmembers + 1));
@ -641,12 +641,12 @@ MultiXactIdSetOldestVisible(void)
/* /*
* ReadNextMultiXactId * ReadNextMultiXactId
* Return the next MultiXactId to be assigned, but don't allocate it * Return the next MultiXactId to be assigned, but don't allocate it
*/ */
MultiXactId MultiXactId
ReadNextMultiXactId(void) ReadNextMultiXactId(void)
{ {
MultiXactId mxid; MultiXactId mxid;
/* XXX we could presumably do this without a lock. */ /* XXX we could presumably do this without a lock. */
LWLockAcquire(MultiXactGenLock, LW_SHARED); LWLockAcquire(MultiXactGenLock, LW_SHARED);
@ -722,9 +722,9 @@ CreateMultiXactId(int nmembers, MultiXactMember *members)
/* /*
* XXX Note: there's a lot of padding space in MultiXactMember. We could * XXX Note: there's a lot of padding space in MultiXactMember. We could
* find a more compact representation of this Xlog record -- perhaps all the * find a more compact representation of this Xlog record -- perhaps all
* status flags in one XLogRecData, then all the xids in another one? Not * the status flags in one XLogRecData, then all the xids in another one?
* clear that it's worth the trouble though. * Not clear that it's worth the trouble though.
*/ */
rdata[0].data = (char *) (&xlrec); rdata[0].data = (char *) (&xlrec);
rdata[0].len = SizeOfMultiXactCreate; rdata[0].len = SizeOfMultiXactCreate;
@ -878,7 +878,7 @@ GetNewMultiXactId(int nmembers, MultiXactOffset *offset)
/*---------- /*----------
* Check to see if it's safe to assign another MultiXactId. This protects * Check to see if it's safe to assign another MultiXactId. This protects
* against catastrophic data loss due to multixact wraparound. The basic * against catastrophic data loss due to multixact wraparound. The basic
* rules are: * rules are:
* *
* If we're past multiVacLimit, start trying to force autovacuum cycles. * If we're past multiVacLimit, start trying to force autovacuum cycles.
@ -892,7 +892,7 @@ GetNewMultiXactId(int nmembers, MultiXactOffset *offset)
{ {
/* /*
* For safety's sake, we release MultiXactGenLock while sending * For safety's sake, we release MultiXactGenLock while sending
* signals, warnings, etc. This is not so much because we care about * signals, warnings, etc. This is not so much because we care about
* preserving concurrency in this situation, as to avoid any * preserving concurrency in this situation, as to avoid any
* possibility of deadlock while doing get_database_name(). First, * possibility of deadlock while doing get_database_name(). First,
* copy all the shared values we'll need in this path. * copy all the shared values we'll need in this path.
@ -923,15 +923,15 @@ GetNewMultiXactId(int nmembers, MultiXactOffset *offset)
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("database is not accepting commands that generate new MultiXactIds to avoid wraparound data loss in database \"%s\"", errmsg("database is not accepting commands that generate new MultiXactIds to avoid wraparound data loss in database \"%s\"",
oldest_datname), oldest_datname),
errhint("Execute a database-wide VACUUM in that database.\n" errhint("Execute a database-wide VACUUM in that database.\n"
"You might also need to commit or roll back old prepared transactions."))); "You might also need to commit or roll back old prepared transactions.")));
else else
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("database is not accepting commands that generate new MultiXactIds to avoid wraparound data loss in database with OID %u", errmsg("database is not accepting commands that generate new MultiXactIds to avoid wraparound data loss in database with OID %u",
oldest_datoid), oldest_datoid),
errhint("Execute a database-wide VACUUM in that database.\n" errhint("Execute a database-wide VACUUM in that database.\n"
"You might also need to commit or roll back old prepared transactions."))); "You might also need to commit or roll back old prepared transactions.")));
} }
else if (!MultiXactIdPrecedes(result, multiWarnLimit)) else if (!MultiXactIdPrecedes(result, multiWarnLimit))
{ {
@ -943,15 +943,15 @@ GetNewMultiXactId(int nmembers, MultiXactOffset *offset)
(errmsg("database \"%s\" must be vacuumed before %u more MultiXactIds are used", (errmsg("database \"%s\" must be vacuumed before %u more MultiXactIds are used",
oldest_datname, oldest_datname,
multiWrapLimit - result), multiWrapLimit - result),
errhint("Execute a database-wide VACUUM in that database.\n" errhint("Execute a database-wide VACUUM in that database.\n"
"You might also need to commit or roll back old prepared transactions."))); "You might also need to commit or roll back old prepared transactions.")));
else else
ereport(WARNING, ereport(WARNING,
(errmsg("database with OID %u must be vacuumed before %u more MultiXactIds are used", (errmsg("database with OID %u must be vacuumed before %u more MultiXactIds are used",
oldest_datoid, oldest_datoid,
multiWrapLimit - result), multiWrapLimit - result),
errhint("Execute a database-wide VACUUM in that database.\n" errhint("Execute a database-wide VACUUM in that database.\n"
"You might also need to commit or roll back old prepared transactions."))); "You might also need to commit or roll back old prepared transactions.")));
} }
/* Re-acquire lock and start over */ /* Re-acquire lock and start over */
@ -995,10 +995,10 @@ GetNewMultiXactId(int nmembers, MultiXactOffset *offset)
* *
* We don't care about MultiXactId wraparound here; it will be handled by * We don't care about MultiXactId wraparound here; it will be handled by
* the next iteration. But note that nextMXact may be InvalidMultiXactId * the next iteration. But note that nextMXact may be InvalidMultiXactId
* or the first value on a segment-beginning page after this routine exits, * or the first value on a segment-beginning page after this routine
* so anyone else looking at the variable must be prepared to deal with * exits, so anyone else looking at the variable must be prepared to deal
* either case. Similarly, nextOffset may be zero, but we won't use that * with either case. Similarly, nextOffset may be zero, but we won't use
* as the actual start offset of the next multixact. * that as the actual start offset of the next multixact.
*/ */
(MultiXactState->nextMXact)++; (MultiXactState->nextMXact)++;
@ -1066,18 +1066,18 @@ GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members,
* *
* An ID older than MultiXactState->oldestMultiXactId cannot possibly be * An ID older than MultiXactState->oldestMultiXactId cannot possibly be
* useful; it should have already been frozen by vacuum. We've truncated * useful; it should have already been frozen by vacuum. We've truncated
* the on-disk structures anyway. Returning the wrong values could lead to * the on-disk structures anyway. Returning the wrong values could lead
* an incorrect visibility result. However, to support pg_upgrade we need * to an incorrect visibility result. However, to support pg_upgrade we
* to allow an empty set to be returned regardless, if the caller is * need to allow an empty set to be returned regardless, if the caller is
* willing to accept it; the caller is expected to check that it's an * willing to accept it; the caller is expected to check that it's an
* allowed condition (such as ensuring that the infomask bits set on the * allowed condition (such as ensuring that the infomask bits set on the
* tuple are consistent with the pg_upgrade scenario). If the caller is * tuple are consistent with the pg_upgrade scenario). If the caller is
* expecting this to be called only on recently created multis, then we * expecting this to be called only on recently created multis, then we
* raise an error. * raise an error.
* *
* Conversely, an ID >= nextMXact shouldn't ever be seen here; if it is * Conversely, an ID >= nextMXact shouldn't ever be seen here; if it is
* seen, it implies undetected ID wraparound has occurred. This raises * seen, it implies undetected ID wraparound has occurred. This raises a
* a hard error. * hard error.
* *
* Shared lock is enough here since we aren't modifying any global state. * Shared lock is enough here since we aren't modifying any global state.
* Acquire it just long enough to grab the current counter values. We may * Acquire it just long enough to grab the current counter values. We may
@ -1095,8 +1095,8 @@ GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members,
{ {
ereport(allow_old ? DEBUG1 : ERROR, ereport(allow_old ? DEBUG1 : ERROR,
(errcode(ERRCODE_INTERNAL_ERROR), (errcode(ERRCODE_INTERNAL_ERROR),
errmsg("MultiXactId %u does no longer exist -- apparent wraparound", errmsg("MultiXactId %u does no longer exist -- apparent wraparound",
multi))); multi)));
return -1; return -1;
} }
@ -1349,7 +1349,7 @@ mXactCacheGetById(MultiXactId multi, MultiXactMember **members)
memcpy(ptr, entry->members, size); memcpy(ptr, entry->members, size);
debug_elog3(DEBUG2, "CacheGet: found %s", debug_elog3(DEBUG2, "CacheGet: found %s",
mxid_to_string(multi, entry->nmembers, entry->members)); mxid_to_string(multi, entry->nmembers, entry->members));
return entry->nmembers; return entry->nmembers;
} }
} }
@ -1423,8 +1423,8 @@ mxstatus_to_string(MultiXactStatus status)
char * char *
mxid_to_string(MultiXactId multi, int nmembers, MultiXactMember *members) mxid_to_string(MultiXactId multi, int nmembers, MultiXactMember *members)
{ {
static char *str = NULL; static char *str = NULL;
StringInfoData buf; StringInfoData buf;
int i; int i;
if (str != NULL) if (str != NULL)
@ -1721,7 +1721,7 @@ ZeroMultiXactMemberPage(int pageno, bool writeXlog)
* *
* StartupXLOG has already established nextMXact/nextOffset by calling * StartupXLOG has already established nextMXact/nextOffset by calling
* MultiXactSetNextMXact and/or MultiXactAdvanceNextMXact, and the oldestMulti * MultiXactSetNextMXact and/or MultiXactAdvanceNextMXact, and the oldestMulti
* info from pg_control and/or MultiXactAdvanceOldest. Note that we may * info from pg_control and/or MultiXactAdvanceOldest. Note that we may
* already have replayed WAL data into the SLRU files. * already have replayed WAL data into the SLRU files.
* *
* We don't need any locks here, really; the SLRU locks are taken * We don't need any locks here, really; the SLRU locks are taken
@ -1883,17 +1883,17 @@ MultiXactSetNextMXact(MultiXactId nextMulti,
void void
SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid) SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid)
{ {
MultiXactId multiVacLimit; MultiXactId multiVacLimit;
MultiXactId multiWarnLimit; MultiXactId multiWarnLimit;
MultiXactId multiStopLimit; MultiXactId multiStopLimit;
MultiXactId multiWrapLimit; MultiXactId multiWrapLimit;
MultiXactId curMulti; MultiXactId curMulti;
Assert(MultiXactIdIsValid(oldest_datminmxid)); Assert(MultiXactIdIsValid(oldest_datminmxid));
/* /*
* The place where we actually get into deep trouble is halfway around * The place where we actually get into deep trouble is halfway around
* from the oldest potentially-existing XID/multi. (This calculation is * from the oldest potentially-existing XID/multi. (This calculation is
* probably off by one or two counts for Xids, because the special XIDs * probably off by one or two counts for Xids, because the special XIDs
* reduce the size of the loop a little bit. But we throw in plenty of * reduce the size of the loop a little bit. But we throw in plenty of
* slop below, so it doesn't matter.) * slop below, so it doesn't matter.)
@ -1911,11 +1911,11 @@ SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid)
multiStopLimit -= FirstMultiXactId; multiStopLimit -= FirstMultiXactId;
/* /*
* We'll start complaining loudly when we get within 10M multis of the stop * We'll start complaining loudly when we get within 10M multis of the
* point. This is kind of arbitrary, but if you let your gas gauge get * stop point. This is kind of arbitrary, but if you let your gas gauge
* down to 1% of full, would you be looking for the next gas station? We * get down to 1% of full, would you be looking for the next gas station?
* need to be fairly liberal about this number because there are lots of * We need to be fairly liberal about this number because there are lots
* scenarios where most transactions are done by automatic clients that * of scenarios where most transactions are done by automatic clients that
* won't pay attention to warnings. (No, we're not gonna make this * won't pay attention to warnings. (No, we're not gonna make this
* configurable. If you know enough to configure it, you know enough to * configurable. If you know enough to configure it, you know enough to
* not get in this kind of trouble in the first place.) * not get in this kind of trouble in the first place.)
@ -1925,8 +1925,8 @@ SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid)
multiWarnLimit -= FirstMultiXactId; multiWarnLimit -= FirstMultiXactId;
/* /*
* We'll start trying to force autovacuums when oldest_datminmxid gets * We'll start trying to force autovacuums when oldest_datminmxid gets to
* to be more than 200 million transactions old. * be more than 200 million transactions old.
*/ */
multiVacLimit = oldest_datminmxid + 200000000; multiVacLimit = oldest_datminmxid + 200000000;
if (multiVacLimit < FirstMultiXactId) if (multiVacLimit < FirstMultiXactId)
@ -1945,8 +1945,8 @@ SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid)
/* Log the info */ /* Log the info */
ereport(DEBUG1, ereport(DEBUG1,
(errmsg("MultiXactId wrap limit is %u, limited by database with OID %u", (errmsg("MultiXactId wrap limit is %u, limited by database with OID %u",
multiWrapLimit, oldest_datoid))); multiWrapLimit, oldest_datoid)));
/* /*
* If past the autovacuum force point, immediately signal an autovac * If past the autovacuum force point, immediately signal an autovac
@ -2127,9 +2127,9 @@ ExtendMultiXactMember(MultiXactOffset offset, int nmembers)
MultiXactId MultiXactId
GetOldestMultiXactId(void) GetOldestMultiXactId(void)
{ {
MultiXactId oldestMXact; MultiXactId oldestMXact;
MultiXactId nextMXact; MultiXactId nextMXact;
int i; int i;
/* /*
* This is the oldest valid value among all the OldestMemberMXactId[] and * This is the oldest valid value among all the OldestMemberMXactId[] and
@ -2168,17 +2168,17 @@ GetOldestMultiXactId(void)
typedef struct mxtruncinfo typedef struct mxtruncinfo
{ {
int earliestExistingPage; int earliestExistingPage;
} mxtruncinfo; } mxtruncinfo;
/* /*
* SlruScanDirectory callback * SlruScanDirectory callback
* This callback determines the earliest existing page number. * This callback determines the earliest existing page number.
*/ */
static bool static bool
SlruScanDirCbFindEarliest(SlruCtl ctl, char *filename, int segpage, void *data) SlruScanDirCbFindEarliest(SlruCtl ctl, char *filename, int segpage, void *data)
{ {
mxtruncinfo *trunc = (mxtruncinfo *) data; mxtruncinfo *trunc = (mxtruncinfo *) data;
if (trunc->earliestExistingPage == -1 || if (trunc->earliestExistingPage == -1 ||
ctl->PagePrecedes(segpage, trunc->earliestExistingPage)) ctl->PagePrecedes(segpage, trunc->earliestExistingPage))
@ -2186,7 +2186,7 @@ SlruScanDirCbFindEarliest(SlruCtl ctl, char *filename, int segpage, void *data)
trunc->earliestExistingPage = segpage; trunc->earliestExistingPage = segpage;
} }
return false; /* keep going */ return false; /* keep going */
} }
/* /*
@ -2200,16 +2200,16 @@ SlruScanDirCbFindEarliest(SlruCtl ctl, char *filename, int segpage, void *data)
void void
TruncateMultiXact(MultiXactId oldestMXact) TruncateMultiXact(MultiXactId oldestMXact)
{ {
MultiXactOffset oldestOffset; MultiXactOffset oldestOffset;
mxtruncinfo trunc; mxtruncinfo trunc;
MultiXactId earliest; MultiXactId earliest;
/* /*
* Note we can't just plow ahead with the truncation; it's possible that * Note we can't just plow ahead with the truncation; it's possible that
* there are no segments to truncate, which is a problem because we are * there are no segments to truncate, which is a problem because we are
* going to attempt to read the offsets page to determine where to truncate * going to attempt to read the offsets page to determine where to
* the members SLRU. So we first scan the directory to determine the * truncate the members SLRU. So we first scan the directory to determine
* earliest offsets page number that we can read without error. * the earliest offsets page number that we can read without error.
*/ */
trunc.earliestExistingPage = -1; trunc.earliestExistingPage = -1;
SlruScanDirectory(MultiXactOffsetCtl, SlruScanDirCbFindEarliest, &trunc); SlruScanDirectory(MultiXactOffsetCtl, SlruScanDirCbFindEarliest, &trunc);
@ -2220,9 +2220,9 @@ TruncateMultiXact(MultiXactId oldestMXact)
return; return;
/* /*
* First, compute the safe truncation point for MultiXactMember. * First, compute the safe truncation point for MultiXactMember. This is
* This is the starting offset of the multixact we were passed * the starting offset of the multixact we were passed as MultiXactOffset
* as MultiXactOffset cutoff. * cutoff.
*/ */
{ {
int pageno; int pageno;
@ -2380,7 +2380,7 @@ multixact_redo(XLogRecPtr lsn, XLogRecord *record)
else if (info == XLOG_MULTIXACT_CREATE_ID) else if (info == XLOG_MULTIXACT_CREATE_ID)
{ {
xl_multixact_create *xlrec = xl_multixact_create *xlrec =
(xl_multixact_create *) XLogRecGetData(record); (xl_multixact_create *) XLogRecGetData(record);
TransactionId max_xid; TransactionId max_xid;
int i; int i;
@ -2427,12 +2427,12 @@ pg_get_multixact_members(PG_FUNCTION_ARGS)
{ {
typedef struct typedef struct
{ {
MultiXactMember *members; MultiXactMember *members;
int nmembers; int nmembers;
int iter; int iter;
} mxact; } mxact;
MultiXactId mxid = PG_GETARG_UINT32(0); MultiXactId mxid = PG_GETARG_UINT32(0);
mxact *multi; mxact *multi;
FuncCallContext *funccxt; FuncCallContext *funccxt;
if (mxid < FirstMultiXactId) if (mxid < FirstMultiXactId)

View File

@ -15,7 +15,7 @@
* <parentTLI> <switchpoint> <reason> * <parentTLI> <switchpoint> <reason>
* *
* parentTLI ID of the parent timeline * parentTLI ID of the parent timeline
* switchpoint XLogRecPtr of the WAL position where the switch happened * switchpoint XLogRecPtr of the WAL position where the switch happened
* reason human-readable explanation of why the timeline was changed * reason human-readable explanation of why the timeline was changed
* *
* The fields are separated by tabs. Lines beginning with # are comments, and * The fields are separated by tabs. Lines beginning with # are comments, and
@ -49,7 +49,7 @@ restoreTimeLineHistoryFiles(TimeLineID begin, TimeLineID end)
{ {
char path[MAXPGPATH]; char path[MAXPGPATH];
char histfname[MAXFNAMELEN]; char histfname[MAXFNAMELEN];
TimeLineID tli; TimeLineID tli;
for (tli = begin; tli < end; tli++) for (tli = begin; tli < end; tli++)
{ {
@ -179,8 +179,8 @@ readTimeLineHistory(TimeLineID targetTLI)
errhint("Timeline IDs must be less than child timeline's ID."))); errhint("Timeline IDs must be less than child timeline's ID.")));
/* /*
* Create one more entry for the "tip" of the timeline, which has no * Create one more entry for the "tip" of the timeline, which has no entry
* entry in the history file. * in the history file.
*/ */
entry = (TimeLineHistoryEntry *) palloc(sizeof(TimeLineHistoryEntry)); entry = (TimeLineHistoryEntry *) palloc(sizeof(TimeLineHistoryEntry));
entry->tli = targetTLI; entry->tli = targetTLI;
@ -418,7 +418,7 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI,
/* /*
* Prefer link() to rename() here just to be really sure that we don't * Prefer link() to rename() here just to be really sure that we don't
* overwrite an existing file. However, there shouldn't be one, so * overwrite an existing file. However, there shouldn't be one, so
* rename() is an acceptable substitute except for the truly paranoid. * rename() is an acceptable substitute except for the truly paranoid.
*/ */
#if HAVE_WORKING_LINK #if HAVE_WORKING_LINK
@ -530,7 +530,7 @@ writeTimeLineHistoryFile(TimeLineID tli, char *content, int size)
bool bool
tliInHistory(TimeLineID tli, List *expectedTLEs) tliInHistory(TimeLineID tli, List *expectedTLEs)
{ {
ListCell *cell; ListCell *cell;
foreach(cell, expectedTLEs) foreach(cell, expectedTLEs)
{ {
@ -548,11 +548,12 @@ tliInHistory(TimeLineID tli, List *expectedTLEs)
TimeLineID TimeLineID
tliOfPointInHistory(XLogRecPtr ptr, List *history) tliOfPointInHistory(XLogRecPtr ptr, List *history)
{ {
ListCell *cell; ListCell *cell;
foreach(cell, history) foreach(cell, history)
{ {
TimeLineHistoryEntry *tle = (TimeLineHistoryEntry *) lfirst(cell); TimeLineHistoryEntry *tle = (TimeLineHistoryEntry *) lfirst(cell);
if ((XLogRecPtrIsInvalid(tle->begin) || tle->begin <= ptr) && if ((XLogRecPtrIsInvalid(tle->begin) || tle->begin <= ptr) &&
(XLogRecPtrIsInvalid(tle->end) || ptr < tle->end)) (XLogRecPtrIsInvalid(tle->end) || ptr < tle->end))
{ {
@ -563,7 +564,7 @@ tliOfPointInHistory(XLogRecPtr ptr, List *history)
/* shouldn't happen. */ /* shouldn't happen. */
elog(ERROR, "timeline history was not contiguous"); elog(ERROR, "timeline history was not contiguous");
return 0; /* keep compiler quiet */ return 0; /* keep compiler quiet */
} }
/* /*
@ -579,7 +580,7 @@ tliSwitchPoint(TimeLineID tli, List *history, TimeLineID *nextTLI)
if (nextTLI) if (nextTLI)
*nextTLI = 0; *nextTLI = 0;
foreach (cell, history) foreach(cell, history)
{ {
TimeLineHistoryEntry *tle = (TimeLineHistoryEntry *) lfirst(cell); TimeLineHistoryEntry *tle = (TimeLineHistoryEntry *) lfirst(cell);
@ -592,5 +593,5 @@ tliSwitchPoint(TimeLineID tli, List *history, TimeLineID *nextTLI)
ereport(ERROR, ereport(ERROR,
(errmsg("requested timeline %u is not in this server's history", (errmsg("requested timeline %u is not in this server's history",
tli))); tli)));
return InvalidXLogRecPtr; /* keep compiler quiet */ return InvalidXLogRecPtr; /* keep compiler quiet */
} }

View File

@ -1024,8 +1024,8 @@ RecordTransactionCommit(void)
* *
* It's safe to change the delayChkpt flag of our own backend without * It's safe to change the delayChkpt flag of our own backend without
* holding the ProcArrayLock, since we're the only one modifying it. * holding the ProcArrayLock, since we're the only one modifying it.
* This makes checkpoint's determination of which xacts are delayChkpt a * This makes checkpoint's determination of which xacts are delayChkpt
* bit fuzzy, but it doesn't matter. * a bit fuzzy, but it doesn't matter.
*/ */
START_CRIT_SECTION(); START_CRIT_SECTION();
MyPgXact->delayChkpt = true; MyPgXact->delayChkpt = true;
@ -4683,12 +4683,11 @@ xact_redo_commit_internal(TransactionId xid, XLogRecPtr lsn,
* from the template database, and then commit the transaction. If we * from the template database, and then commit the transaction. If we
* crash after all the files have been copied but before the commit, you * crash after all the files have been copied but before the commit, you
* have files in the data directory without an entry in pg_database. To * have files in the data directory without an entry in pg_database. To
* minimize the window * minimize the window for that, we use ForceSyncCommit() to rush the
* for that, we use ForceSyncCommit() to rush the commit record to disk as * commit record to disk as quick as possible. We have the same window
* quick as possible. We have the same window during recovery, and forcing * during recovery, and forcing an XLogFlush() (which updates
* an XLogFlush() (which updates minRecoveryPoint during recovery) helps * minRecoveryPoint during recovery) helps to reduce that problem window,
* to reduce that problem window, for any user that requested * for any user that requested ForceSyncCommit().
* ForceSyncCommit().
*/ */
if (XactCompletionForceSyncCommit(xinfo)) if (XactCompletionForceSyncCommit(xinfo))
XLogFlush(lsn); XLogFlush(lsn);

File diff suppressed because it is too large Load Diff

View File

@ -87,9 +87,9 @@ RestoreArchivedFile(char *path, const char *xlogfname,
* of log segments that weren't yet transferred to the archive. * of log segments that weren't yet transferred to the archive.
* *
* Notice that we don't actually overwrite any files when we copy back * Notice that we don't actually overwrite any files when we copy back
* from archive because the restore_command may inadvertently * from archive because the restore_command may inadvertently restore
* restore inappropriate xlogs, or they may be corrupt, so we may wish to * inappropriate xlogs, or they may be corrupt, so we may wish to fallback
* fallback to the segments remaining in current XLOGDIR later. The * to the segments remaining in current XLOGDIR later. The
* copy-from-archive filename is always the same, ensuring that we don't * copy-from-archive filename is always the same, ensuring that we don't
* run out of disk space on long recoveries. * run out of disk space on long recoveries.
*/ */
@ -433,19 +433,20 @@ KeepFileRestoredFromArchive(char *path, char *xlogfname)
if (stat(xlogfpath, &statbuf) == 0) if (stat(xlogfpath, &statbuf) == 0)
{ {
char oldpath[MAXPGPATH]; char oldpath[MAXPGPATH];
#ifdef WIN32 #ifdef WIN32
static unsigned int deletedcounter = 1; static unsigned int deletedcounter = 1;
/* /*
* On Windows, if another process (e.g a walsender process) holds * On Windows, if another process (e.g a walsender process) holds the
* the file open in FILE_SHARE_DELETE mode, unlink will succeed, * file open in FILE_SHARE_DELETE mode, unlink will succeed, but the
* but the file will still show up in directory listing until the * file will still show up in directory listing until the last handle
* last handle is closed, and we cannot rename the new file in its * is closed, and we cannot rename the new file in its place until
* place until that. To avoid that problem, rename the old file to * that. To avoid that problem, rename the old file to a temporary
* a temporary name first. Use a counter to create a unique * name first. Use a counter to create a unique filename, because the
* filename, because the same file might be restored from the * same file might be restored from the archive multiple times, and a
* archive multiple times, and a walsender could still be holding * walsender could still be holding onto an old deleted version of it.
* onto an old deleted version of it.
*/ */
snprintf(oldpath, MAXPGPATH, "%s.deleted%u", snprintf(oldpath, MAXPGPATH, "%s.deleted%u",
xlogfpath, deletedcounter++); xlogfpath, deletedcounter++);
@ -474,17 +475,17 @@ KeepFileRestoredFromArchive(char *path, char *xlogfname)
path, xlogfpath))); path, xlogfpath)));
/* /*
* Create .done file forcibly to prevent the restored segment from * Create .done file forcibly to prevent the restored segment from being
* being archived again later. * archived again later.
*/ */
XLogArchiveForceDone(xlogfname); XLogArchiveForceDone(xlogfname);
/* /*
* If the existing file was replaced, since walsenders might have it * If the existing file was replaced, since walsenders might have it open,
* open, request them to reload a currently-open segment. This is only * request them to reload a currently-open segment. This is only required
* required for WAL segments, walsenders don't hold other files open, but * for WAL segments, walsenders don't hold other files open, but there's
* there's no harm in doing this too often, and we don't know what kind * no harm in doing this too often, and we don't know what kind of a file
* of a file we're dealing with here. * we're dealing with here.
*/ */
if (reload) if (reload)
WalSndRqstFileReload(); WalSndRqstFileReload();

View File

@ -545,8 +545,8 @@ pg_xlog_location_diff(PG_FUNCTION_ARGS)
* XXX: this won't handle values higher than 2^63 correctly. * XXX: this won't handle values higher than 2^63 correctly.
*/ */
result = DatumGetNumeric(DirectFunctionCall2(numeric_sub, result = DatumGetNumeric(DirectFunctionCall2(numeric_sub,
DirectFunctionCall1(int8_numeric, Int64GetDatum((int64) bytes1)), DirectFunctionCall1(int8_numeric, Int64GetDatum((int64) bytes1)),
DirectFunctionCall1(int8_numeric, Int64GetDatum((int64) bytes2)))); DirectFunctionCall1(int8_numeric, Int64GetDatum((int64) bytes2))));
PG_RETURN_NUMERIC(result); PG_RETURN_NUMERIC(result);
} }
@ -584,7 +584,7 @@ pg_backup_start_time(PG_FUNCTION_ARGS)
ereport(ERROR, ereport(ERROR,
(errcode_for_file_access(), (errcode_for_file_access(),
errmsg("could not read file \"%s\": %m", errmsg("could not read file \"%s\": %m",
BACKUP_LABEL_FILE))); BACKUP_LABEL_FILE)));
PG_RETURN_NULL(); PG_RETURN_NULL();
} }
@ -602,13 +602,13 @@ pg_backup_start_time(PG_FUNCTION_ARGS)
if (ferror(lfp)) if (ferror(lfp))
ereport(ERROR, ereport(ERROR,
(errcode_for_file_access(), (errcode_for_file_access(),
errmsg("could not read file \"%s\": %m", BACKUP_LABEL_FILE))); errmsg("could not read file \"%s\": %m", BACKUP_LABEL_FILE)));
/* Close the backup label file. */ /* Close the backup label file. */
if (FreeFile(lfp)) if (FreeFile(lfp))
ereport(ERROR, ereport(ERROR,
(errcode_for_file_access(), (errcode_for_file_access(),
errmsg("could not close file \"%s\": %m", BACKUP_LABEL_FILE))); errmsg("could not close file \"%s\": %m", BACKUP_LABEL_FILE)));
if (strlen(backup_start_time) == 0) if (strlen(backup_start_time) == 0)
ereport(ERROR, ereport(ERROR,

View File

@ -221,9 +221,9 @@ XLogReadRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg)
targetRecOff = RecPtr % XLOG_BLCKSZ; targetRecOff = RecPtr % XLOG_BLCKSZ;
/* /*
* Read the page containing the record into state->readBuf. Request * Read the page containing the record into state->readBuf. Request enough
* enough byte to cover the whole record header, or at least the part of * byte to cover the whole record header, or at least the part of it that
* it that fits on the same page. * fits on the same page.
*/ */
readOff = ReadPageInternal(state, readOff = ReadPageInternal(state,
targetPagePtr, targetPagePtr,

View File

@ -49,7 +49,7 @@
extern int optind; extern int optind;
extern char *optarg; extern char *optarg;
uint32 bootstrap_data_checksum_version = 0; /* No checksum */ uint32 bootstrap_data_checksum_version = 0; /* No checksum */
#define ALLOC(t, c) ((t *) calloc((unsigned)(c), sizeof(t))) #define ALLOC(t, c) ((t *) calloc((unsigned)(c), sizeof(t)))
@ -67,7 +67,7 @@ static void cleanup(void);
* ---------------- * ----------------
*/ */
AuxProcType MyAuxProcType = NotAnAuxProcess; /* declared in miscadmin.h */ AuxProcType MyAuxProcType = NotAnAuxProcess; /* declared in miscadmin.h */
Relation boot_reldesc; /* current relation descriptor */ Relation boot_reldesc; /* current relation descriptor */
@ -389,7 +389,7 @@ AuxiliaryProcessMain(int argc, char *argv[])
/* /*
* Assign the ProcSignalSlot for an auxiliary process. Since it * Assign the ProcSignalSlot for an auxiliary process. Since it
* doesn't have a BackendId, the slot is statically allocated based on * doesn't have a BackendId, the slot is statically allocated based on
* the auxiliary process type (MyAuxProcType). Backends use slots * the auxiliary process type (MyAuxProcType). Backends use slots
* indexed in the range from 1 to MaxBackends (inclusive), so we use * indexed in the range from 1 to MaxBackends (inclusive), so we use
* MaxBackends + AuxProcType + 1 as the index of the slot for an * MaxBackends + AuxProcType + 1 as the index of the slot for an
* auxiliary process. * auxiliary process.

View File

@ -3419,7 +3419,7 @@ aclcheck_error_col(AclResult aclerr, AclObjectKind objectkind,
void void
aclcheck_error_type(AclResult aclerr, Oid typeOid) aclcheck_error_type(AclResult aclerr, Oid typeOid)
{ {
Oid element_type = get_element_type(typeOid); Oid element_type = get_element_type(typeOid);
aclcheck_error(aclerr, ACL_KIND_TYPE, format_type_be(element_type ? element_type : typeOid)); aclcheck_error(aclerr, ACL_KIND_TYPE, format_type_be(element_type ? element_type : typeOid));
} }

View File

@ -335,7 +335,7 @@ GetNewOid(Relation relation)
* This is exported separately because there are cases where we want to use * This is exported separately because there are cases where we want to use
* an index that will not be recognized by RelationGetOidIndex: TOAST tables * an index that will not be recognized by RelationGetOidIndex: TOAST tables
* have indexes that are usable, but have multiple columns and are on * have indexes that are usable, but have multiple columns and are on
* ordinary columns rather than a true OID column. This code will work * ordinary columns rather than a true OID column. This code will work
* anyway, so long as the OID is the index's first column. The caller must * anyway, so long as the OID is the index's first column. The caller must
* pass in the actual heap attnum of the OID column, however. * pass in the actual heap attnum of the OID column, however.
* *

View File

@ -198,7 +198,7 @@ static void
deleteObjectsInList(ObjectAddresses *targetObjects, Relation *depRel, deleteObjectsInList(ObjectAddresses *targetObjects, Relation *depRel,
int flags) int flags)
{ {
int i; int i;
/* /*
* Keep track of objects for event triggers, if necessary. * Keep track of objects for event triggers, if necessary.

View File

@ -98,7 +98,7 @@ static void StoreRelCheck(Relation rel, char *ccname, Node *expr,
bool is_validated, bool is_local, int inhcount, bool is_validated, bool is_local, int inhcount,
bool is_no_inherit, bool is_internal); bool is_no_inherit, bool is_internal);
static void StoreConstraints(Relation rel, List *cooked_constraints, static void StoreConstraints(Relation rel, List *cooked_constraints,
bool is_internal); bool is_internal);
static bool MergeWithExistingConstraint(Relation rel, char *ccname, Node *expr, static bool MergeWithExistingConstraint(Relation rel, char *ccname, Node *expr,
bool allow_merge, bool is_local, bool allow_merge, bool is_local,
bool is_no_inherit); bool is_no_inherit);
@ -870,6 +870,7 @@ AddNewRelationTuple(Relation pg_class_desc,
* that will do. * that will do.
*/ */
new_rel_reltup->relfrozenxid = RecentXmin; new_rel_reltup->relfrozenxid = RecentXmin;
/* /*
* Similarly, initialize the minimum Multixact to the first value that * Similarly, initialize the minimum Multixact to the first value that
* could possibly be stored in tuples in the table. Running * could possibly be stored in tuples in the table. Running
@ -1915,10 +1916,10 @@ StoreAttrDefault(Relation rel, AttrNumber attnum,
/* /*
* Post creation hook for attribute defaults. * Post creation hook for attribute defaults.
* *
* XXX. ALTER TABLE ALTER COLUMN SET/DROP DEFAULT is implemented * XXX. ALTER TABLE ALTER COLUMN SET/DROP DEFAULT is implemented with a
* with a couple of deletion/creation of the attribute's default entry, * couple of deletion/creation of the attribute's default entry, so the
* so the callee should check existence of an older version of this * callee should check existence of an older version of this entry if it
* entry if it needs to distinguish. * needs to distinguish.
*/ */
InvokeObjectPostCreateHookArg(AttrDefaultRelationId, InvokeObjectPostCreateHookArg(AttrDefaultRelationId,
RelationGetRelid(rel), attnum, is_internal); RelationGetRelid(rel), attnum, is_internal);
@ -2018,7 +2019,7 @@ StoreRelCheck(Relation rel, char *ccname, Node *expr,
is_local, /* conislocal */ is_local, /* conislocal */
inhcount, /* coninhcount */ inhcount, /* coninhcount */
is_no_inherit, /* connoinherit */ is_no_inherit, /* connoinherit */
is_internal); /* internally constructed? */ is_internal); /* internally constructed? */
pfree(ccbin); pfree(ccbin);
pfree(ccsrc); pfree(ccsrc);

View File

@ -293,9 +293,10 @@ RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode,
Oid namespaceId; Oid namespaceId;
namespaceId = LookupExplicitNamespace(relation->schemaname, missing_ok); namespaceId = LookupExplicitNamespace(relation->schemaname, missing_ok);
/* /*
* For missing_ok, allow a non-existant schema name to * For missing_ok, allow a non-existant schema name to
* return InvalidOid. * return InvalidOid.
*/ */
if (namespaceId != myTempNamespace) if (namespaceId != myTempNamespace)
ereport(ERROR, ereport(ERROR,
@ -2701,7 +2702,7 @@ LookupExplicitNamespace(const char *nspname, bool missing_ok)
namespaceId = get_namespace_oid(nspname, missing_ok); namespaceId = get_namespace_oid(nspname, missing_ok);
if (missing_ok && !OidIsValid(namespaceId)) if (missing_ok && !OidIsValid(namespaceId))
return InvalidOid; return InvalidOid;
aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE); aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE);
if (aclresult != ACLCHECK_OK) if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_NAMESPACE, aclcheck_error(aclresult, ACL_KIND_NAMESPACE,

View File

@ -29,7 +29,7 @@ void
RunObjectPostCreateHook(Oid classId, Oid objectId, int subId, RunObjectPostCreateHook(Oid classId, Oid objectId, int subId,
bool is_internal) bool is_internal)
{ {
ObjectAccessPostCreate pc_arg; ObjectAccessPostCreate pc_arg;
/* caller should check, but just in case... */ /* caller should check, but just in case... */
Assert(object_access_hook != NULL); Assert(object_access_hook != NULL);
@ -37,9 +37,9 @@ RunObjectPostCreateHook(Oid classId, Oid objectId, int subId,
memset(&pc_arg, 0, sizeof(ObjectAccessPostCreate)); memset(&pc_arg, 0, sizeof(ObjectAccessPostCreate));
pc_arg.is_internal = is_internal; pc_arg.is_internal = is_internal;
(*object_access_hook)(OAT_POST_CREATE, (*object_access_hook) (OAT_POST_CREATE,
classId, objectId, subId, classId, objectId, subId,
(void *) &pc_arg); (void *) &pc_arg);
} }
/* /*
@ -51,7 +51,7 @@ void
RunObjectDropHook(Oid classId, Oid objectId, int subId, RunObjectDropHook(Oid classId, Oid objectId, int subId,
int dropflags) int dropflags)
{ {
ObjectAccessDrop drop_arg; ObjectAccessDrop drop_arg;
/* caller should check, but just in case... */ /* caller should check, but just in case... */
Assert(object_access_hook != NULL); Assert(object_access_hook != NULL);
@ -59,9 +59,9 @@ RunObjectDropHook(Oid classId, Oid objectId, int subId,
memset(&drop_arg, 0, sizeof(ObjectAccessDrop)); memset(&drop_arg, 0, sizeof(ObjectAccessDrop));
drop_arg.dropflags = dropflags; drop_arg.dropflags = dropflags;
(*object_access_hook)(OAT_DROP, (*object_access_hook) (OAT_DROP,
classId, objectId, subId, classId, objectId, subId,
(void *) &drop_arg); (void *) &drop_arg);
} }
/* /*
@ -73,7 +73,7 @@ void
RunObjectPostAlterHook(Oid classId, Oid objectId, int subId, RunObjectPostAlterHook(Oid classId, Oid objectId, int subId,
Oid auxiliaryId, bool is_internal) Oid auxiliaryId, bool is_internal)
{ {
ObjectAccessPostAlter pa_arg; ObjectAccessPostAlter pa_arg;
/* caller should check, but just in case... */ /* caller should check, but just in case... */
Assert(object_access_hook != NULL); Assert(object_access_hook != NULL);
@ -82,9 +82,9 @@ RunObjectPostAlterHook(Oid classId, Oid objectId, int subId,
pa_arg.auxiliary_id = auxiliaryId; pa_arg.auxiliary_id = auxiliaryId;
pa_arg.is_internal = is_internal; pa_arg.is_internal = is_internal;
(*object_access_hook)(OAT_POST_ALTER, (*object_access_hook) (OAT_POST_ALTER,
classId, objectId, subId, classId, objectId, subId,
(void *) &pa_arg); (void *) &pa_arg);
} }
/* /*
@ -95,7 +95,7 @@ RunObjectPostAlterHook(Oid classId, Oid objectId, int subId,
bool bool
RunNamespaceSearchHook(Oid objectId, bool ereport_on_violation) RunNamespaceSearchHook(Oid objectId, bool ereport_on_violation)
{ {
ObjectAccessNamespaceSearch ns_arg; ObjectAccessNamespaceSearch ns_arg;
/* caller should check, but just in case... */ /* caller should check, but just in case... */
Assert(object_access_hook != NULL); Assert(object_access_hook != NULL);
@ -104,9 +104,9 @@ RunNamespaceSearchHook(Oid objectId, bool ereport_on_violation)
ns_arg.ereport_on_violation = ereport_on_violation; ns_arg.ereport_on_violation = ereport_on_violation;
ns_arg.result = true; ns_arg.result = true;
(*object_access_hook)(OAT_NAMESPACE_SEARCH, (*object_access_hook) (OAT_NAMESPACE_SEARCH,
NamespaceRelationId, objectId, 0, NamespaceRelationId, objectId, 0,
(void *) &ns_arg); (void *) &ns_arg);
return ns_arg.result; return ns_arg.result;
} }
@ -122,7 +122,7 @@ RunFunctionExecuteHook(Oid objectId)
/* caller should check, but just in case... */ /* caller should check, but just in case... */
Assert(object_access_hook != NULL); Assert(object_access_hook != NULL);
(*object_access_hook)(OAT_FUNCTION_EXECUTE, (*object_access_hook) (OAT_FUNCTION_EXECUTE,
ProcedureRelationId, objectId, 0, ProcedureRelationId, objectId, 0,
NULL); NULL);
} }

View File

@ -94,10 +94,11 @@ typedef struct
AttrNumber attnum_owner; /* attnum of owner field */ AttrNumber attnum_owner; /* attnum of owner field */
AttrNumber attnum_acl; /* attnum of acl field */ AttrNumber attnum_acl; /* attnum of acl field */
AclObjectKind acl_kind; /* ACL_KIND_* of this object type */ AclObjectKind acl_kind; /* ACL_KIND_* of this object type */
bool is_nsp_name_unique; /* can the nsp/name combination (or name bool is_nsp_name_unique; /* can the nsp/name combination (or
* alone, if there's no namespace) be * name alone, if there's no
* considered an unique identifier for an * namespace) be considered an unique
* object of this class? */ * identifier for an object of this
* class? */
} ObjectPropertyType; } ObjectPropertyType;
static ObjectPropertyType ObjectProperty[] = static ObjectPropertyType ObjectProperty[] =
@ -1443,7 +1444,7 @@ get_object_property_data(Oid class_id)
ereport(ERROR, ereport(ERROR,
(errmsg_internal("unrecognized class id: %u", class_id))); (errmsg_internal("unrecognized class id: %u", class_id)));
return NULL; /* keep MSC compiler happy */ return NULL; /* keep MSC compiler happy */
} }
/* /*
@ -1463,14 +1464,14 @@ get_catalog_object_by_oid(Relation catalog, Oid objectId)
if (oidCacheId > 0) if (oidCacheId > 0)
{ {
tuple = SearchSysCacheCopy1(oidCacheId, ObjectIdGetDatum(objectId)); tuple = SearchSysCacheCopy1(oidCacheId, ObjectIdGetDatum(objectId));
if (!HeapTupleIsValid(tuple)) /* should not happen */ if (!HeapTupleIsValid(tuple)) /* should not happen */
return NULL; return NULL;
} }
else else
{ {
Oid oidIndexId = get_object_oid_index(classId); Oid oidIndexId = get_object_oid_index(classId);
SysScanDesc scan; SysScanDesc scan;
ScanKeyData skey; ScanKeyData skey;
Assert(OidIsValid(oidIndexId)); Assert(OidIsValid(oidIndexId));
@ -2127,7 +2128,7 @@ getObjectDescription(const ObjectAddress *object)
break; break;
} }
case OCLASS_EVENT_TRIGGER: case OCLASS_EVENT_TRIGGER:
{ {
HeapTuple tup; HeapTuple tup;
@ -2137,7 +2138,7 @@ getObjectDescription(const ObjectAddress *object)
elog(ERROR, "cache lookup failed for event trigger %u", elog(ERROR, "cache lookup failed for event trigger %u",
object->objectId); object->objectId);
appendStringInfo(&buffer, _("event trigger %s"), appendStringInfo(&buffer, _("event trigger %s"),
NameStr(((Form_pg_event_trigger) GETSTRUCT(tup))->evtname)); NameStr(((Form_pg_event_trigger) GETSTRUCT(tup))->evtname));
ReleaseSysCache(tup); ReleaseSysCache(tup);
break; break;
} }
@ -2355,22 +2356,22 @@ pg_identify_object(PG_FUNCTION_ARGS)
RelationGetDescr(catalog), &isnull); RelationGetDescr(catalog), &isnull);
if (isnull) if (isnull)
elog(ERROR, "invalid null namespace in object %u/%u/%d", elog(ERROR, "invalid null namespace in object %u/%u/%d",
address.classId, address.objectId, address.objectSubId); address.classId, address.objectId, address.objectSubId);
} }
/* /*
* We only return the object name if it can be used (together * We only return the object name if it can be used (together with
* with the schema name, if any) as an unique identifier. * the schema name, if any) as an unique identifier.
*/ */
if (get_object_namensp_unique(address.classId)) if (get_object_namensp_unique(address.classId))
{ {
nameAttnum = get_object_attnum_name(address.classId); nameAttnum = get_object_attnum_name(address.classId);
if (nameAttnum != InvalidAttrNumber) if (nameAttnum != InvalidAttrNumber)
{ {
Datum nameDatum; Datum nameDatum;
nameDatum = heap_getattr(objtup, nameAttnum, nameDatum = heap_getattr(objtup, nameAttnum,
RelationGetDescr(catalog), &isnull); RelationGetDescr(catalog), &isnull);
if (isnull) if (isnull)
elog(ERROR, "invalid null name in object %u/%u/%d", elog(ERROR, "invalid null name in object %u/%u/%d",
address.classId, address.objectId, address.objectSubId); address.classId, address.objectId, address.objectSubId);
@ -2389,7 +2390,7 @@ pg_identify_object(PG_FUNCTION_ARGS)
/* schema name */ /* schema name */
if (OidIsValid(schema_oid)) if (OidIsValid(schema_oid))
{ {
const char *schema = quote_identifier(get_namespace_name(schema_oid)); const char *schema = quote_identifier(get_namespace_name(schema_oid));
values[1] = CStringGetTextDatum(schema); values[1] = CStringGetTextDatum(schema);
nulls[1] = false; nulls[1] = false;
@ -2622,7 +2623,7 @@ getConstraintTypeDescription(StringInfo buffer, Oid constroid)
{ {
Relation constrRel; Relation constrRel;
HeapTuple constrTup; HeapTuple constrTup;
Form_pg_constraint constrForm; Form_pg_constraint constrForm;
constrRel = heap_open(ConstraintRelationId, AccessShareLock); constrRel = heap_open(ConstraintRelationId, AccessShareLock);
constrTup = get_catalog_object_by_oid(constrRel, constroid); constrTup = get_catalog_object_by_oid(constrRel, constroid);
@ -2651,7 +2652,7 @@ getProcedureTypeDescription(StringInfo buffer, Oid procid)
Form_pg_proc procForm; Form_pg_proc procForm;
procTup = SearchSysCache1(PROCOID, procTup = SearchSysCache1(PROCOID,
ObjectIdGetDatum(procid)); ObjectIdGetDatum(procid));
if (!HeapTupleIsValid(procTup)) if (!HeapTupleIsValid(procTup))
elog(ERROR, "cache lookup failed for procedure %u", procid); elog(ERROR, "cache lookup failed for procedure %u", procid);
procForm = (Form_pg_proc) GETSTRUCT(procTup); procForm = (Form_pg_proc) GETSTRUCT(procTup);
@ -2683,7 +2684,7 @@ getObjectIdentity(const ObjectAddress *object)
getRelationIdentity(&buffer, object->objectId); getRelationIdentity(&buffer, object->objectId);
if (object->objectSubId != 0) if (object->objectSubId != 0)
{ {
char *attr; char *attr;
attr = get_relid_attribute_name(object->objectId, attr = get_relid_attribute_name(object->objectId,
object->objectSubId); object->objectSubId);
@ -2718,8 +2719,8 @@ getObjectIdentity(const ObjectAddress *object)
castForm = (Form_pg_cast) GETSTRUCT(tup); castForm = (Form_pg_cast) GETSTRUCT(tup);
appendStringInfo(&buffer, "(%s AS %s)", appendStringInfo(&buffer, "(%s AS %s)",
format_type_be_qualified(castForm->castsource), format_type_be_qualified(castForm->castsource),
format_type_be_qualified(castForm->casttarget)); format_type_be_qualified(castForm->casttarget));
heap_close(castRel, AccessShareLock); heap_close(castRel, AccessShareLock);
break; break;
@ -2729,7 +2730,7 @@ getObjectIdentity(const ObjectAddress *object)
{ {
HeapTuple collTup; HeapTuple collTup;
Form_pg_collation coll; Form_pg_collation coll;
char *schema; char *schema;
collTup = SearchSysCache1(COLLOID, collTup = SearchSysCache1(COLLOID,
ObjectIdGetDatum(object->objectId)); ObjectIdGetDatum(object->objectId));
@ -2740,7 +2741,7 @@ getObjectIdentity(const ObjectAddress *object)
schema = get_namespace_name(coll->collnamespace); schema = get_namespace_name(coll->collnamespace);
appendStringInfoString(&buffer, appendStringInfoString(&buffer,
quote_qualified_identifier(schema, quote_qualified_identifier(schema,
NameStr(coll->collname))); NameStr(coll->collname)));
ReleaseSysCache(collTup); ReleaseSysCache(collTup);
break; break;
} }
@ -2765,7 +2766,7 @@ getObjectIdentity(const ObjectAddress *object)
} }
else else
{ {
ObjectAddress domain; ObjectAddress domain;
domain.classId = TypeRelationId; domain.classId = TypeRelationId;
domain.objectId = con->contypid; domain.objectId = con->contypid;
@ -2849,7 +2850,7 @@ getObjectIdentity(const ObjectAddress *object)
object->objectId); object->objectId);
langForm = (Form_pg_language) GETSTRUCT(langTup); langForm = (Form_pg_language) GETSTRUCT(langTup);
appendStringInfo(&buffer, "%s", appendStringInfo(&buffer, "%s",
quote_identifier(NameStr(langForm->lanname))); quote_identifier(NameStr(langForm->lanname)));
ReleaseSysCache(langTup); ReleaseSysCache(langTup);
break; break;
} }
@ -2889,7 +2890,7 @@ getObjectIdentity(const ObjectAddress *object)
appendStringInfo(&buffer, appendStringInfo(&buffer,
"%s", "%s",
quote_qualified_identifier(schema, quote_qualified_identifier(schema,
NameStr(opcForm->opcname))); NameStr(opcForm->opcname)));
appendStringInfo(&buffer, " for %s", appendStringInfo(&buffer, " for %s",
quote_identifier(NameStr(amForm->amname))); quote_identifier(NameStr(amForm->amname)));
@ -2935,8 +2936,8 @@ getObjectIdentity(const ObjectAddress *object)
appendStringInfo(&buffer, "operator %d (%s, %s) of %s", appendStringInfo(&buffer, "operator %d (%s, %s) of %s",
amopForm->amopstrategy, amopForm->amopstrategy,
format_type_be_qualified(amopForm->amoplefttype), format_type_be_qualified(amopForm->amoplefttype),
format_type_be_qualified(amopForm->amoprighttype), format_type_be_qualified(amopForm->amoprighttype),
opfam.data); opfam.data);
pfree(opfam.data); pfree(opfam.data);
@ -2979,8 +2980,8 @@ getObjectIdentity(const ObjectAddress *object)
appendStringInfo(&buffer, "function %d (%s, %s) of %s", appendStringInfo(&buffer, "function %d (%s, %s) of %s",
amprocForm->amprocnum, amprocForm->amprocnum,
format_type_be_qualified(amprocForm->amproclefttype), format_type_be_qualified(amprocForm->amproclefttype),
format_type_be_qualified(amprocForm->amprocrighttype), format_type_be_qualified(amprocForm->amprocrighttype),
opfam.data); opfam.data);
pfree(opfam.data); pfree(opfam.data);
@ -3054,7 +3055,7 @@ getObjectIdentity(const ObjectAddress *object)
case OCLASS_TSPARSER: case OCLASS_TSPARSER:
{ {
HeapTuple tup; HeapTuple tup;
Form_pg_ts_parser formParser; Form_pg_ts_parser formParser;
tup = SearchSysCache1(TSPARSEROID, tup = SearchSysCache1(TSPARSEROID,
ObjectIdGetDatum(object->objectId)); ObjectIdGetDatum(object->objectId));
@ -3063,7 +3064,7 @@ getObjectIdentity(const ObjectAddress *object)
object->objectId); object->objectId);
formParser = (Form_pg_ts_parser) GETSTRUCT(tup); formParser = (Form_pg_ts_parser) GETSTRUCT(tup);
appendStringInfo(&buffer, "%s", appendStringInfo(&buffer, "%s",
quote_identifier(NameStr(formParser->prsname))); quote_identifier(NameStr(formParser->prsname)));
ReleaseSysCache(tup); ReleaseSysCache(tup);
break; break;
} }
@ -3071,7 +3072,7 @@ getObjectIdentity(const ObjectAddress *object)
case OCLASS_TSDICT: case OCLASS_TSDICT:
{ {
HeapTuple tup; HeapTuple tup;
Form_pg_ts_dict formDict; Form_pg_ts_dict formDict;
tup = SearchSysCache1(TSDICTOID, tup = SearchSysCache1(TSDICTOID,
ObjectIdGetDatum(object->objectId)); ObjectIdGetDatum(object->objectId));
@ -3080,7 +3081,7 @@ getObjectIdentity(const ObjectAddress *object)
object->objectId); object->objectId);
formDict = (Form_pg_ts_dict) GETSTRUCT(tup); formDict = (Form_pg_ts_dict) GETSTRUCT(tup);
appendStringInfo(&buffer, "%s", appendStringInfo(&buffer, "%s",
quote_identifier(NameStr(formDict->dictname))); quote_identifier(NameStr(formDict->dictname)));
ReleaseSysCache(tup); ReleaseSysCache(tup);
break; break;
} }
@ -3097,7 +3098,7 @@ getObjectIdentity(const ObjectAddress *object)
object->objectId); object->objectId);
formTmpl = (Form_pg_ts_template) GETSTRUCT(tup); formTmpl = (Form_pg_ts_template) GETSTRUCT(tup);
appendStringInfo(&buffer, "%s", appendStringInfo(&buffer, "%s",
quote_identifier(NameStr(formTmpl->tmplname))); quote_identifier(NameStr(formTmpl->tmplname)));
ReleaseSysCache(tup); ReleaseSysCache(tup);
break; break;
} }
@ -3121,7 +3122,7 @@ getObjectIdentity(const ObjectAddress *object)
case OCLASS_ROLE: case OCLASS_ROLE:
{ {
char *username; char *username;
username = GetUserNameFromId(object->objectId); username = GetUserNameFromId(object->objectId);
appendStringInfo(&buffer, "%s", appendStringInfo(&buffer, "%s",
@ -3229,11 +3230,11 @@ getObjectIdentity(const ObjectAddress *object)
appendStringInfo(&buffer, appendStringInfo(&buffer,
"for role %s", "for role %s",
quote_identifier(GetUserNameFromId(defacl->defaclrole))); quote_identifier(GetUserNameFromId(defacl->defaclrole)));
if (OidIsValid(defacl->defaclnamespace)) if (OidIsValid(defacl->defaclnamespace))
{ {
char *schema; char *schema;
schema = get_namespace_name(defacl->defaclnamespace); schema = get_namespace_name(defacl->defaclnamespace);
appendStringInfo(&buffer, appendStringInfo(&buffer,
@ -3291,7 +3292,7 @@ getObjectIdentity(const ObjectAddress *object)
object->objectId); object->objectId);
trigForm = (Form_pg_event_trigger) GETSTRUCT(tup); trigForm = (Form_pg_event_trigger) GETSTRUCT(tup);
appendStringInfo(&buffer, "%s", appendStringInfo(&buffer, "%s",
quote_identifier(NameStr(trigForm->evtname))); quote_identifier(NameStr(trigForm->evtname)));
ReleaseSysCache(tup); ReleaseSysCache(tup);
break; break;
} }

View File

@ -682,7 +682,7 @@ RenameConstraintById(Oid conId, const char *newname)
*/ */
void void
AlterConstraintNamespaces(Oid ownerId, Oid oldNspId, AlterConstraintNamespaces(Oid ownerId, Oid oldNspId,
Oid newNspId, bool isType, ObjectAddresses *objsMoved) Oid newNspId, bool isType, ObjectAddresses *objsMoved)
{ {
Relation conRel; Relation conRel;
ScanKeyData key[1]; ScanKeyData key[1];
@ -715,7 +715,7 @@ AlterConstraintNamespaces(Oid ownerId, Oid oldNspId,
while (HeapTupleIsValid((tup = systable_getnext(scan)))) while (HeapTupleIsValid((tup = systable_getnext(scan))))
{ {
Form_pg_constraint conform = (Form_pg_constraint) GETSTRUCT(tup); Form_pg_constraint conform = (Form_pg_constraint) GETSTRUCT(tup);
ObjectAddress thisobj; ObjectAddress thisobj;
thisobj.classId = ConstraintRelationId; thisobj.classId = ConstraintRelationId;
thisobj.objectId = HeapTupleGetOid(tup); thisobj.objectId = HeapTupleGetOid(tup);

View File

@ -180,7 +180,7 @@ AddEnumLabel(Oid enumTypeOid,
const char *newVal, const char *newVal,
const char *neighbor, const char *neighbor,
bool newValIsAfter, bool newValIsAfter,
bool skipIfExists) bool skipIfExists)
{ {
Relation pg_enum; Relation pg_enum;
Oid newOid; Oid newOid;

View File

@ -92,11 +92,11 @@ validOperatorName(const char *name)
return false; return false;
/* /*
* For SQL standard compatibility, '+' and '-' cannot be the last char of a * For SQL standard compatibility, '+' and '-' cannot be the last char of
* multi-char operator unless the operator contains chars that are not in * a multi-char operator unless the operator contains chars that are not
* SQL operators. The idea is to lex '=-' as two operators, but not to * in SQL operators. The idea is to lex '=-' as two operators, but not to
* forbid operator names like '?-' that could not be sequences of standard SQL * forbid operator names like '?-' that could not be sequences of standard
* operators. * SQL operators.
*/ */
if (len > 1 && if (len > 1 &&
(name[len - 1] == '+' || (name[len - 1] == '+' ||

View File

@ -406,7 +406,7 @@ ProcedureCreate(const char *procedureName,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("cannot change return type of existing function"), errmsg("cannot change return type of existing function"),
errhint("Use DROP FUNCTION %s first.", errhint("Use DROP FUNCTION %s first.",
format_procedure(HeapTupleGetOid(oldtup))))); format_procedure(HeapTupleGetOid(oldtup)))));
/* /*
* If it returns RECORD, check for possible change of record type * If it returns RECORD, check for possible change of record type
@ -430,7 +430,7 @@ ProcedureCreate(const char *procedureName,
errmsg("cannot change return type of existing function"), errmsg("cannot change return type of existing function"),
errdetail("Row type defined by OUT parameters is different."), errdetail("Row type defined by OUT parameters is different."),
errhint("Use DROP FUNCTION %s first.", errhint("Use DROP FUNCTION %s first.",
format_procedure(HeapTupleGetOid(oldtup))))); format_procedure(HeapTupleGetOid(oldtup)))));
} }
/* /*
@ -473,7 +473,7 @@ ProcedureCreate(const char *procedureName,
errmsg("cannot change name of input parameter \"%s\"", errmsg("cannot change name of input parameter \"%s\"",
old_arg_names[j]), old_arg_names[j]),
errhint("Use DROP FUNCTION %s first.", errhint("Use DROP FUNCTION %s first.",
format_procedure(HeapTupleGetOid(oldtup))))); format_procedure(HeapTupleGetOid(oldtup)))));
} }
} }
@ -497,7 +497,7 @@ ProcedureCreate(const char *procedureName,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("cannot remove parameter defaults from existing function"), errmsg("cannot remove parameter defaults from existing function"),
errhint("Use DROP FUNCTION %s first.", errhint("Use DROP FUNCTION %s first.",
format_procedure(HeapTupleGetOid(oldtup))))); format_procedure(HeapTupleGetOid(oldtup)))));
proargdefaults = SysCacheGetAttr(PROCNAMEARGSNSP, oldtup, proargdefaults = SysCacheGetAttr(PROCNAMEARGSNSP, oldtup,
Anum_pg_proc_proargdefaults, Anum_pg_proc_proargdefaults,
@ -524,7 +524,7 @@ ProcedureCreate(const char *procedureName,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("cannot change data type of existing parameter default value"), errmsg("cannot change data type of existing parameter default value"),
errhint("Use DROP FUNCTION %s first.", errhint("Use DROP FUNCTION %s first.",
format_procedure(HeapTupleGetOid(oldtup))))); format_procedure(HeapTupleGetOid(oldtup)))));
newlc = lnext(newlc); newlc = lnext(newlc);
} }
} }

View File

@ -1382,7 +1382,7 @@ shdepReassignOwned(List *roleids, Oid newrole)
AlterEventTriggerOwner_oid(sdepForm->objid, newrole); AlterEventTriggerOwner_oid(sdepForm->objid, newrole);
break; break;
/* Generic alter owner cases */ /* Generic alter owner cases */
case CollationRelationId: case CollationRelationId:
case ConversionRelationId: case ConversionRelationId:
case OperatorRelationId: case OperatorRelationId:

View File

@ -505,13 +505,12 @@ smgr_redo(XLogRecPtr lsn, XLogRecord *record)
smgrcreate(reln, MAIN_FORKNUM, true); smgrcreate(reln, MAIN_FORKNUM, true);
/* /*
* Before we perform the truncation, update minimum recovery point * Before we perform the truncation, update minimum recovery point to
* to cover this WAL record. Once the relation is truncated, there's * cover this WAL record. Once the relation is truncated, there's no
* no going back. The buffer manager enforces the WAL-first rule * going back. The buffer manager enforces the WAL-first rule for
* for normal updates to relation files, so that the minimum recovery * normal updates to relation files, so that the minimum recovery
* point is always updated before the corresponding change in the * point is always updated before the corresponding change in the data
* data file is flushed to disk. We have to do the same manually * file is flushed to disk. We have to do the same manually here.
* here.
* *
* Doing this before the truncation means that if the truncation fails * Doing this before the truncation means that if the truncation fails
* for some reason, you cannot start up the system even after restart, * for some reason, you cannot start up the system even after restart,

View File

@ -217,13 +217,13 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters)
/* /*
* Most of the argument-checking is done inside of AggregateCreate * Most of the argument-checking is done inside of AggregateCreate
*/ */
return AggregateCreate(aggName, /* aggregate name */ return AggregateCreate(aggName, /* aggregate name */
aggNamespace, /* namespace */ aggNamespace, /* namespace */
aggArgTypes, /* input data type(s) */ aggArgTypes, /* input data type(s) */
numArgs, numArgs,
transfuncName, /* step function name */ transfuncName, /* step function name */
finalfuncName, /* final function name */ finalfuncName, /* final function name */
sortoperatorName, /* sort operator name */ sortoperatorName, /* sort operator name */
transTypeId, /* transition data type */ transTypeId, /* transition data type */
initval); /* initial condition */ initval); /* initial condition */
} }

View File

@ -62,7 +62,7 @@
#include "utils/tqual.h" #include "utils/tqual.h"
static Oid AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid); static Oid AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid);
/* /*
* Raise an error to the effect that an object of the given name is already * Raise an error to the effect that an object of the given name is already
@ -71,7 +71,7 @@ static Oid AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid);
static void static void
report_name_conflict(Oid classId, const char *name) report_name_conflict(Oid classId, const char *name)
{ {
char *msgfmt; char *msgfmt;
switch (classId) switch (classId)
{ {
@ -100,7 +100,7 @@ report_name_conflict(Oid classId, const char *name)
static void static void
report_namespace_conflict(Oid classId, const char *name, Oid nspOid) report_namespace_conflict(Oid classId, const char *name, Oid nspOid)
{ {
char *msgfmt; char *msgfmt;
Assert(OidIsValid(nspOid)); Assert(OidIsValid(nspOid));
@ -221,10 +221,10 @@ AlterObjectRename_internal(Relation rel, Oid objectId, const char *new_name)
} }
/* /*
* Check for duplicate name (more friendly than unique-index failure). * Check for duplicate name (more friendly than unique-index failure).
* Since this is just a friendliness check, we can just skip it in cases * Since this is just a friendliness check, we can just skip it in cases
* where there isn't suitable support. * where there isn't suitable support.
*/ */
if (classId == ProcedureRelationId) if (classId == ProcedureRelationId)
{ {
Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(oldtup); Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(oldtup);
@ -355,9 +355,9 @@ ExecRenameStmt(RenameStmt *stmt)
case OBJECT_TSPARSER: case OBJECT_TSPARSER:
case OBJECT_TSTEMPLATE: case OBJECT_TSTEMPLATE:
{ {
ObjectAddress address; ObjectAddress address;
Relation catalog; Relation catalog;
Relation relation; Relation relation;
address = get_object_address(stmt->renameType, address = get_object_address(stmt->renameType,
stmt->object, stmt->objarg, stmt->object, stmt->objarg,
@ -377,7 +377,7 @@ ExecRenameStmt(RenameStmt *stmt)
default: default:
elog(ERROR, "unrecognized rename stmt type: %d", elog(ERROR, "unrecognized rename stmt type: %d",
(int) stmt->renameType); (int) stmt->renameType);
return InvalidOid; /* keep compiler happy */ return InvalidOid; /* keep compiler happy */
} }
} }
@ -699,7 +699,7 @@ ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
return AlterEventTriggerOwner(strVal(linitial(stmt->object)), return AlterEventTriggerOwner(strVal(linitial(stmt->object)),
newowner); newowner);
/* Generic cases */ /* Generic cases */
case OBJECT_AGGREGATE: case OBJECT_AGGREGATE:
case OBJECT_COLLATION: case OBJECT_COLLATION:
case OBJECT_CONVERSION: case OBJECT_CONVERSION:
@ -716,7 +716,7 @@ ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
Relation catalog; Relation catalog;
Relation relation; Relation relation;
Oid classId; Oid classId;
ObjectAddress address; ObjectAddress address;
address = get_object_address(stmt->objectType, address = get_object_address(stmt->objectType,
stmt->object, stmt->object,
@ -804,13 +804,13 @@ AlterObjectOwner_internal(Relation rel, Oid objectId, Oid new_ownerId)
/* Superusers can bypass permission checks */ /* Superusers can bypass permission checks */
if (!superuser()) if (!superuser())
{ {
AclObjectKind aclkind = get_object_aclkind(classId); AclObjectKind aclkind = get_object_aclkind(classId);
/* must be owner */ /* must be owner */
if (!has_privs_of_role(GetUserId(), old_ownerId)) if (!has_privs_of_role(GetUserId(), old_ownerId))
{ {
char *objname; char *objname;
char namebuf[NAMEDATALEN]; char namebuf[NAMEDATALEN];
if (Anum_name != InvalidAttrNumber) if (Anum_name != InvalidAttrNumber)
{ {
@ -833,7 +833,7 @@ AlterObjectOwner_internal(Relation rel, Oid objectId, Oid new_ownerId)
/* New owner must have CREATE privilege on namespace */ /* New owner must have CREATE privilege on namespace */
if (OidIsValid(namespaceId)) if (OidIsValid(namespaceId))
{ {
AclResult aclresult; AclResult aclresult;
aclresult = pg_namespace_aclcheck(namespaceId, new_ownerId, aclresult = pg_namespace_aclcheck(namespaceId, new_ownerId,
ACL_CREATE); ACL_CREATE);
@ -861,7 +861,7 @@ AlterObjectOwner_internal(Relation rel, Oid objectId, Oid new_ownerId)
Anum_acl, RelationGetDescr(rel), &isnull); Anum_acl, RelationGetDescr(rel), &isnull);
if (!isnull) if (!isnull)
{ {
Acl *newAcl; Acl *newAcl;
newAcl = aclnewowner(DatumGetAclP(datum), newAcl = aclnewowner(DatumGetAclP(datum),
old_ownerId, new_ownerId); old_ownerId, new_ownerId);

View File

@ -1147,7 +1147,7 @@ asyncQueueUnregister(void)
Assert(listenChannels == NIL); /* else caller error */ Assert(listenChannels == NIL); /* else caller error */
if (!amRegisteredListener) /* nothing to do */ if (!amRegisteredListener) /* nothing to do */
return; return;
LWLockAcquire(AsyncQueueLock, LW_SHARED); LWLockAcquire(AsyncQueueLock, LW_SHARED);
@ -1519,7 +1519,7 @@ AtAbort_Notify(void)
/* /*
* If we LISTEN but then roll back the transaction after PreCommit_Notify, * If we LISTEN but then roll back the transaction after PreCommit_Notify,
* we have registered as a listener but have not made any entry in * we have registered as a listener but have not made any entry in
* listenChannels. In that case, deregister again. * listenChannels. In that case, deregister again.
*/ */
if (amRegisteredListener && listenChannels == NIL) if (amRegisteredListener && listenChannels == NIL)
asyncQueueUnregister(); asyncQueueUnregister();

Some files were not shown because too many files have changed in this diff Show More