void RowKeyAdd(size_t i) { g_row_key = pg_realloc(g_row_key, (g_row_key_n + 1) * sizeof(size_t)); g_row_key[g_row_key_n] = i; g_row_key_n++; }
/* * load_directory() * * Read all the file names in the specified directory, and return them as * an array of "struct dirent" pointers. The array address is returned in * *namelist, and the function result is the count of file names. * * To free the result data, free each namelist array member, then free the * namelist array itself. */ int load_directory(const char *dirname, struct dirent *** namelist) { DIR *dirdesc; struct dirent *direntry; int count = 0; int allocsize = 64; size_t entrysize; *namelist = (struct dirent **) pg_malloc(allocsize * sizeof(struct dirent *)); if ((dirdesc = opendir(dirname)) == NULL) pg_log(PG_FATAL, "could not open directory \"%s\": %s\n", dirname, getErrorText(errno)); while (errno = 0, (direntry = readdir(dirdesc)) != NULL) { if (count >= allocsize) { allocsize *= 2; *namelist = (struct dirent **) pg_realloc(*namelist, allocsize * sizeof(struct dirent *)); } entrysize = offsetof(struct dirent, d_name) + strlen(direntry->d_name) + 1; (*namelist)[count] = (struct dirent *) pg_malloc(entrysize); memcpy((*namelist)[count], direntry, entrysize); count++; } #ifdef WIN32 /* * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in * released version */ if (GetLastError() == ERROR_NO_MORE_FILES) errno = 0; #endif if (errno) pg_log(PG_FATAL, "could not read directory \"%s\": %s\n", dirname, getErrorText(errno)); closedir(dirdesc); return count; }
/* * add_one_elt * * Add one element to a (possibly empty) eary struct. */ void add_one_elt(char *eltname, eary *eary) { if (eary->alloc == 0) { eary ->alloc = 8; eary ->array = (char **) pg_malloc(8 * sizeof(char *)); } else if (eary->num >= eary->alloc) { eary ->alloc *= 2; eary ->array = (char **) pg_realloc(eary->array, eary->alloc * sizeof(char *)); } eary ->array[eary->num] = pg_strdup(eltname); eary ->num++; }
/* * Convert the linked list of entries in map->first/last to the array, * map->array. */ static void filemap_list_to_array(filemap_t *map) { int narray; file_entry_t *entry, *next; map->array = (file_entry_t **) pg_realloc(map->array, (map->nlist + map->narray) * sizeof(file_entry_t *)); narray = map->narray; for (entry = map->first; entry != NULL; entry = next) { map->array[narray++] = entry; next = entry->next; entry->next = NULL; } Assert(narray == map->nlist + map->narray); map->narray = narray; map->nlist = 0; map->first = map->last = NULL; }
void * repalloc(void *pointer, Size size) { return pg_realloc(pointer, size); }
/* * Try to read a timeline's history file. * * If successful, return the list of component TLIs (the given TLI followed by * its ancestor TLIs). If we can't find the history file, assume that the * timeline has no parents, and return a list of just the specified timeline * ID. */ TimeLineHistoryEntry * rewind_parseTimeLineHistory(char *buffer, TimeLineID targetTLI, int *nentries) { char *fline; TimeLineHistoryEntry *entry; TimeLineHistoryEntry *entries = NULL; int nlines = 0; TimeLineID lasttli = 0; XLogRecPtr prevend; char *bufptr; bool lastline = false; /* * Parse the file... */ prevend = InvalidXLogRecPtr; bufptr = buffer; while (!lastline) { char *ptr; TimeLineID tli; uint32 switchpoint_hi; uint32 switchpoint_lo; int nfields; fline = bufptr; while (*bufptr && *bufptr != '\n') bufptr++; if (!(*bufptr)) lastline = true; else *bufptr++ = '\0'; /* skip leading whitespace and check for # comment */ for (ptr = fline; *ptr; ptr++) { if (!isspace((unsigned char) *ptr)) break; } if (*ptr == '\0' || *ptr == '#') continue; nfields = sscanf(fline, "%u\t%X/%X", &tli, &switchpoint_hi, &switchpoint_lo); if (nfields < 1) { /* expect a numeric timeline ID as first field of line */ fprintf(stderr, _("syntax error in history file: %s\n"), fline); fprintf(stderr, _("Expected a numeric timeline ID.\n")); exit(1); } if (nfields != 3) { fprintf(stderr, _("syntax error in history file: %s\n"), fline); fprintf(stderr, _("Expected a write-ahead log switchpoint location.\n")); exit(1); } if (entries && tli <= lasttli) { fprintf(stderr, _("invalid data in history file: %s\n"), fline); fprintf(stderr, _("Timeline IDs must be in increasing sequence.\n")); exit(1); } lasttli = tli; nlines++; entries = pg_realloc(entries, nlines * sizeof(TimeLineHistoryEntry)); entry = &entries[nlines - 1]; entry->tli = tli; entry->begin = prevend; entry->end = ((uint64) (switchpoint_hi)) << 32 | (uint64) switchpoint_lo; prevend = entry->end; /* we ignore the remainder of each line */ } if (entries && targetTLI <= lasttli) { fprintf(stderr, _("invalid data in history file\n")); fprintf(stderr, _("Timeline IDs must be less than child timeline's ID.\n")); exit(1); } /* * Create one more entry for the "tip" of the timeline, which has no entry * in the history file. */ nlines++; if (entries) entries = pg_realloc(entries, nlines * sizeof(TimeLineHistoryEntry)); else entries = pg_malloc(1 * sizeof(TimeLineHistoryEntry)); entry = &entries[nlines - 1]; entry->tli = targetTLI; entry->begin = prevend; entry->end = InvalidXLogRecPtr; *nentries = nlines; return entries; }
/* * Parse "arg", which is a string of column IDs separated by "separator". * * Each column ID can be: * - a number from 1 to PQnfields(res) * - an unquoted column name matching (case insensitively) one of PQfname(res,...) * - a quoted column name matching (case sensitively) one of PQfname(res,...) * * If max_columns > 0, it is the max number of column IDs allowed. * * On success, return number of column IDs found (possibly 0), and return a * malloc'd array of the matching column numbers of "res" into *col_numbers. * * On failure, return -1 and set *col_numbers to NULL. */ static int parseColumnRefs(const char *arg, const PGresult *res, int **col_numbers, int max_columns, char separator) { const char *p = arg; char c; int num_cols = 0; *col_numbers = NULL; while ((c = *p) != '\0') { const char *field_start = p; bool quoted_field = false; /* first char */ if (c == '"') { quoted_field = true; p++; } while ((c = *p) != '\0') { if (c == separator && !quoted_field) break; if (c == '"') /* end of field or embedded double quote */ { p++; if (*p == '"') { if (quoted_field) { p++; continue; } } else if (quoted_field && *p == separator) break; } if (*p) p += PQmblen(p, pset.encoding); } if (p != field_start) { char *col_name; int col_num; /* enforce max_columns limit */ if (max_columns > 0 && num_cols == max_columns) { psql_error(_("No more than %d column references expected\n"), max_columns); goto errfail; } /* look up the column and add its index into *col_numbers */ col_name = pg_malloc(p - field_start + 1); memcpy(col_name, field_start, p - field_start); col_name[p - field_start] = '\0'; col_num = indexOfColumn(col_name, res); pg_free(col_name); if (col_num < 0) goto errfail; *col_numbers = (int *) pg_realloc(*col_numbers, (num_cols + 1) * sizeof(int)); (*col_numbers)[num_cols++] = col_num; } else { psql_error(_("Empty column reference\n")); goto errfail; } if (*p) p += PQmblen(p, pset.encoding); } return num_cols; errfail: pg_free(*col_numbers); *col_numbers = NULL; return -1; }
int main(int argc, char **argv) { int c; char *nodename = NULL; /* GTM Proxy nodename */ progname = "gtm_ctl"; /* * save argv[0] so do_start() can look for the gtm if necessary. we * don't look for gtm here because in many cases we won't need it. */ argv0 = argv[0]; umask(077); /* support --help and --version even if invoked as root */ if (argc > 1) { if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0) { do_help(); exit(0); } if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0) { puts("gtm_ctl (Postgres-XC) " PGXC_VERSION); exit(0); } } /* * Disallow running as root, to forestall any possible security holes. */ if (geteuid() == 0) { write_stderr(_("%s: cannot be run as root\n" "Please log in (using, e.g., \"su\") as the " "(unprivileged) user that will\n" "own the server process.\n"), progname); exit(1); } /* * 'Action' can be before or after args so loop over both. Some * getopt_long() implementations will reorder argv[] to place all flags * first (GNU?), but we don't rely on it. Our /port version doesn't do * that. */ optind = 1; /* process command-line options */ while (optind < argc) { while ((c = getopt(argc, argv, "D:i:l:m:o:p:t:wWZ:C:")) != -1) { switch (c) { case 'D': { char *env_var = pg_malloc(strlen(optarg) + 9); gtmdata_D = xstrdup(optarg); canonicalize_path(gtmdata_D); snprintf(env_var, strlen(optarg) + 9, "GTMDATA=%s", gtmdata_D); putenv(env_var); /* * We could pass GTMDATA just in an environment * variable but we do -D too for clearer gtm * 'ps' display */ gtmdata_opt = (char *) pg_malloc(strlen(gtmdata_D) + 8); snprintf(gtmdata_opt, strlen(gtmdata_D) + 8, "-D \"%s\" ", gtmdata_D); break; } case 'i': nodename = strdup(optarg); break; case 'l': log_file = xstrdup(optarg); break; case 'm': set_mode(optarg); break; case 'o': gtm_opts = xstrdup(optarg); break; case 'p': gtm_path = xstrdup(optarg); canonicalize_path(gtm_path); break; case 't': wait_seconds = atoi(optarg); break; case 'C': control_file = xstrdup(optarg); break; case 'w': do_wait = true; wait_set = true; break; case 'W': do_wait = false; wait_set = true; break; case 'Z': gtm_app = xstrdup(optarg); if (strcmp(gtm_app,"gtm_proxy") != 0 && strcmp(gtm_app,"gtm_standby") != 0 && strcmp(gtm_app,"gtm") != 0) { write_stderr(_("%s: %s launch name set not correct\n"), progname, gtm_app); do_advice(); exit(1); } break; default: /* getopt_long already issued a suitable error message */ do_advice(); exit(1); } } /* Process an action */ if (optind < argc) { if (ctl_command != NO_COMMAND) { write_stderr(_("%s: too many command-line arguments (first is \"%s\")\n"), progname, argv[optind]); do_advice(); exit(1); } if (strcmp(argv[optind], "start") == 0) ctl_command = START_COMMAND; else if (strcmp(argv[optind], "stop") == 0) ctl_command = STOP_COMMAND; else if (strcmp(argv[optind], "promote") == 0) ctl_command = PROMOTE_COMMAND; else if (strcmp(argv[optind], "restart") == 0) ctl_command = RESTART_COMMAND; else if (strcmp(argv[optind], "status") == 0) ctl_command = STATUS_COMMAND; else if (strcmp(argv[optind], "reconnect") == 0) ctl_command = RECONNECT_COMMAND; else { write_stderr(_("%s: unrecognized operation mode \"%s\"\n"), progname, argv[optind]); do_advice(); exit(1); } optind++; } } /* * Take care of the control file (-C Option) */ if (control_file) { char ctrl_path[MAXPGPATH+1]; char C_opt_path[MAXPGPATH+1]; char bkup_path[MAXPGPATH+1]; FILE *f1, *f2; int c; if (!gtmdata_D) { write_stderr(_("No -D option specified.\n")); exit(1); } if ((strcmp(gtm_app, "gtm") != 0) && (strcmp(gtm_app, "gtm_master") != 0)) { write_stderr(_("-C option is valid only for gtm.\n")); exit(1); } /* If there's already a control file, backup it to *.bak */ trim_last_slash(gtmdata_D); snprintf(ctrl_path, MAXPGPATH, "%s/%s", gtmdata_D, GTM_CONTROL_FILE); if ((f1 = fopen(ctrl_path, "r"))) { snprintf(bkup_path, MAXPGPATH, "%s/%s.bak", gtmdata_D, GTM_CONTROL_FILE); if (!(f2 = fopen(bkup_path, "w"))) { fclose(f1); write_stderr(_("Cannot open backup file, %s/%s.bak, %s\n"), gtmdata_D, GTM_CONTROL_FILE, strerror(errno)); exit(1); } while ((c = getc(f1)) != EOF) putc(c, f2); fclose(f1); fclose(f2); } /* Copy specified control file. */ snprintf(C_opt_path, MAXPGPATH, "%s/%s", gtmdata_D, control_file); if (!(f1 = fopen(ctrl_path, "w"))) { write_stderr(_("Cannot oopen control file, %s, %s\n"), ctrl_path, strerror(errno)); exit(1); } if (!(f2 = fopen(C_opt_path, "r"))) { fclose(f1); write_stderr(_("Cannot open -C option file, %s, %s\n"), C_opt_path, strerror(errno)); exit(1); } while ((c = getc(f2)) != EOF) putc(c, f1); fclose(f1); fclose(f2); } if (ctl_command == NO_COMMAND) { write_stderr(_("%s: no operation specified\n"), progname); do_advice(); exit(1); } gtm_data = getenv("GTMDATA"); if (gtm_data) { gtm_data = xstrdup(gtm_data); canonicalize_path(gtm_data); } if (!gtm_data) { write_stderr("%s: no GTM/GTM Proxy directory specified \n", progname); do_advice(); exit(1); } /* * pid files of gtm and gtm proxy are named differently * -Z option has also to be set for STOP_COMMAND * or gtm_ctl will not be able to find the correct pid_file */ if (!gtm_app) { write_stderr("%s: no launch option not specified\n", progname); do_advice(); exit(1); } if (strcmp(gtm_app,"gtm_proxy") != 0 && strcmp(gtm_app, "gtm_standby") != 0 && strcmp(gtm_app,"gtm") != 0) { write_stderr(_("%s: launch option incorrect\n"), progname); do_advice(); exit(1); } /* Check if GTM Proxy ID is set, this is not necessary when stopping */ if (ctl_command == START_COMMAND || ctl_command == RESTART_COMMAND) { /* Rebuild option string to include Proxy ID */ if (strcmp(gtm_app, "gtm_proxy") == 0) { gtmdata_opt = (char *) pg_realloc(gtmdata_opt, strlen(gtmdata_opt) + 9); if (nodename) sprintf(gtmdata_opt, "%s -i %s ", gtmdata_opt, nodename); else sprintf(gtmdata_opt, "%s ", gtmdata_opt); } } if (!wait_set) { switch (ctl_command) { case RESTART_COMMAND: case START_COMMAND: case PROMOTE_COMMAND: case STATUS_COMMAND: do_wait = false; break; case STOP_COMMAND: do_wait = true; break; default: break; } } /* Build strings for pid file and option file */ if (strcmp(gtm_app,"gtm_proxy") == 0) { snprintf(pid_file, MAXPGPATH, "%s/gtm_proxy.pid", gtm_data); snprintf(gtmopts_file, MAXPGPATH, "%s/gtm_proxy.opts", gtm_data); snprintf(conf_file, MAXPGPATH, "%s/gtm_proxy.conf", gtm_data); } else if (strcmp(gtm_app,"gtm") == 0) { snprintf(pid_file, MAXPGPATH, "%s/gtm.pid", gtm_data); snprintf(gtmopts_file, MAXPGPATH, "%s/gtm.opts", gtm_data); snprintf(conf_file, MAXPGPATH, "%s/gtm.conf", gtm_data); } else if (strcmp(gtm_app,"gtm_standby") == 0) { snprintf(pid_file, MAXPGPATH, "%s/gtm.pid", gtm_data); snprintf(gtmopts_file, MAXPGPATH, "%s/gtm.opts", gtm_data); snprintf(conf_file, MAXPGPATH, "%s/gtm.conf", gtm_data); } if (ctl_command==STATUS_COMMAND) gtm_opts = xstrdup("-c"); switch (ctl_command) { case START_COMMAND: do_start(); break; case STOP_COMMAND: do_stop(); break; case PROMOTE_COMMAND: do_promote(); break; case RESTART_COMMAND: do_restart(); break; case STATUS_COMMAND: do_status(); break; case RECONNECT_COMMAND: do_reconnect(); break; default: break; } exit(0); }