Datum country_recv(PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); const char *str = pq_getmsgstring(buf); pq_getmsgend(buf); PG_RETURN_UINT8(country_from_str(str)); }
void ProcessGTMEndBackup(Port *myport, StringInfo message) { int ii; GTM_ThreadInfo *my_threadinfo; StringInfoData buf; pq_getmsgend(message); my_threadinfo = GetMyThreadInfo; for (ii = 0; ii < GTMThreads->gt_array_size; ii++) { if (GTMThreads->gt_threads[ii] && GTMThreads->gt_threads[ii] != my_threadinfo) GTM_RWLockRelease(>MThreads->gt_threads[ii]->thr_lock); } my_threadinfo->thr_status = GTM_THREAD_RUNNING; pq_beginmessage(&buf, 'S'); pq_sendint(&buf, END_BACKUP_RESULT, 4); pq_endmessage(myport, &buf); pq_flush(myport); }
void ProcessGTMBeginBackup(Port *myport, StringInfo message) { int ii; GTM_ThreadInfo *my_threadinfo; StringInfoData buf; pq_getmsgend(message); my_threadinfo = GetMyThreadInfo; for (ii = 0; ii < GTMThreads->gt_array_size; ii++) { if (GTMThreads->gt_threads[ii] && GTMThreads->gt_threads[ii] != my_threadinfo) GTM_RWLockAcquire(>MThreads->gt_threads[ii]->thr_lock, GTM_LOCKMODE_WRITE); } my_threadinfo->thr_status = GTM_THREAD_BACKUP; pq_beginmessage(&buf, 'S'); pq_sendint(&buf, BEGIN_BACKUP_RESULT, 4); pq_endmessage(myport, &buf); pq_flush(myport); }
/* * Execute commands from walreceiver, until we enter streaming mode. */ static void WalSndHandshake(void) { StringInfoData input_message; bool replication_started = false; initStringInfo(&input_message); while (!replication_started) { int firstchar; WalSndSetState(WALSNDSTATE_STARTUP); set_ps_display("idle", false); /* Wait for a command to arrive */ firstchar = pq_getbyte(); /* * Emergency bailout if postmaster has died. This is to avoid the * necessity for manual cleanup of all postmaster children. */ if (!PostmasterIsAlive()) exit(1); /* * Check for any other interesting events that happened while we * slept. */ if (got_SIGHUP) { got_SIGHUP = false; ProcessConfigFile(PGC_SIGHUP); } if (firstchar != EOF) { /* * Read the message contents. This is expected to be done without * blocking because we've been able to get message type code. */ if (pq_getmessage(&input_message, 0)) firstchar = EOF; /* suitable message already logged */ } /* Handle the very limited subset of commands expected in this phase */ switch (firstchar) { case 'Q': /* Query message */ { const char *query_string; query_string = pq_getmsgstring(&input_message); pq_getmsgend(&input_message); if (HandleReplicationCommand(query_string)) replication_started = true; } break; case 'X': /* standby is closing the connection */ proc_exit(0); case EOF: /* standby disconnected unexpectedly */ ereport(COMMERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("unexpected EOF on standby connection"))); proc_exit(0); default: ereport(FATAL, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("invalid standby handshake message type %d", firstchar))); } } }
/* * Parse an ErrorResponse or NoticeResponse payload and populate an ErrorData * structure with the results. */ void pq_parse_errornotice(StringInfo msg, ErrorData *edata) { /* Initialize edata with reasonable defaults. */ MemSet(edata, 0, sizeof(ErrorData)); edata->elevel = ERROR; edata->assoc_context = CurrentMemoryContext; /* Loop over fields and extract each one. */ for (;;) { char code = pq_getmsgbyte(msg); const char *value; if (code == '\0') { pq_getmsgend(msg); break; } value = pq_getmsgstring(msg); switch (code) { case PG_DIAG_SEVERITY: if (strcmp(value, "DEBUG") == 0) edata->elevel = DEBUG1; /* or some other DEBUG level */ else if (strcmp(value, "LOG") == 0) edata->elevel = LOG; /* can't be COMMERROR */ else if (strcmp(value, "INFO") == 0) edata->elevel = INFO; else if (strcmp(value, "NOTICE") == 0) edata->elevel = NOTICE; else if (strcmp(value, "WARNING") == 0) edata->elevel = WARNING; else if (strcmp(value, "ERROR") == 0) edata->elevel = ERROR; else if (strcmp(value, "FATAL") == 0) edata->elevel = FATAL; else if (strcmp(value, "PANIC") == 0) edata->elevel = PANIC; else elog(ERROR, "unknown error severity"); break; case PG_DIAG_SQLSTATE: if (strlen(value) != 5) elog(ERROR, "malformed sql state"); edata->sqlerrcode = MAKE_SQLSTATE(value[0], value[1], value[2], value[3], value[4]); break; case PG_DIAG_MESSAGE_PRIMARY: edata->message = pstrdup(value); break; case PG_DIAG_MESSAGE_DETAIL: edata->detail = pstrdup(value); break; case PG_DIAG_MESSAGE_HINT: edata->hint = pstrdup(value); break; case PG_DIAG_STATEMENT_POSITION: edata->cursorpos = pg_atoi(value, sizeof(int), '\0'); break; case PG_DIAG_INTERNAL_POSITION: edata->internalpos = pg_atoi(value, sizeof(int), '\0'); break; case PG_DIAG_INTERNAL_QUERY: edata->internalquery = pstrdup(value); break; case PG_DIAG_CONTEXT: edata->context = pstrdup(value); break; case PG_DIAG_SCHEMA_NAME: edata->schema_name = pstrdup(value); break; case PG_DIAG_TABLE_NAME: edata->table_name = pstrdup(value); break; case PG_DIAG_COLUMN_NAME: edata->column_name = pstrdup(value); break; case PG_DIAG_DATATYPE_NAME: edata->datatype_name = pstrdup(value); break; case PG_DIAG_CONSTRAINT_NAME: edata->constraint_name = pstrdup(value); break; case PG_DIAG_SOURCE_FILE: edata->filename = pstrdup(value); break; case PG_DIAG_SOURCE_LINE: edata->lineno = pg_atoi(value, sizeof(int), '\0'); break; case PG_DIAG_SOURCE_FUNCTION: edata->funcname = pstrdup(value); break; default: elog(ERROR, "unknown error field: %d", (int) code); break; } } }
/* * Execute commands from walreceiver, until we enter streaming mode. */ static void WalSndHandshake(void) { StringInfoData input_message; bool replication_started = false; initStringInfo(&input_message); while (!replication_started) { int firstchar; /* Wait for a command to arrive */ firstchar = pq_getbyte(); /* * Emergency bailout if postmaster has died. This is to avoid the * necessity for manual cleanup of all postmaster children. */ if (!PostmasterIsAlive(true)) exit(1); /* * Check for any other interesting events that happened while we * slept. */ if (got_SIGHUP) { got_SIGHUP = false; ProcessConfigFile(PGC_SIGHUP); } if (firstchar != EOF) { /* * Read the message contents. This is expected to be done without * blocking because we've been able to get message type code. */ if (pq_getmessage(&input_message, 0)) firstchar = EOF; /* suitable message already logged */ } /* Handle the very limited subset of commands expected in this phase */ switch (firstchar) { case 'Q': /* Query message */ { const char *query_string; XLogRecPtr recptr; query_string = pq_getmsgstring(&input_message); pq_getmsgend(&input_message); if (strcmp(query_string, "IDENTIFY_SYSTEM") == 0) { StringInfoData buf; char sysid[32]; char tli[11]; /* * Reply with a result set with one row, two columns. * First col is system ID, and second is timeline ID */ snprintf(sysid, sizeof(sysid), UINT64_FORMAT, GetSystemIdentifier()); snprintf(tli, sizeof(tli), "%u", ThisTimeLineID); /* Send a RowDescription message */ pq_beginmessage(&buf, 'T'); pq_sendint(&buf, 2, 2); /* 2 fields */ /* first field */ pq_sendstring(&buf, "systemid"); /* col name */ pq_sendint(&buf, 0, 4); /* table oid */ pq_sendint(&buf, 0, 2); /* attnum */ pq_sendint(&buf, TEXTOID, 4); /* type oid */ pq_sendint(&buf, -1, 2); /* typlen */ pq_sendint(&buf, 0, 4); /* typmod */ pq_sendint(&buf, 0, 2); /* format code */ /* second field */ pq_sendstring(&buf, "timeline"); /* col name */ pq_sendint(&buf, 0, 4); /* table oid */ pq_sendint(&buf, 0, 2); /* attnum */ pq_sendint(&buf, INT4OID, 4); /* type oid */ pq_sendint(&buf, 4, 2); /* typlen */ pq_sendint(&buf, 0, 4); /* typmod */ pq_sendint(&buf, 0, 2); /* format code */ pq_endmessage(&buf); /* Send a DataRow message */ pq_beginmessage(&buf, 'D'); pq_sendint(&buf, 2, 2); /* # of columns */ pq_sendint(&buf, strlen(sysid), 4); /* col1 len */ pq_sendbytes(&buf, (char *) &sysid, strlen(sysid)); pq_sendint(&buf, strlen(tli), 4); /* col2 len */ pq_sendbytes(&buf, (char *) tli, strlen(tli)); pq_endmessage(&buf); /* Send CommandComplete and ReadyForQuery messages */ EndCommand("SELECT", DestRemote); ReadyForQuery(DestRemote); /* ReadyForQuery did pq_flush for us */ } else if (sscanf(query_string, "START_REPLICATION %X/%X", &recptr.xlogid, &recptr.xrecoff) == 2) { StringInfoData buf; /* * Check that we're logging enough information in the * WAL for log-shipping. * * NOTE: This only checks the current value of * wal_level. Even if the current setting is not * 'minimal', there can be old WAL in the pg_xlog * directory that was created with 'minimal'. So this * is not bulletproof, the purpose is just to give a * user-friendly error message that hints how to * configure the system correctly. */ if (wal_level == WAL_LEVEL_MINIMAL) ereport(FATAL, (errcode(ERRCODE_CANNOT_CONNECT_NOW), errmsg("standby connections not allowed because wal_level=minimal"))); /* Send a CopyOutResponse message, and start streaming */ pq_beginmessage(&buf, 'H'); pq_sendbyte(&buf, 0); pq_sendint(&buf, 0, 2); pq_endmessage(&buf); pq_flush(); /* * Initialize position to the received one, then the * xlog records begin to be shipped from that position */ sentPtr = recptr; /* break out of the loop */ replication_started = true; } else { ereport(FATAL, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("invalid standby query string: %s", query_string))); } break; } case 'X': /* standby is closing the connection */ proc_exit(0); case EOF: /* standby disconnected unexpectedly */ ereport(COMMERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("unexpected EOF on standby connection"))); proc_exit(0); default: ereport(FATAL, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("invalid standby handshake message type %d", firstchar))); } } }
/* * Parse an ErrorResponse or NoticeResponse payload and populate an ErrorData * structure with the results. */ void pq_parse_errornotice(StringInfo msg, ErrorData *edata) { /* Initialize edata with reasonable defaults. */ MemSet(edata, 0, sizeof(ErrorData)); edata->elevel = ERROR; edata->assoc_context = CurrentMemoryContext; /* Loop over fields and extract each one. */ for (;;) { char code = pq_getmsgbyte(msg); const char *value; if (code == '\0') { pq_getmsgend(msg); break; } value = pq_getmsgrawstring(msg); switch (code) { case PG_DIAG_SEVERITY: /* ignore, trusting we'll get a nonlocalized version */ break; case PG_DIAG_SEVERITY_NONLOCALIZED: if (strcmp(value, "DEBUG") == 0) { /* * We can't reconstruct the exact DEBUG level, but * presumably it was >= client_min_messages, so select * DEBUG1 to ensure we'll pass it on to the client. */ edata->elevel = DEBUG1; } else if (strcmp(value, "LOG") == 0) { /* * It can't be LOG_SERVER_ONLY, or the worker wouldn't * have sent it to us; so LOG is the correct value. */ edata->elevel = LOG; } else if (strcmp(value, "INFO") == 0) edata->elevel = INFO; else if (strcmp(value, "NOTICE") == 0) edata->elevel = NOTICE; else if (strcmp(value, "WARNING") == 0) edata->elevel = WARNING; else if (strcmp(value, "ERROR") == 0) edata->elevel = ERROR; else if (strcmp(value, "FATAL") == 0) edata->elevel = FATAL; else if (strcmp(value, "PANIC") == 0) edata->elevel = PANIC; else elog(ERROR, "unrecognized error severity: \"%s\"", value); break; case PG_DIAG_SQLSTATE: if (strlen(value) != 5) elog(ERROR, "invalid SQLSTATE: \"%s\"", value); edata->sqlerrcode = MAKE_SQLSTATE(value[0], value[1], value[2], value[3], value[4]); break; case PG_DIAG_MESSAGE_PRIMARY: edata->message = pstrdup(value); break; case PG_DIAG_MESSAGE_DETAIL: edata->detail = pstrdup(value); break; case PG_DIAG_MESSAGE_HINT: edata->hint = pstrdup(value); break; case PG_DIAG_STATEMENT_POSITION: edata->cursorpos = pg_strtoint32(value); break; case PG_DIAG_INTERNAL_POSITION: edata->internalpos = pg_strtoint32(value); break; case PG_DIAG_INTERNAL_QUERY: edata->internalquery = pstrdup(value); break; case PG_DIAG_CONTEXT: edata->context = pstrdup(value); break; case PG_DIAG_SCHEMA_NAME: edata->schema_name = pstrdup(value); break; case PG_DIAG_TABLE_NAME: edata->table_name = pstrdup(value); break; case PG_DIAG_COLUMN_NAME: edata->column_name = pstrdup(value); break; case PG_DIAG_DATATYPE_NAME: edata->datatype_name = pstrdup(value); break; case PG_DIAG_CONSTRAINT_NAME: edata->constraint_name = pstrdup(value); break; case PG_DIAG_SOURCE_FILE: edata->filename = pstrdup(value); break; case PG_DIAG_SOURCE_LINE: edata->lineno = pg_strtoint32(value); break; case PG_DIAG_SOURCE_FUNCTION: edata->funcname = pstrdup(value); break; default: elog(ERROR, "unrecognized error field code: %d", (int) code); break; } } }