DeflateCompressorZlib(AH, cs, true);
if (deflateEnd(zp) != Z_OK)
- die_horribly(AH, modulename,
- "could not close compression stream: %s\n", zp->msg);
+ exit_horribly(modulename,
+ "could not close compression stream: %s\n", zp->msg);
free(cs->zlibOut);
free(cs->zp);
{
res = deflate(zp, flush ? Z_FINISH : Z_NO_FLUSH);
if (res == Z_STREAM_ERROR)
- die_horribly(AH, modulename,
- "could not compress data: %s\n", zp->msg);
+ exit_horribly(modulename,
+ "could not compress data: %s\n", zp->msg);
if ((flush && (zp->avail_out < cs->zlibOutSize))
|| (zp->avail_out == 0)
|| (zp->avail_in != 0)
size_t len = cs->zlibOutSize - zp->avail_out;
if (cs->writeF(AH, out, len) != len)
- die_horribly(AH, modulename,
- "could not write to output file: %s\n",
- strerror(errno));
+ exit_horribly(modulename,
+ "could not write to output file: %s\n",
+ strerror(errno));
}
zp->next_out = (void *) out;
zp->avail_out = cs->zlibOutSize;
/*
* we have either succeeded in writing dLen bytes or we have called
- * die_horribly()
+ * exit_horribly()
*/
return dLen;
}
res = inflate(zp, 0);
if (res != Z_OK && res != Z_STREAM_END)
- die_horribly(AH, modulename,
- "could not uncompress data: %s\n", zp->msg);
+ exit_horribly(modulename,
+ "could not uncompress data: %s\n", zp->msg);
out[ZLIB_OUT_SIZE - zp->avail_out] = '\0';
ahwrite(out, 1, ZLIB_OUT_SIZE - zp->avail_out, AH);
zp->avail_out = ZLIB_OUT_SIZE;
res = inflate(zp, 0);
if (res != Z_OK && res != Z_STREAM_END)
- die_horribly(AH, modulename,
- "could not uncompress data: %s\n", zp->msg);
+ exit_horribly(modulename,
+ "could not uncompress data: %s\n", zp->msg);
out[ZLIB_OUT_SIZE - zp->avail_out] = '\0';
ahwrite(out, 1, ZLIB_OUT_SIZE - zp->avail_out, AH);
}
if (inflateEnd(zp) != Z_OK)
- die_horribly(AH, modulename,
- "could not close compression library: %s\n", zp->msg);
+ exit_horribly(modulename,
+ "could not close compression library: %s\n", zp->msg);
free(buf);
free(out);
* do a check here as well...
*/
if (cs->writeF(AH, data, dLen) != dLen)
- die_horribly(AH, modulename,
- "could not write to output file: %s\n",
- strerror(errno));
+ exit_horribly(modulename,
+ "could not write to output file: %s\n",
+ strerror(errno));
return dLen;
}
#ifdef WIN32
static bool parallel_init_done = false;
static DWORD tls_index;
+static DWORD mainThreadId;
#endif
void
{
tls_index = TlsAlloc();
parallel_init_done = true;
+ mainThreadId = GetCurrentThreadId();
}
#endif
}
while (--on_exit_nicely_index >= 0)
(*on_exit_nicely_list[on_exit_nicely_index].function)(code,
on_exit_nicely_list[on_exit_nicely_index].arg);
+#ifdef WIN32
+ if (parallel_init_done && GetCurrentThreadId() != mainThreadId)
+ ExitThread(code);
+#endif
exit(code);
}
CATALOG_NAME = pg_dump
AVAIL_LANGUAGES = de es fr it ja ko pt_BR sv tr zh_CN zh_TW
GETTEXT_FILES = pg_dump.c common.c pg_backup_archiver.c pg_backup_custom.c \
- pg_backup_db.c pg_backup_files.c pg_backup_null.c \
+ pg_backup_db.c pg_backup_null.c \
pg_backup_tar.c pg_restore.c pg_dumpall.c \
../../port/exec.c
-GETTEXT_TRIGGERS = write_msg:2 die_horribly:3 exit_horribly:2 simple_prompt \
- ExecuteSqlCommand:3 ahlog:3
+GETTEXT_TRIGGERS = write_msg:2 exit_horribly:2 simple_prompt \
+ ExecuteSqlCommand:3 ahlog:3 warn_or_exit_horribly:3
GETTEXT_FLAGS = \
write_msg:2:c-format \
- die_horribly:3:c-format \
exit_horribly:2:c-format \
- ahlog:3:c-format
+ ahlog:3:c-format \
+ warn_or_exit_horribly:3:c-format
#define thandle HANDLE
#endif
+typedef struct ParallelStateEntry
+{
+#ifdef WIN32
+ unsigned int threadId;
+#else
+ pid_t pid;
+#endif
+ ArchiveHandle *AH;
+} ParallelStateEntry;
+
+typedef struct ParallelState
+{
+ int numWorkers;
+ ParallelStateEntry *pse;
+} ParallelState;
+
/* Arguments needed for a worker child */
typedef struct _restore_args
{
ArchiveHandle *AH;
TocEntry *te;
+ ParallelStateEntry *pse;
} RestoreArgs;
/* State for each parallel activity slot */
RestoreArgs *args;
} ParallelSlot;
+typedef struct ShutdownInformation
+{
+ ParallelState *pstate;
+ Archive *AHX;
+} ShutdownInformation;
+
+static ShutdownInformation shutdown_info;
+
#define NO_SLOT (-1)
#define TEXT_DUMP_HEADER "--\n-- PostgreSQL database dump\n--\n\n"
static int RestoringToDB(ArchiveHandle *AH);
static void dump_lo_buf(ArchiveHandle *AH);
-static void vdie_horribly(ArchiveHandle *AH, const char *modulename,
- const char *fmt, va_list ap)
- __attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 0), noreturn));
-
static void dumpTimestamp(ArchiveHandle *AH, const char *msg, time_t tim);
static void SetOutput(ArchiveHandle *AH, const char *filename, int compression);
static OutputContext SaveOutput(ArchiveHandle *AH);
static ArchiveHandle *CloneArchive(ArchiveHandle *AH);
static void DeCloneArchive(ArchiveHandle *AH);
+static void setProcessIdentifier(ParallelStateEntry *pse, ArchiveHandle *AH);
+static void unsetProcessIdentifier(ParallelStateEntry *pse);
+static ParallelStateEntry *GetMyPSEntry(ParallelState *pstate);
+static void archive_close_connection(int code, void *arg);
+
/*
* Wrapper functions.
res = fclose(AH->OF);
if (res != 0)
- die_horribly(AH, modulename, "could not close output file: %s\n",
- strerror(errno));
+ exit_horribly(modulename, "could not close output file: %s\n",
+ strerror(errno));
}
/* Public */
* connected to, not the one we will create, which is very bad...
*/
if (ropt->createDB && ropt->dropSchema)
- die_horribly(AH, modulename, "-C and -c are incompatible options\n");
+ exit_horribly(modulename, "-C and -c are incompatible options\n");
/*
* -C is not compatible with -1, because we can't create a database inside
* a transaction block.
*/
if (ropt->createDB && ropt->single_txn)
- die_horribly(AH, modulename, "-C and -1 are incompatible options\n");
+ exit_horribly(modulename, "-C and -1 are incompatible options\n");
/*
* If we're going to do parallel restore, there are some restrictions.
{
/* We haven't got round to making this work for all archive formats */
if (AH->ClonePtr == NULL || AH->ReopenPtr == NULL)
- die_horribly(AH, modulename, "parallel restore is not supported with this archive file format\n");
+ exit_horribly(modulename, "parallel restore is not supported with this archive file format\n");
/* Doesn't work if the archive represents dependencies as OIDs */
if (AH->version < K_VERS_1_8)
- die_horribly(AH, modulename, "parallel restore is not supported with archives made by pre-8.0 pg_dump\n");
+ exit_horribly(modulename, "parallel restore is not supported with archives made by pre-8.0 pg_dump\n");
/*
* It's also not gonna work if we can't reopen the input file, so
{
reqs = _tocEntryRequired(te, ropt, false);
if (te->hadDumper && (reqs & REQ_DATA) != 0)
- die_horribly(AH, modulename, "cannot restore from compressed archive (compression not supported in this installation)\n");
+ exit_horribly(modulename, "cannot restore from compressed archive (compression not supported in this installation)\n");
}
}
#endif
{
ahlog(AH, 1, "connecting to database for restore\n");
if (AH->version < K_VERS_1_3)
- die_horribly(AH, modulename, "direct database connections are not supported in pre-1.3 archives\n");
+ exit_horribly(modulename, "direct database connections are not supported in pre-1.3 archives\n");
/* XXX Should get this from the archive */
AHX->minRemoteVersion = 070100;
ArchiveHandle *AH = (ArchiveHandle *) AHX;
if (!AH->currToc)
- die_horribly(AH, modulename, "internal error -- WriteData cannot be called outside the context of a DataDumper routine\n");
+ exit_horribly(modulename, "internal error -- WriteData cannot be called outside the context of a DataDumper routine\n");
return (*AH->WriteDataPtr) (AH, data, dLen);
}
ArchiveHandle *AH = (ArchiveHandle *) AHX;
if (!AH->StartBlobPtr)
- die_horribly(AH, modulename, "large-object output not supported in chosen format\n");
+ exit_horribly(modulename, "large-object output not supported in chosen format\n");
(*AH->StartBlobPtr) (AH, AH->currToc, oid);
{
loOid = lo_create(AH->connection, oid);
if (loOid == 0 || loOid != oid)
- die_horribly(AH, modulename, "could not create large object %u: %s",
- oid, PQerrorMessage(AH->connection));
+ exit_horribly(modulename, "could not create large object %u: %s",
+ oid, PQerrorMessage(AH->connection));
}
AH->loFd = lo_open(AH->connection, oid, INV_WRITE);
if (AH->loFd == -1)
- die_horribly(AH, modulename, "could not open large object %u: %s",
- oid, PQerrorMessage(AH->connection));
+ exit_horribly(modulename, "could not open large object %u: %s",
+ oid, PQerrorMessage(AH->connection));
}
else
{
/* Setup the file */
fh = fopen(ropt->tocFile, PG_BINARY_R);
if (!fh)
- die_horribly(AH, modulename, "could not open TOC file \"%s\": %s\n",
- ropt->tocFile, strerror(errno));
+ exit_horribly(modulename, "could not open TOC file \"%s\": %s\n",
+ ropt->tocFile, strerror(errno));
incomplete_line = false;
while (fgets(buf, sizeof(buf), fh) != NULL)
/* Find TOC entry */
te = getTocEntryByDumpId(AH, id);
if (!te)
- die_horribly(AH, modulename, "could not find entry for ID %d\n",
- id);
+ exit_horribly(modulename, "could not find entry for ID %d\n",
+ id);
/* Mark it wanted */
ropt->idWanted[id - 1] = true;
}
if (fclose(fh) != 0)
- die_horribly(AH, modulename, "could not close TOC file: %s\n",
- strerror(errno));
+ exit_horribly(modulename, "could not close TOC file: %s\n",
+ strerror(errno));
}
/*
if (!AH->OF)
{
if (filename)
- die_horribly(AH, modulename, "could not open output file \"%s\": %s\n",
- filename, strerror(errno));
+ exit_horribly(modulename, "could not open output file \"%s\": %s\n",
+ filename, strerror(errno));
else
- die_horribly(AH, modulename, "could not open output file: %s\n",
- strerror(errno));
+ exit_horribly(modulename, "could not open output file: %s\n",
+ strerror(errno));
}
}
res = fclose(AH->OF);
if (res != 0)
- die_horribly(AH, modulename, "could not close output file: %s\n",
+ exit_horribly(modulename, "could not close output file: %s\n",
strerror(errno));
AH->gzOut = savedContext.gzOut;
AH->lo_buf_used),
(unsigned long) AH->lo_buf_used, (unsigned long) res);
if (res != AH->lo_buf_used)
- die_horribly(AH, modulename,
+ exit_horribly(modulename,
"could not write to large object (result: %lu, expected: %lu)\n",
(unsigned long) res, (unsigned long) AH->lo_buf_used);
}
{
res = GZWRITE(ptr, size, nmemb, AH->OF);
if (res != (nmemb * size))
- die_horribly(AH, modulename, "could not write to output file: %s\n", strerror(errno));
+ exit_horribly(modulename, "could not write to output file: %s\n", strerror(errno));
return res;
}
else if (AH->CustomOutPtr)
res = AH->CustomOutPtr (AH, ptr, size * nmemb);
if (res != (nmemb * size))
- die_horribly(AH, modulename, "could not write to custom output routine\n");
+ exit_horribly(modulename, "could not write to custom output routine\n");
return res;
}
else
{
res = fwrite(ptr, size, nmemb, AH->OF);
if (res != nmemb)
- die_horribly(AH, modulename, "could not write to output file: %s\n",
+ exit_horribly(modulename, "could not write to output file: %s\n",
strerror(errno));
return res;
}
}
}
-
-/* Report a fatal error and exit(1) */
-static void
-vdie_horribly(ArchiveHandle *AH, const char *modulename,
- const char *fmt, va_list ap)
-{
- vwrite_msg(modulename, fmt, ap);
-
- if (AH)
- {
- if (AH->public.verbose)
- write_msg(NULL, "*** aborted because of error\n");
- DisconnectDatabase(&AH->public);
- }
-
- exit_nicely(1);
-}
-
-/* As above, but with variable arg list */
-void
-die_horribly(ArchiveHandle *AH, const char *modulename, const char *fmt,...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- vdie_horribly(AH, modulename, fmt, ap);
- va_end(ap);
-}
-
-/* As above, but with a complaint about a particular query. */
-void
-die_on_query_failure(ArchiveHandle *AH, const char *modulename,
- const char *query)
-{
- write_msg(modulename, "query failed: %s",
- PQerrorMessage(AH->connection));
- die_horribly(AH, modulename, "query was: %s\n", query);
-}
-
/* on some error, we may decide to go on... */
void
-warn_or_die_horribly(ArchiveHandle *AH,
- const char *modulename, const char *fmt,...)
+warn_or_exit_horribly(ArchiveHandle *AH,
+ const char *modulename, const char *fmt,...)
{
va_list ap;
AH->lastErrorTE = AH->currentTE;
va_start(ap, fmt);
+ vwrite_msg(modulename, fmt, ap);
+ va_end(ap);
+
if (AH->public.exit_on_error)
- vdie_horribly(AH, modulename, fmt, ap);
+ exit_nicely(1);
else
- {
- vwrite_msg(modulename, fmt, ap);
AH->public.n_errors++;
- }
- va_end(ap);
}
#ifdef NOT_USED
break;
default:
- die_horribly(AH, modulename, "unexpected data offset flag %d\n", offsetFlg);
+ exit_horribly(modulename, "unexpected data offset flag %d\n", offsetFlg);
}
/*
else
{
if ((*AH->ReadBytePtr) (AH) != 0)
- die_horribly(AH, modulename, "file offset in dump file is too large\n");
+ exit_horribly(modulename, "file offset in dump file is too large\n");
}
}
{
buf = (char *) pg_malloc(l + 1);
if ((*AH->ReadBufPtr) (AH, (void *) buf, l) != l)
- die_horribly(AH, modulename, "unexpected end of file\n");
+ exit_horribly(modulename, "unexpected end of file\n");
buf[l] = '\0';
}
char buf[MAXPGPATH];
if (snprintf(buf, MAXPGPATH, "%s/toc.dat", AH->fSpec) >= MAXPGPATH)
- die_horribly(AH, modulename, "directory name too long: \"%s\"\n",
- AH->fSpec);
+ exit_horribly(modulename, "directory name too long: \"%s\"\n",
+ AH->fSpec);
if (stat(buf, &st) == 0 && S_ISREG(st.st_mode))
{
AH->format = archDirectory;
#ifdef HAVE_LIBZ
if (snprintf(buf, MAXPGPATH, "%s/toc.dat.gz", AH->fSpec) >= MAXPGPATH)
- die_horribly(AH, modulename, "directory name too long: \"%s\"\n",
- AH->fSpec);
+ exit_horribly(modulename, "directory name too long: \"%s\"\n",
+ AH->fSpec);
if (stat(buf, &st) == 0 && S_ISREG(st.st_mode))
{
AH->format = archDirectory;
return AH->format;
}
#endif
- die_horribly(AH, modulename, "directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)\n",
- AH->fSpec);
+ exit_horribly(modulename, "directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)\n",
+ AH->fSpec);
fh = NULL; /* keep compiler quiet */
}
else
{
fh = fopen(AH->fSpec, PG_BINARY_R);
if (!fh)
- die_horribly(AH, modulename, "could not open input file \"%s\": %s\n",
- AH->fSpec, strerror(errno));
+ exit_horribly(modulename, "could not open input file \"%s\": %s\n",
+ AH->fSpec, strerror(errno));
}
}
else
{
fh = stdin;
if (!fh)
- die_horribly(AH, modulename, "could not open input file: %s\n",
- strerror(errno));
+ exit_horribly(modulename, "could not open input file: %s\n",
+ strerror(errno));
}
cnt = fread(sig, 1, 5, fh);
if (cnt != 5)
{
if (ferror(fh))
- die_horribly(AH, modulename, "could not read input file: %s\n", strerror(errno));
+ exit_horribly(modulename, "could not read input file: %s\n", strerror(errno));
else
- die_horribly(AH, modulename, "input file is too short (read %lu, expected 5)\n",
- (unsigned long) cnt);
+ exit_horribly(modulename, "input file is too short (read %lu, expected 5)\n",
+ (unsigned long) cnt);
}
/* Save it, just in case we need it later */
strncmp(AH->lookahead, TEXT_DUMPALL_HEADER, strlen(TEXT_DUMPALL_HEADER)) == 0))
{
/* looks like it's probably a text format dump. so suggest they try psql */
- die_horribly(AH, modulename, "input file appears to be a text format dump. Please use psql.\n");
+ exit_horribly(modulename, "input file appears to be a text format dump. Please use psql.\n");
}
if (AH->lookaheadLen != 512)
- die_horribly(AH, modulename, "input file does not appear to be a valid archive (too short?)\n");
+ exit_horribly(modulename, "input file does not appear to be a valid archive (too short?)\n");
if (!isValidTarHeader(AH->lookahead))
- die_horribly(AH, modulename, "input file does not appear to be a valid archive\n");
+ exit_horribly(modulename, "input file does not appear to be a valid archive\n");
AH->format = archTar;
}
/* Close the file */
if (wantClose)
if (fclose(fh) != 0)
- die_horribly(AH, modulename, "could not close input file: %s\n",
- strerror(errno));
+ exit_horribly(modulename, "could not close input file: %s\n",
+ strerror(errno));
return AH->format;
}
break;
default:
- die_horribly(AH, modulename, "unrecognized file format \"%d\"\n", fmt);
+ exit_horribly(modulename, "unrecognized file format \"%d\"\n", fmt);
}
return AH;
/* Sanity check */
if (te->dumpId <= 0)
- die_horribly(AH, modulename,
- "entry ID %d out of range -- perhaps a corrupt TOC\n",
- te->dumpId);
+ exit_horribly(modulename,
+ "entry ID %d out of range -- perhaps a corrupt TOC\n",
+ te->dumpId);
te->hadDumper = ReadInt(AH);
*ptr2 = '\0';
encoding = pg_char_to_encoding(ptr1);
if (encoding < 0)
- die_horribly(AH, modulename, "unrecognized encoding \"%s\"\n",
- ptr1);
+ exit_horribly(modulename, "unrecognized encoding \"%s\"\n",
+ ptr1);
AH->public.encoding = encoding;
}
else
- die_horribly(AH, modulename, "invalid ENCODING item: %s\n",
- te->defn);
+ exit_horribly(modulename, "invalid ENCODING item: %s\n",
+ te->defn);
free(defn);
}
else if (ptr1 && strncmp(ptr1, "'off'", 5) == 0)
AH->public.std_strings = false;
else
- die_horribly(AH, modulename, "invalid STDSTRINGS item: %s\n",
- te->defn);
+ exit_horribly(modulename, "invalid STDSTRINGS item: %s\n",
+ te->defn);
}
static teReqs
res = PQexec(AH->connection, cmd->data);
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
- /* NOT warn_or_die_horribly... use -O instead to skip this. */
- die_horribly(AH, modulename, "could not set session user to \"%s\": %s",
- user, PQerrorMessage(AH->connection));
+ /* NOT warn_or_exit_horribly... use -O instead to skip this. */
+ exit_horribly(modulename, "could not set session user to \"%s\": %s",
+ user, PQerrorMessage(AH->connection));
PQclear(res);
}
res = PQexec(AH->connection, cmd->data);
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
- warn_or_die_horribly(AH, modulename,
- "could not set default_with_oids: %s",
- PQerrorMessage(AH->connection));
+ warn_or_exit_horribly(AH, modulename,
+ "could not set default_with_oids: %s",
+ PQerrorMessage(AH->connection));
PQclear(res);
}
res = PQexec(AH->connection, qry->data);
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
- warn_or_die_horribly(AH, modulename,
- "could not set search_path to \"%s\": %s",
- schemaName, PQerrorMessage(AH->connection));
+ warn_or_exit_horribly(AH, modulename,
+ "could not set search_path to \"%s\": %s",
+ schemaName, PQerrorMessage(AH->connection));
PQclear(res);
}
res = PQexec(AH->connection, qry->data);
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
- warn_or_die_horribly(AH, modulename,
- "could not set default_tablespace to %s: %s",
- fmtId(want), PQerrorMessage(AH->connection));
+ warn_or_exit_horribly(AH, modulename,
+ "could not set default_tablespace to %s: %s",
+ fmtId(want), PQerrorMessage(AH->connection));
PQclear(res);
}
if (!AH->readHeader)
{
if ((*AH->ReadBufPtr) (AH, tmpMag, 5) != 5)
- die_horribly(AH, modulename, "unexpected end of file\n");
+ exit_horribly(modulename, "unexpected end of file\n");
if (strncmp(tmpMag, "PGDMP", 5) != 0)
- die_horribly(AH, modulename, "did not find magic string in file header\n");
+ exit_horribly(modulename, "did not find magic string in file header\n");
AH->vmaj = (*AH->ReadBytePtr) (AH);
AH->vmin = (*AH->ReadBytePtr) (AH);
AH->version = ((AH->vmaj * 256 + AH->vmin) * 256 + AH->vrev) * 256 + 0;
if (AH->version < K_VERS_1_0 || AH->version > K_VERS_MAX)
- die_horribly(AH, modulename, "unsupported version (%d.%d) in file header\n",
- AH->vmaj, AH->vmin);
+ exit_horribly(modulename, "unsupported version (%d.%d) in file header\n",
+ AH->vmaj, AH->vmin);
AH->intSize = (*AH->ReadBytePtr) (AH);
if (AH->intSize > 32)
- die_horribly(AH, modulename, "sanity check on integer size (%lu) failed\n",
- (unsigned long) AH->intSize);
+ exit_horribly(modulename, "sanity check on integer size (%lu) failed\n",
+ (unsigned long) AH->intSize);
if (AH->intSize > sizeof(int))
write_msg(modulename, "WARNING: archive was made on a machine with larger integers, some operations might fail\n");
fmt = (*AH->ReadBytePtr) (AH);
if (AH->format != fmt)
- die_horribly(AH, modulename, "expected format (%d) differs from format found in file (%d)\n",
- AH->format, fmt);
+ exit_horribly(modulename, "expected format (%d) differs from format found in file (%d)\n",
+ AH->format, fmt);
}
if (AH->version >= K_VERS_1_2)
ahprintf(AH, "-- %s %s\n\n", msg, buf);
}
+static void
+setProcessIdentifier(ParallelStateEntry *pse, ArchiveHandle *AH)
+{
+#ifdef WIN32
+ pse->threadId = GetCurrentThreadId();
+#else
+ pse->pid = getpid();
+#endif
+ pse->AH = AH;
+}
+
+static void
+unsetProcessIdentifier(ParallelStateEntry *pse)
+{
+#ifdef WIN32
+ pse->threadId = 0;
+#else
+ pse->pid = 0;
+#endif
+ pse->AH = NULL;
+}
+
+static ParallelStateEntry *
+GetMyPSEntry(ParallelState *pstate)
+{
+ int i;
+
+ for (i = 0; i < pstate->numWorkers; i++)
+#ifdef WIN32
+ if (pstate->pse[i].threadId == GetCurrentThreadId())
+#else
+ if (pstate->pse[i].pid == getpid())
+#endif
+ return &(pstate->pse[i]);
+
+ return NULL;
+}
+
+static void
+archive_close_connection(int code, void *arg)
+{
+ ShutdownInformation *si = (ShutdownInformation *) arg;
+
+ if (si->pstate)
+ {
+ ParallelStateEntry *entry = GetMyPSEntry(si->pstate);
+
+ if (entry != NULL && entry->AH)
+ DisconnectDatabase(&(entry->AH->public));
+ }
+ else if (si->AHX)
+ DisconnectDatabase(si->AHX);
+}
+
+void
+on_exit_close_archive(Archive *AHX)
+{
+ shutdown_info.AHX = AHX;
+ on_exit_nicely(archive_close_connection, &shutdown_info);
+}
/*
* Main engine for parallel restore.
TocEntry *next_work_item;
thandle ret_child;
TocEntry *te;
+ ParallelState *pstate;
+ int i;
ahlog(AH, 2, "entering restore_toc_entries_parallel\n");
- slots = (ParallelSlot *) pg_calloc(sizeof(ParallelSlot), n_slots);
+ slots = (ParallelSlot *) pg_calloc(n_slots, sizeof(ParallelSlot));
+ pstate = (ParallelState *) pg_malloc(sizeof(ParallelState));
+ pstate->pse = (ParallelStateEntry *) pg_calloc(n_slots, sizeof(ParallelStateEntry));
+ pstate->numWorkers = ropt->number_of_jobs;
+ for (i = 0; i < pstate->numWorkers; i++)
+ unsetProcessIdentifier(&(pstate->pse[i]));
/* Adjust dependency information */
fix_dependencies(AH);
*/
DisconnectDatabase(&AH->public);
+ /*
+ * Set the pstate in the shutdown_info. The exit handler uses pstate if set
+ * and falls back to AHX otherwise.
+ */
+ shutdown_info.pstate = pstate;
+
/* blow away any transient state from the old connection */
if (AH->currUser)
free(AH->currUser);
args = pg_malloc(sizeof(RestoreArgs));
args->AH = CloneArchive(AH);
args->te = next_work_item;
+ args->pse = &pstate->pse[next_slot];
/* run the step in a worker child */
child = spawn_restore(args);
}
else
{
- die_horribly(AH, modulename, "worker process crashed: status %d\n",
- work_status);
+ exit_horribly(modulename, "worker process crashed: status %d\n",
+ work_status);
}
}
ahlog(AH, 1, "finished main parallel loop\n");
+ /*
+ * Remove the pstate again, so the exit handler will now fall back to
+ * closing AH->connection again.
+ */
+ shutdown_info.pstate = NULL;
+
/*
* Now reconnect the single parent connection.
*/
{
/* in child process */
parallel_restore(args);
- die_horribly(args->AH, modulename,
- "parallel_restore should not return\n");
+ exit_horribly(modulename,
+ "parallel_restore should not return\n");
}
else if (child < 0)
{
/* fork failed */
- die_horribly(args->AH, modulename,
- "could not create worker process: %s\n",
- strerror(errno));
+ exit_horribly(modulename,
+ "could not create worker process: %s\n",
+ strerror(errno));
}
#else
child = (HANDLE) _beginthreadex(NULL, 0, (void *) parallel_restore,
args, 0, NULL);
if (child == 0)
- die_horribly(args->AH, modulename,
- "could not create worker thread: %s\n",
- strerror(errno));
+ exit_horribly(modulename,
+ "could not create worker thread: %s\n",
+ strerror(errno));
#endif
return child;
RestoreOptions *ropt = AH->ropt;
int retval;
+ setProcessIdentifier(args->pse, AH);
+
/*
* Close and reopen the input file so we have a private file pointer that
* doesn't stomp on anyone else's file pointer, if we're actually going to
/* And clean up */
DisconnectDatabase((Archive *) AH);
+ unsetProcessIdentifier(args->pse);
/* If we reopened the file, we are done with it, so close it now */
if (te->section == SECTION_DATA)
}
if (te == NULL)
- die_horribly(AH, modulename, "could not find slot of finished worker\n");
+ exit_horribly(modulename, "could not find slot of finished worker\n");
ahlog(AH, 1, "finished item %d %s %s\n",
te->dumpId, te->desc, te->tag);
else if (status == WORKER_IGNORED_ERRORS)
AH->public.n_errors++;
else if (status != 0)
- die_horribly(AH, modulename, "worker process failed: exit code %d\n",
- status);
+ exit_horribly(modulename, "worker process failed: exit code %d\n",
+ status);
reduce_dependencies(AH, te, ready_list);
}
int nLockDeps; /* number of such dependencies */
} TocEntry;
+extern void on_exit_close_archive(Archive *AHX);
-extern void die_horribly(ArchiveHandle *AH, const char *modulename, const char *fmt,...) __attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4), noreturn));
-extern void die_on_query_failure(ArchiveHandle *AH, const char *modulename, const char *query) __attribute__((noreturn));
-extern void warn_or_die_horribly(ArchiveHandle *AH, const char *modulename, const char *fmt,...) __attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4)));
+extern void warn_or_exit_horribly(ArchiveHandle *AH, const char *modulename, const char *fmt,...) __attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4)));
extern void WriteTOC(ArchiveHandle *AH);
extern void ReadTOC(ArchiveHandle *AH);
{
AH->FH = fopen(AH->fSpec, PG_BINARY_W);
if (!AH->FH)
- die_horribly(AH, modulename, "could not open output file \"%s\": %s\n",
- AH->fSpec, strerror(errno));
+ exit_horribly(modulename, "could not open output file \"%s\": %s\n",
+ AH->fSpec, strerror(errno));
}
else
{
AH->FH = stdout;
if (!AH->FH)
- die_horribly(AH, modulename, "could not open output file: %s\n",
- strerror(errno));
+ exit_horribly(modulename, "could not open output file: %s\n",
+ strerror(errno));
}
ctx->hasSeek = checkSeek(AH->FH);
{
AH->FH = fopen(AH->fSpec, PG_BINARY_R);
if (!AH->FH)
- die_horribly(AH, modulename, "could not open input file \"%s\": %s\n",
- AH->fSpec, strerror(errno));
+ exit_horribly(modulename, "could not open input file \"%s\": %s\n",
+ AH->fSpec, strerror(errno));
}
else
{
AH->FH = stdin;
if (!AH->FH)
- die_horribly(AH, modulename, "could not open input file: %s\n",
- strerror(errno));
+ exit_horribly(modulename, "could not open input file: %s\n",
+ strerror(errno));
}
ctx->hasSeek = checkSeek(AH->FH);
lclContext *ctx = (lclContext *) AH->formatData;
if (oid == 0)
- die_horribly(AH, modulename, "invalid OID for large object\n");
+ exit_horribly(modulename, "invalid OID for large object\n");
WriteInt(AH, oid);
break;
default: /* Always have a default */
- die_horribly(AH, modulename,
- "unrecognized data block type (%d) while searching archive\n",
- blkType);
+ exit_horribly(modulename,
+ "unrecognized data block type (%d) while searching archive\n",
+ blkType);
break;
}
_readBlockHeader(AH, &blkType, &id);
{
/* We can just seek to the place we need to be. */
if (fseeko(AH->FH, tctx->dataPos, SEEK_SET) != 0)
- die_horribly(AH, modulename, "error during file seek: %s\n",
- strerror(errno));
+ exit_horribly(modulename, "error during file seek: %s\n",
+ strerror(errno));
_readBlockHeader(AH, &blkType, &id);
}
if (blkType == EOF)
{
if (tctx->dataState == K_OFFSET_POS_NOT_SET)
- die_horribly(AH, modulename, "could not find block ID %d in archive -- "
- "possibly due to out-of-order restore request, "
- "which cannot be handled due to lack of data offsets in archive\n",
- te->dumpId);
+ exit_horribly(modulename, "could not find block ID %d in archive -- "
+ "possibly due to out-of-order restore request, "
+ "which cannot be handled due to lack of data offsets in archive\n",
+ te->dumpId);
else if (!ctx->hasSeek)
- die_horribly(AH, modulename, "could not find block ID %d in archive -- "
- "possibly due to out-of-order restore request, "
- "which cannot be handled due to non-seekable input file\n",
- te->dumpId);
+ exit_horribly(modulename, "could not find block ID %d in archive -- "
+ "possibly due to out-of-order restore request, "
+ "which cannot be handled due to non-seekable input file\n",
+ te->dumpId);
else /* huh, the dataPos led us to EOF? */
- die_horribly(AH, modulename, "could not find block ID %d in archive -- "
- "possibly corrupt archive\n",
- te->dumpId);
+ exit_horribly(modulename, "could not find block ID %d in archive -- "
+ "possibly corrupt archive\n",
+ te->dumpId);
}
/* Are we sane? */
if (id != te->dumpId)
- die_horribly(AH, modulename, "found unexpected block ID (%d) when reading data -- expected %d\n",
- id, te->dumpId);
+ exit_horribly(modulename, "found unexpected block ID (%d) when reading data -- expected %d\n",
+ id, te->dumpId);
switch (blkType)
{
break;
default: /* Always have a default */
- die_horribly(AH, modulename, "unrecognized data block type %d while restoring archive\n",
- blkType);
+ exit_horribly(modulename, "unrecognized data block type %d while restoring archive\n",
+ blkType);
break;
}
}
if (cnt != blkLen)
{
if (feof(AH->FH))
- die_horribly(AH, modulename,
- "could not read from input file: end of file\n");
+ exit_horribly(modulename,
+ "could not read from input file: end of file\n");
else
- die_horribly(AH, modulename,
- "could not read from input file: %s\n", strerror(errno));
+ exit_horribly(modulename,
+ "could not read from input file: %s\n", strerror(errno));
}
ctx->filePos += blkLen;
if (res != EOF)
ctx->filePos += 1;
else
- die_horribly(AH, modulename, "could not write byte: %s\n", strerror(errno));
+ exit_horribly(modulename, "could not write byte: %s\n", strerror(errno));
return res;
}
res = getc(AH->FH);
if (res == EOF)
- die_horribly(AH, modulename, "unexpected end of file\n");
+ exit_horribly(modulename, "unexpected end of file\n");
ctx->filePos += 1;
return res;
}
res = fwrite(buf, 1, len, AH->FH);
if (res != len)
- die_horribly(AH, modulename,
+ exit_horribly(modulename,
"could not write to output file: %s\n", strerror(errno));
ctx->filePos += res;
}
if (fclose(AH->FH) != 0)
- die_horribly(AH, modulename, "could not close archive file: %s\n", strerror(errno));
+ exit_horribly(modulename, "could not close archive file: %s\n", strerror(errno));
AH->FH = NULL;
}
pgoff_t tpos;
if (AH->mode == archModeWrite)
- die_horribly(AH, modulename, "can only reopen input archives\n");
+ exit_horribly(modulename, "can only reopen input archives\n");
/*
* These two cases are user-facing errors since they represent unsupported
* (but not invalid) use-cases. Word the error messages appropriately.
*/
if (AH->fSpec == NULL || strcmp(AH->fSpec, "") == 0)
- die_horribly(AH, modulename, "parallel restore from stdin is not supported\n");
+ exit_horribly(modulename, "parallel restore from stdin is not supported\n");
if (!ctx->hasSeek)
- die_horribly(AH, modulename, "parallel restore from non-seekable file is not supported\n");
+ exit_horribly(modulename, "parallel restore from non-seekable file is not supported\n");
errno = 0;
tpos = ftello(AH->FH);
if (errno)
- die_horribly(AH, modulename, "could not determine seek position in archive file: %s\n",
- strerror(errno));
+ exit_horribly(modulename, "could not determine seek position in archive file: %s\n",
+ strerror(errno));
#ifndef WIN32
if (fclose(AH->FH) != 0)
- die_horribly(AH, modulename, "could not close archive file: %s\n",
- strerror(errno));
+ exit_horribly(modulename, "could not close archive file: %s\n",
+ strerror(errno));
#endif
AH->FH = fopen(AH->fSpec, PG_BINARY_R);
if (!AH->FH)
- die_horribly(AH, modulename, "could not open input file \"%s\": %s\n",
- AH->fSpec, strerror(errno));
+ exit_horribly(modulename, "could not open input file \"%s\": %s\n",
+ AH->fSpec, strerror(errno));
if (fseeko(AH->FH, tpos, SEEK_SET) != 0)
- die_horribly(AH, modulename, "could not set seek position in archive file: %s\n",
- strerror(errno));
+ exit_horribly(modulename, "could not set seek position in archive file: %s\n",
+ strerror(errno));
}
/*
/* sanity check, shouldn't happen */
if (ctx->cs != NULL)
- die_horribly(AH, modulename, "compressor active\n");
+ exit_horribly(modulename, "compressor active\n");
/*
* Note: we do not make a local lo_buf because we expect at most one BLOBS
int byt;
/*
- * Note: if we are at EOF with a pre-1.3 input file, we'll die_horribly
+ * Note: if we are at EOF with a pre-1.3 input file, we'll exit_horribly
* inside ReadInt rather than returning EOF. It doesn't seem worth
* jumping through hoops to deal with that case better, because no such
* files are likely to exist in the wild: only some 7.1 development
if (cnt != blkLen)
{
if (feof(AH->FH))
- die_horribly(AH, modulename,
- "could not read from input file: end of file\n");
+ exit_horribly(modulename,
+ "could not read from input file: end of file\n");
else
- die_horribly(AH, modulename,
+ exit_horribly(modulename,
"could not read from input file: %s\n", strerror(errno));
}
return cnt;
static void notice_processor(void *arg, const char *message);
static int
-_parse_version(ArchiveHandle *AH, const char *versionString)
+_parse_version(const char *versionString)
{
int v;
v = parse_version(versionString);
if (v < 0)
- die_horribly(AH, modulename, "could not parse version string \"%s\"\n", versionString);
+ exit_horribly(modulename, "could not parse version string \"%s\"\n", versionString);
return v;
}
const char *remoteversion_str;
int remoteversion;
- myversion = _parse_version(AH, PG_VERSION);
+ myversion = _parse_version(PG_VERSION);
remoteversion_str = PQparameterStatus(AH->connection, "server_version");
if (!remoteversion_str)
- die_horribly(AH, modulename, "could not get server_version from libpq\n");
+ exit_horribly(modulename, "could not get server_version from libpq\n");
- remoteversion = _parse_version(AH, remoteversion_str);
+ remoteversion = _parse_version(remoteversion_str);
AH->public.remoteVersionStr = pg_strdup(remoteversion_str);
AH->public.remoteVersion = remoteversion;
{
write_msg(NULL, "server version: %s; %s version: %s\n",
remoteversion_str, progname, PG_VERSION);
- die_horribly(AH, NULL, "aborting because of server version mismatch\n");
+ exit_horribly(NULL, "aborting because of server version mismatch\n");
}
}
{
password = simple_prompt("Password: ", 100, false);
if (password == NULL)
- die_horribly(AH, modulename, "out of memory\n");
+ exit_horribly(modulename, "out of memory\n");
}
do
free(values);
if (!newConn)
- die_horribly(AH, modulename, "failed to reconnect to database\n");
+ exit_horribly(modulename, "failed to reconnect to database\n");
if (PQstatus(newConn) == CONNECTION_BAD)
{
if (!PQconnectionNeedsPassword(newConn))
- die_horribly(AH, modulename, "could not reconnect to database: %s",
+ exit_horribly(modulename, "could not reconnect to database: %s",
PQerrorMessage(newConn));
PQfinish(newConn);
if (AH->promptPassword != TRI_NO)
password = simple_prompt("Password: ", 100, false);
else
- die_horribly(AH, modulename, "connection needs password\n");
+ exit_horribly(modulename, "connection needs password\n");
if (password == NULL)
- die_horribly(AH, modulename, "out of memory\n");
+ exit_horribly(modulename, "out of memory\n");
new_pass = true;
}
} while (new_pass);
bool new_pass;
if (AH->connection)
- die_horribly(AH, modulename, "already connected to a database\n");
+ exit_horribly(modulename, "already connected to a database\n");
if (prompt_password == TRI_YES && password == NULL)
{
password = simple_prompt("Password: ", 100, false);
if (password == NULL)
- die_horribly(AH, modulename, "out of memory\n");
+ exit_horribly(modulename, "out of memory\n");
}
AH->promptPassword = prompt_password;
free(values);
if (!AH->connection)
- die_horribly(AH, modulename, "failed to connect to database\n");
+ exit_horribly(modulename, "failed to connect to database\n");
if (PQstatus(AH->connection) == CONNECTION_BAD &&
PQconnectionNeedsPassword(AH->connection) &&
PQfinish(AH->connection);
password = simple_prompt("Password: ", 100, false);
if (password == NULL)
- die_horribly(AH, modulename, "out of memory\n");
+ exit_horribly(modulename, "out of memory\n");
new_pass = true;
}
} while (new_pass);
/* check to see that the backend connection was successfully made */
if (PQstatus(AH->connection) == CONNECTION_BAD)
- die_horribly(AH, modulename, "connection to database \"%s\" failed: %s",
+ exit_horribly(modulename, "connection to database \"%s\" failed: %s",
PQdb(AH->connection), PQerrorMessage(AH->connection));
/* check for version mismatch */
write_msg(NULL, "%s", message);
}
+/* Like exit_horribly(), but with a complaint about a particular query. */
+static void
+die_on_query_failure(ArchiveHandle *AH, const char *modulename, const char *query)
+{
+ write_msg(modulename, "query failed: %s",
+ PQerrorMessage(AH->connection));
+ exit_horribly(modulename, "query was: %s\n", query);
+}
void
ExecuteSqlStatement(Archive *AHX, const char *query)
errStmt[DB_MAX_ERR_STMT - 2] = '.';
errStmt[DB_MAX_ERR_STMT - 1] = '\0';
}
- warn_or_die_horribly(AH, modulename, "%s: %s Command was: %s\n",
- desc, PQerrorMessage(conn), errStmt);
+ warn_or_exit_horribly(AH, modulename, "%s: %s Command was: %s\n",
+ desc, PQerrorMessage(conn), errStmt);
break;
}
*/
if (AH->pgCopyIn &&
PQputCopyData(AH->connection, buf, bufLen) <= 0)
- die_horribly(AH, modulename, "error returned by PQputCopyData: %s",
- PQerrorMessage(AH->connection));
+ exit_horribly(modulename, "error returned by PQputCopyData: %s",
+ PQerrorMessage(AH->connection));
}
else if (AH->outputKind == OUTPUT_OTHERDATA)
{
PGresult *res;
if (PQputCopyEnd(AH->connection, NULL) <= 0)
- die_horribly(AH, modulename, "error returned by PQputCopyEnd: %s",
- PQerrorMessage(AH->connection));
+ exit_horribly(modulename, "error returned by PQputCopyEnd: %s",
+ PQerrorMessage(AH->connection));
/* Check command status and return to normal libpq state */
res = PQgetResult(AH->connection);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
- warn_or_die_horribly(AH, modulename, "COPY failed for table \"%s\": %s",
- te->tag, PQerrorMessage(AH->connection));
+ warn_or_exit_horribly(AH, modulename, "COPY failed for table \"%s\": %s",
+ te->tag, PQerrorMessage(AH->connection));
PQclear(res);
AH->pgCopyIn = false;
*/
if (!AH->fSpec || strcmp(AH->fSpec, "") == 0)
- die_horribly(AH, modulename, "no output directory specified\n");
+ exit_horribly(modulename, "no output directory specified\n");
ctx->directory = AH->fSpec;
tocFH = cfopen_read(fname, PG_BINARY_R);
if (tocFH == NULL)
- die_horribly(AH, modulename,
- "could not open input file \"%s\": %s\n",
- fname, strerror(errno));
+ exit_horribly(modulename,
+ "could not open input file \"%s\": %s\n",
+ fname, strerror(errno));
ctx->dataFH = tocFH;
/* Nothing else in the file, so close it again... */
if (cfclose(tocFH) != 0)
- die_horribly(AH, modulename, "could not close TOC file: %s\n",
+ exit_horribly(modulename, "could not close TOC file: %s\n",
strerror(errno));
ctx->dataFH = NULL;
}
ctx->dataFH = cfopen_write(fname, PG_BINARY_W, AH->compression);
if (ctx->dataFH == NULL)
- die_horribly(AH, modulename, "could not open output file \"%s\": %s\n",
- fname, strerror(errno));
+ exit_horribly(modulename, "could not open output file \"%s\": %s\n",
+ fname, strerror(errno));
}
/*
cfp = cfopen_read(filename, PG_BINARY_R);
if (!cfp)
- die_horribly(AH, modulename, "could not open input file \"%s\": %s\n",
+ exit_horribly(modulename, "could not open input file \"%s\": %s\n",
filename, strerror(errno));
buf = pg_malloc(ZLIB_OUT_SIZE);
free(buf);
if (cfclose(cfp) != 0)
- die_horribly(AH, modulename, "could not close data file: %s\n",
+ exit_horribly(modulename, "could not close data file: %s\n",
strerror(errno));
}
ctx->blobsTocFH = cfopen_read(fname, PG_BINARY_R);
if (ctx->blobsTocFH == NULL)
- die_horribly(AH, modulename, "could not open large object TOC file \"%s\" for input: %s\n",
- fname, strerror(errno));
+ exit_horribly(modulename, "could not open large object TOC file \"%s\" for input: %s\n",
+ fname, strerror(errno));
/* Read the blobs TOC file line-by-line, and process each blob */
while ((cfgets(ctx->blobsTocFH, line, MAXPGPATH)) != NULL)
char path[MAXPGPATH];
if (sscanf(line, "%u %s\n", &oid, fname) != 2)
- die_horribly(AH, modulename, "invalid line in large object TOC file: %s\n",
- line);
+ exit_horribly(modulename, "invalid line in large object TOC file: %s\n",
+ line);
StartRestoreBlob(AH, oid, ropt->dropSchema);
snprintf(path, MAXPGPATH, "%s/%s", ctx->directory, fname);
EndRestoreBlob(AH, oid);
}
if (!cfeof(ctx->blobsTocFH))
- die_horribly(AH, modulename, "error reading large object TOC file \"%s\"\n",
+ exit_horribly(modulename, "error reading large object TOC file \"%s\"\n",
fname);
if (cfclose(ctx->blobsTocFH) != 0)
- die_horribly(AH, modulename, "could not close large object TOC file \"%s\": %s\n",
- fname, strerror(errno));
+ exit_horribly(modulename, "could not close large object TOC file \"%s\": %s\n",
+ fname, strerror(errno));
ctx->blobsTocFH = NULL;
lclContext *ctx = (lclContext *) AH->formatData;
if (cfwrite(&c, 1, ctx->dataFH) != 1)
- die_horribly(AH, modulename, "could not write byte\n");
+ exit_horribly(modulename, "could not write byte\n");
return 1;
}
res = cfgetc(ctx->dataFH);
if (res == EOF)
- die_horribly(AH, modulename, "unexpected end of file\n");
+ exit_horribly(modulename, "unexpected end of file\n");
return res;
}
res = cfwrite(buf, len, ctx->dataFH);
if (res != len)
- die_horribly(AH, modulename, "could not write to output file: %s\n",
+ exit_horribly(modulename, "could not write to output file: %s\n",
strerror(errno));
return res;
/* The TOC is always created uncompressed */
tocFH = cfopen_write(fname, PG_BINARY_W, 0);
if (tocFH == NULL)
- die_horribly(AH, modulename, "could not open output file \"%s\": %s\n",
- fname, strerror(errno));
+ exit_horribly(modulename, "could not open output file \"%s\": %s\n",
+ fname, strerror(errno));
ctx->dataFH = tocFH;
/*
AH->format = archDirectory;
WriteToc(AH);
if (cfclose(tocFH) != 0)
- die_horribly(AH, modulename, "could not close TOC file: %s\n",
- strerror(errno));
+ exit_horribly(modulename, "could not close TOC file: %s\n",
+ strerror(errno));
WriteDataChunks(AH);
}
AH->FH = NULL;
/* The blob TOC file is never compressed */
ctx->blobsTocFH = cfopen_write(fname, "ab", 0);
if (ctx->blobsTocFH == NULL)
- die_horribly(AH, modulename, "could not open output file \"%s\": %s\n",
- fname, strerror(errno));
+ exit_horribly(modulename, "could not open output file \"%s\": %s\n",
+ fname, strerror(errno));
}
/*
ctx->dataFH = cfopen_write(fname, PG_BINARY_W, AH->compression);
if (ctx->dataFH == NULL)
- die_horribly(AH, modulename, "could not open output file \"%s\": %s\n",
+ exit_horribly(modulename, "could not open output file \"%s\": %s\n",
fname, strerror(errno));
}
/* register the blob in blobs.toc */
len = snprintf(buf, sizeof(buf), "%u blob_%u.dat\n", oid, oid);
if (cfwrite(buf, len, ctx->blobsTocFH) != len)
- die_horribly(AH, modulename, "could not write to blobs TOC file\n");
+ exit_horribly(modulename, "could not write to blobs TOC file\n");
}
/*
dname = ctx->directory;
if (strlen(dname) + 1 + strlen(relativeFilename) + 1 > MAXPGPATH)
- die_horribly(AH, modulename, "path name too long: %s", dname);
+ exit_horribly(modulename, "path name too long: %s", dname);
strcpy(buf, dname);
strcat(buf, "/");
* Now prevent reading...
*/
if (AH->mode == archModeRead)
- die_horribly(AH, NULL, "this format cannot be read\n");
+ exit_horribly(NULL, "this format cannot be read\n");
}
/*
bool old_blob_style = (AH->version < K_VERS_1_12);
if (oid == 0)
- die_horribly(AH, NULL, "invalid OID for large object\n");
+ exit_horribly(NULL, "invalid OID for large object\n");
/* With an old archive we must do drop and create logic here */
if (old_blob_style && AH->ropt->dropSchema)
* Couldn't find the requested file. Future: do SEEK(0) and
* retry.
*/
- die_horribly(AH, modulename, "could not find file \"%s\" in archive\n", filename);
+ exit_horribly(modulename, "could not find file \"%s\" in archive\n", filename);
}
else
{
if (AH->compression == 0)
tm->nFH = ctx->tarFH;
else
- die_horribly(AH, modulename, "compression is not supported by tar archive format\n");
+ exit_horribly(modulename, "compression is not supported by tar archive format\n");
/* tm->zFH = gzdopen(dup(fileno(ctx->tarFH)), "rb"); */
#else
tm->nFH = ctx->tarFH;
#endif
if (tm->tmpFH == NULL)
- die_horribly(AH, modulename, "could not generate temporary file name: %s\n", strerror(errno));
+ exit_horribly(modulename, "could not generate temporary file name: %s\n", strerror(errno));
#ifdef HAVE_LIBZ
sprintf(fmode, "wb%d", AH->compression);
tm->zFH = gzdopen(dup(fileno(tm->tmpFH)), fmode);
if (tm->zFH == NULL)
- die_horribly(AH, modulename, "could not open temporary file\n");
+ exit_horribly(modulename, "could not open temporary file\n");
}
else
tm->nFH = tm->tmpFH;
*/
if (AH->compression != 0)
if (GZCLOSE(th->zFH) != 0)
- die_horribly(AH, modulename, "could not close tar member\n");
+ exit_horribly(modulename, "could not close tar member\n");
if (th->mode == 'w')
_tarAddFile(AH, th); /* This will close the temp file */
res = fread(&((char *) buf)[used], 1, len, th->nFH);
}
else
- die_horribly(AH, modulename, "internal error -- neither th nor fh specified in tarReadRaw()\n");
+ exit_horribly(modulename, "internal error -- neither th nor fh specified in tarReadRaw()\n");
}
ctx->tarFHpos += res + used;
res = fwrite(buf, 1, len, th->nFH);
if (res != len)
- die_horribly(th->AH, modulename,
- "could not write to output file: %s\n", strerror(errno));
+ exit_horribly(modulename,
+ "could not write to output file: %s\n", strerror(errno));
th->pos += res;
return res;
* we search the string for it in a paranoid sort of way.
*/
if (strncmp(tmpCopy, "copy ", 5) != 0)
- die_horribly(AH, modulename,
- "invalid COPY statement -- could not find \"copy\" in string \"%s\"\n", tmpCopy);
+ exit_horribly(modulename,
+ "invalid COPY statement -- could not find \"copy\" in string \"%s\"\n", tmpCopy);
pos1 = 5;
for (pos1 = 5; pos1 < strlen(tmpCopy); pos1++)
break;
if (pos2 >= strlen(tmpCopy))
- die_horribly(AH, modulename,
- "invalid COPY statement -- could not find \"from stdin\" in string \"%s\" starting at position %lu\n",
- tmpCopy, (unsigned long) pos1);
+ exit_horribly(modulename,
+ "invalid COPY statement -- could not find \"from stdin\" in string \"%s\" starting at position %lu\n",
+ tmpCopy, (unsigned long) pos1);
ahwrite(tmpCopy, 1, pos2, AH); /* 'copy "table" [with oids]' */
ahprintf(AH, " from '$$PATH$$/%s' %s", tctx->filename, &tmpCopy[pos2 + 10]);
res = tarRead(&c, 1, ctx->FH);
if (res != 1)
- die_horribly(AH, modulename, "unexpected end of file\n");
+ exit_horribly(modulename, "unexpected end of file\n");
ctx->filePos += 1;
return c;
}
for (i = 0; i < 512; i++)
{
if (fputc(0, ctx->tarFH) == EOF)
- die_horribly(AH, modulename,
+ exit_horribly(modulename,
"could not write null block at end of tar archive\n");
}
}
char *sfx;
if (oid == 0)
- die_horribly(AH, modulename, "invalid OID for large object (%u)\n", oid);
+ exit_horribly(modulename, "invalid OID for large object (%u)\n", oid);
if (AH->compression != 0)
sfx = ".gz";
* because pgoff_t can't exceed the compared maximum on their platform.
*/
if (th->fileLen > MAX_TAR_MEMBER_FILELEN)
- die_horribly(AH, modulename, "archive member too large for tar format\n");
+ exit_horribly(modulename, "archive member too large for tar format\n");
_tarWriteHeader(th);
{
res = fwrite(buf, 1, cnt, th->tarFH);
if (res != cnt)
- die_horribly(AH, modulename,
- "could not write to output file: %s\n",
- strerror(errno));
+ exit_horribly(modulename,
+ "could not write to output file: %s\n",
+ strerror(errno));
len += res;
}
if (fclose(tmp) != 0) /* This *should* delete it... */
- die_horribly(AH, modulename, "could not close temporary file: %s\n",
- strerror(errno));
+ exit_horribly(modulename, "could not close temporary file: %s\n",
+ strerror(errno));
if (len != th->fileLen)
{
snprintf(buf1, sizeof(buf1), INT64_FORMAT, (int64) len);
snprintf(buf2, sizeof(buf2), INT64_FORMAT, (int64) th->fileLen);
- die_horribly(AH, modulename, "actual file length (%s) does not match expected (%s)\n",
- buf1, buf2);
+ exit_horribly(modulename, "actual file length (%s) does not match expected (%s)\n",
+ buf1, buf2);
}
pad = ((len + 511) & ~511) - len;
for (i = 0; i < pad; i++)
{
if (fputc('\0', th->tarFH) == EOF)
- die_horribly(AH, modulename, "could not output padding at end of tar member\n");
+ exit_horribly(modulename, "could not output padding at end of tar member\n");
}
ctx->tarFHpos += len + pad;
if (!_tarGetHeader(AH, th))
{
if (filename)
- die_horribly(AH, modulename, "could not find header for file \"%s\" in tar archive\n", filename);
+ exit_horribly(modulename, "could not find header for file \"%s\" in tar archive\n", filename);
else
{
/*
id = atoi(th->targetFile);
if ((TocIDRequired(AH, id, AH->ropt) & REQ_DATA) != 0)
- die_horribly(AH, modulename, "restoring data out of order is not supported in this archive format: "
- "\"%s\" is required, but comes before \"%s\" in the archive file.\n",
- th->targetFile, filename);
+ exit_horribly(modulename, "restoring data out of order is not supported in this archive format: "
+ "\"%s\" is required, but comes before \"%s\" in the archive file.\n",
+ th->targetFile, filename);
/* Header doesn't match, so read to next header */
len = ((th->fileLen + 511) & ~511); /* Padded length */
_tarReadRaw(AH, &header[0], 512, NULL, ctx->tarFH);
if (!_tarGetHeader(AH, th))
- die_horribly(AH, modulename, "could not find header for file \"%s\" in tar archive\n", filename);
+ exit_horribly(modulename, "could not find header for file \"%s\" in tar archive\n", filename);
}
ctx->tarNextMember = ctx->tarFHpos + ((th->fileLen + 511) & ~511);
snprintf(buf1, sizeof(buf1), INT64_FORMAT, (int64) ftello(ctx->tarFH));
snprintf(buf2, sizeof(buf2), INT64_FORMAT, (int64) ftello(ctx->tarFHpos));
- die_horribly(AH, modulename,
+ exit_horribly(modulename,
"mismatch in actual vs. predicted file position (%s vs. %s)\n",
buf1, buf2);
}
return 0;
if (len != 512)
- die_horribly(AH, modulename,
- ngettext("incomplete tar header found (%lu byte)\n",
- "incomplete tar header found (%lu bytes)\n",
- len),
- (unsigned long) len);
+ exit_horribly(modulename,
+ ngettext("incomplete tar header found (%lu byte)\n",
+ "incomplete tar header found (%lu bytes)\n",
+ len),
+ (unsigned long) len);
/* Calc checksum */
chk = _tarChecksum(h);
char buf[100];
snprintf(buf, sizeof(buf), INT64_FORMAT, (int64) ftello(ctx->tarFH));
- die_horribly(AH, modulename,
- "corrupt tar header found in %s "
- "(expected %d, computed %d) file position %s\n",
- tag, sum, chk, buf);
+ exit_horribly(modulename,
+ "corrupt tar header found in %s "
+ "(expected %d, computed %d) file position %s\n",
+ tag, sum, chk, buf);
}
th->targetFile = pg_strdup(tag);
}
if (fwrite(h, 1, 512, th->tarFH) != 512)
- die_horribly(th->AH, modulename, "could not write to output file: %s\n", strerror(errno));
+ exit_horribly(modulename, "could not write to output file: %s\n", strerror(errno));
}
static void help(const char *progname);
-static void pgdump_cleanup_at_exit(int code, void *arg);
static void setup_connection(Archive *AH, const char *dumpencoding,
char *use_role);
static ArchiveFormat parseArchiveFormat(const char *format, ArchiveMode *mode);
/* Open the output file */
fout = CreateArchive(filename, archiveFormat, compressLevel, archiveMode);
- on_exit_nicely(pgdump_cleanup_at_exit, fout);
+
+ /* Register the cleanup hook */
+ on_exit_close_archive(fout);
if (fout == NULL)
exit_horribly(NULL, "could not open output file \"%s\" for writing\n", filename);
printf(_("Report bugs to <pgsql-bugs@postgresql.org>.\n"));
}
-static void
-pgdump_cleanup_at_exit(int code, void *arg)
-{
- Archive *AH = (Archive *) arg;
-
- DisconnectDatabase(AH);
-}
-
static void
setup_connection(Archive *AH, const char *dumpencoding, char *use_role)
{
AH = OpenArchive(inputFileSpec, opts->format);
+ /*
+ * We don't have a connection yet but that doesn't matter. The connection
+ * is initialized to NULL and if we terminate through exit_nicely() while
+ * it's still NULL, the cleanup function will just be a no-op.
+ */
+ on_exit_close_archive(AH);
+
/* Let the archiver know how noisy to be */
AH->verbose = opts->verbose;