Commit 4d14fe00 authored by Tom Lane's avatar Tom Lane

XLOG (and related) changes:

* Store two past checkpoint locations, not just one, in pg_control.
  On startup, we fall back to the older checkpoint if the newer one
  is unreadable.  Also, a physical copy of the newest checkpoint record
  is kept in pg_control for possible use in disaster recovery (ie,
  complete loss of pg_xlog).  Also add a version number for pg_control
  itself.  Remove archdir from pg_control; it ought to be a GUC
  parameter, not a special case (not that it's implemented yet anyway).

* Suppress successive checkpoint records when nothing has been entered
  in the WAL log since the last one.  This is not so much to avoid I/O
  as to make it actually useful to keep track of the last two
  checkpoints.  If the things are right next to each other then there's
  not a lot of redundancy gained...

* Change CRC scheme to a true 64-bit CRC, not a pair of 32-bit CRCs
  on alternate bytes.  Polynomial borrowed from ECMA DLT1 standard.

* Fix XLOG record length handling so that it will work at BLCKSZ = 32k.

* Change XID allocation to work more like OID allocation.  (This is of
  dubious necessity, but I think it's a good idea anyway.)

* Fix a number of minor bugs, such as off-by-one logic for XLOG file
  wraparound at the 4 gig mark.

* Add documentation and clean up some coding infelicities; move file
  format declarations out to include files where planned contrib
  utilities can get at them.

* Checkpoint will now occur every CHECKPOINT_SEGMENTS log segments or
  every CHECKPOINT_TIMEOUT seconds, whichever comes first.  It is also
  possible to force a checkpoint by sending SIGUSR1 to the postmaster
  (undocumented feature...)

* Defend against kill -9 postmaster by storing shmem block's key and ID
  in postmaster.pid lockfile, and checking at startup to ensure that no
  processes are still connected to old shmem block (if it still exists).

* Switch backends to accept SIGQUIT rather than SIGUSR1 for emergency
  stop, for symmetry with postmaster and xlog utilities.  Clean up signal
  handling in bootstrap.c so that xlog utilities launched by postmaster
  will react to signals better.

* Standalone bootstrap now grabs lockfile in target directory, as added
  insurance against running it in parallel with live postmaster.
parent b246510c
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/checkpoint.sgml,v 1.3 2001/01/27 10:19:52 petere Exp $ --> <!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/checkpoint.sgml,v 1.4 2001/03/13 01:17:05 tgl Exp $ -->
<refentry id="sql-checkpoint"> <refentry id="sql-checkpoint">
<docinfo> <docinfo>
...@@ -26,11 +26,12 @@ CHECKPOINT ...@@ -26,11 +26,12 @@ CHECKPOINT
<para> <para>
Write-Ahead Logging (WAL) puts a checkpoint in the transaction log Write-Ahead Logging (WAL) puts a checkpoint in the transaction log
every 300 seconds by default. (This may be changed by the run-time every so often. (To adjust the automatic checkpoint interval, see
configuration option <parameter>CHECKPOINT_TIMEOUT</parameter>.) the run-time
The <command>CHECKPOINT</command> command forces a checkpoint at configuration options <parameter>CHECKPOINT_SEGMENTS</parameter>
the point at which the command is issued. The next automatic and <parameter>CHECKPOINT_TIMEOUT</parameter>.)
checkpoint will still happen after the original cycle expires. The <command>CHECKPOINT</command> command forces an immediate checkpoint
when the command is issued, without waiting for a scheduled checkpoint.
</para> </para>
<para> <para>
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.55 2001/02/18 05:30:12 tgl Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.56 2001/03/13 01:17:05 tgl Exp $
--> -->
<Chapter Id="runtime"> <Chapter Id="runtime">
...@@ -976,6 +976,11 @@ env PGOPTIONS='-c geqo=off' psql ...@@ -976,6 +976,11 @@ env PGOPTIONS='-c geqo=off' psql
fsyncs because of performance problems, you may wish to reconsider fsyncs because of performance problems, you may wish to reconsider
your choice. your choice.
</para> </para>
<para>
This option can only be set at server start or in the
<filename>postgresql.conf</filename> file.
</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
...@@ -1192,11 +1197,25 @@ env PGOPTIONS='-c geqo=off' psql ...@@ -1192,11 +1197,25 @@ env PGOPTIONS='-c geqo=off' psql
tuning. tuning.
<variablelist> <variablelist>
<varlistentry>
<term>CHECKPOINT_SEGMENTS (<type>integer</type>)</term>
<listitem>
<para>
Maximum distance between automatic WAL checkpoints, in logfile
segments (each segment is normally 16 megabytes).
This option can only be set at server start or in the
<filename>postgresql.conf</filename> file.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term>CHECKPOINT_TIMEOUT (<type>integer</type>)</term> <term>CHECKPOINT_TIMEOUT (<type>integer</type>)</term>
<listitem> <listitem>
<para> <para>
Frequency of automatic WAL checkpoints, in seconds. Maximum time between automatic WAL checkpoints, in seconds.
This option can only be set at server start or in the
<filename>postgresql.conf</filename> file.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
...@@ -1205,8 +1224,8 @@ env PGOPTIONS='-c geqo=off' psql ...@@ -1205,8 +1224,8 @@ env PGOPTIONS='-c geqo=off' psql
<term>WAL_BUFFERS (<type>integer</type>)</term> <term>WAL_BUFFERS (<type>integer</type>)</term>
<listitem> <listitem>
<para> <para>
Number of buffers for WAL. This option can only be set at Number of disk-page buffers for WAL log. This option can only be set
server start. at server start.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
...@@ -1226,7 +1245,8 @@ env PGOPTIONS='-c geqo=off' psql ...@@ -1226,7 +1245,8 @@ env PGOPTIONS='-c geqo=off' psql
<listitem> <listitem>
<para> <para>
Number of log files that are created in advance at checkpoint Number of log files that are created in advance at checkpoint
time. This option can only be set at server start. time. This option can only be set at server start or in the
<filename>postgresql.conf</filename> file.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
...@@ -1909,7 +1929,7 @@ default:\ ...@@ -1909,7 +1929,7 @@ default:\
<listitem> <listitem>
<para> <para>
This is the <firstterm>Immediate Shutdown</firstterm> which This is the <firstterm>Immediate Shutdown</firstterm> which
will cause the postmaster to send a SIGUSR1 to all backends and will cause the postmaster to send a SIGQUIT to all backends and
exit immediately (without properly shutting down the database exit immediately (without properly shutting down the database
system). When WAL is implemented, this will lead to recovery on system). When WAL is implemented, this will lead to recovery on
start-up. Right now it's not recommendable to use this option. start-up. Right now it's not recommendable to use this option.
......
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/wal.sgml,v 1.3 2001/02/26 00:50:07 tgl Exp $ --> <!-- $Header: /cvsroot/pgsql/doc/src/sgml/wal.sgml,v 1.4 2001/03/13 01:17:05 tgl Exp $ -->
<chapter id="wal"> <chapter id="wal">
<title>Write-Ahead Logging (<acronym>WAL</acronym>)</title> <title>Write-Ahead Logging (<acronym>WAL</acronym>)</title>
...@@ -257,7 +257,7 @@ ...@@ -257,7 +257,7 @@
The <acronym>WAL</acronym> log is held on the disk as a set of 16 The <acronym>WAL</acronym> log is held on the disk as a set of 16
MB files called <firstterm>segments</firstterm>. By default a new MB files called <firstterm>segments</firstterm>. By default a new
segment is created only if more than 75% of the current segment is segment is created only if more than 75% of the current segment is
used. One can instruct the server to create up to 64 log segments used. One can instruct the server to pre-create up to 64 log segments
at checkpoint time by modifying the <varname>WAL_FILES</varname> at checkpoint time by modifying the <varname>WAL_FILES</varname>
configuration parameter. configuration parameter.
</para> </para>
...@@ -272,11 +272,12 @@ ...@@ -272,11 +272,12 @@
</para> </para>
<para> <para>
By default, the postmaster spawns a special backend process to The postmaster spawns a special backend process every so often
create the next checkpoint 300 seconds after the previous to create the next checkpoint. A checkpoint is created every
checkpoint's creation. One can change this interval by modifying <varname>CHECKPOINT_SEGMENTS</varname> log segments, or every
the <varname>CHECKPOINT_TIMEOUT</varname> parameter. It is also <varname>CHECKPOINT_TIMEOUT</varname> seconds, whichever comes first.
possible to force a checkpoint by using the SQL command The default settings are 3 segments and 300 seconds respectively.
It is also possible to force a checkpoint by using the SQL command
<command>CHECKPOINT</command>. <command>CHECKPOINT</command>.
</para> </para>
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/transam/transam.c,v 1.39 2001/01/24 19:42:51 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/transam/transam.c,v 1.40 2001/03/13 01:17:05 tgl Exp $
* *
* NOTES * NOTES
* This file contains the high level access-method interface to the * This file contains the high level access-method interface to the
...@@ -430,6 +430,7 @@ InitializeTransactionLog(void) ...@@ -430,6 +430,7 @@ InitializeTransactionLog(void)
Assert(!IsUnderPostmaster && Assert(!IsUnderPostmaster &&
ShmemVariableCache->nextXid <= FirstTransactionId); ShmemVariableCache->nextXid <= FirstTransactionId);
ShmemVariableCache->nextXid = FirstTransactionId; ShmemVariableCache->nextXid = FirstTransactionId;
ShmemVariableCache->xidCount = 0; /* force an XLOG rec right away */
} }
else if (RecoveryCheckingEnabled()) else if (RecoveryCheckingEnabled())
{ {
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Copyright (c) 2000, PostgreSQL Global Development Group * Copyright (c) 2000, PostgreSQL Global Development Group
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/transam/varsup.c,v 1.35 2001/01/24 19:42:51 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/transam/varsup.c,v 1.36 2001/03/13 01:17:05 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -14,12 +14,17 @@ ...@@ -14,12 +14,17 @@
#include "postgres.h" #include "postgres.h"
#include "access/transam.h" #include "access/transam.h"
#include "access/xlog.h"
#include "storage/proc.h" #include "storage/proc.h"
SPINLOCK OidGenLockId;
extern SPINLOCK XidGenLockId; /* Number of XIDs and OIDs to prefetch (preallocate) per XLOG write */
extern void XLogPutNextOid(Oid nextOid); #define VAR_XID_PREFETCH 1024
#define VAR_OID_PREFETCH 8192
/* Spinlocks for serializing generation of XIDs and OIDs, respectively */
SPINLOCK XidGenLockId;
SPINLOCK OidGenLockId;
/* pointer to "variable cache" in shared memory (set up by shmem.c) */ /* pointer to "variable cache" in shared memory (set up by shmem.c) */
VariableCache ShmemVariableCache = NULL; VariableCache ShmemVariableCache = NULL;
...@@ -38,23 +43,31 @@ GetNewTransactionId(TransactionId *xid) ...@@ -38,23 +43,31 @@ GetNewTransactionId(TransactionId *xid)
} }
SpinAcquire(XidGenLockId); SpinAcquire(XidGenLockId);
/* If we run out of logged for use xids then we must log more */
if (ShmemVariableCache->xidCount == 0)
{
XLogPutNextXid(ShmemVariableCache->nextXid + VAR_XID_PREFETCH);
ShmemVariableCache->xidCount = VAR_XID_PREFETCH;
}
*xid = ShmemVariableCache->nextXid; *xid = ShmemVariableCache->nextXid;
(ShmemVariableCache->nextXid)++;
if (MyProc != (PROC *) NULL) (ShmemVariableCache->nextXid)++;
MyProc->xid = *xid; (ShmemVariableCache->xidCount)--;
SpinRelease(XidGenLockId); SpinRelease(XidGenLockId);
if (MyProc != (PROC *) NULL)
MyProc->xid = *xid;
} }
/* /*
* Like GetNewTransactionId reads nextXid but don't fetch it. * Read nextXid but don't allocate it.
*/ */
void void
ReadNewTransactionId(TransactionId *xid) ReadNewTransactionId(TransactionId *xid)
{ {
/* /*
* During bootstrap initialization, we return the special * During bootstrap initialization, we return the special
* bootstrap transaction id. * bootstrap transaction id.
...@@ -68,7 +81,6 @@ ReadNewTransactionId(TransactionId *xid) ...@@ -68,7 +81,6 @@ ReadNewTransactionId(TransactionId *xid)
SpinAcquire(XidGenLockId); SpinAcquire(XidGenLockId);
*xid = ShmemVariableCache->nextXid; *xid = ShmemVariableCache->nextXid;
SpinRelease(XidGenLockId); SpinRelease(XidGenLockId);
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -76,7 +88,6 @@ ReadNewTransactionId(TransactionId *xid) ...@@ -76,7 +88,6 @@ ReadNewTransactionId(TransactionId *xid)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
#define VAR_OID_PREFETCH 8192
static Oid lastSeenOid = InvalidOid; static Oid lastSeenOid = InvalidOid;
void void
...@@ -84,7 +95,7 @@ GetNewObjectId(Oid *oid_return) ...@@ -84,7 +95,7 @@ GetNewObjectId(Oid *oid_return)
{ {
SpinAcquire(OidGenLockId); SpinAcquire(OidGenLockId);
/* If we run out of logged for use oids then we log more */ /* If we run out of logged for use oids then we must log more */
if (ShmemVariableCache->oidCount == 0) if (ShmemVariableCache->oidCount == 0)
{ {
XLogPutNextOid(ShmemVariableCache->nextOid + VAR_OID_PREFETCH); XLogPutNextOid(ShmemVariableCache->nextOid + VAR_OID_PREFETCH);
...@@ -103,11 +114,11 @@ GetNewObjectId(Oid *oid_return) ...@@ -103,11 +114,11 @@ GetNewObjectId(Oid *oid_return)
void void
CheckMaxObjectId(Oid assigned_oid) CheckMaxObjectId(Oid assigned_oid)
{ {
if (lastSeenOid != InvalidOid && assigned_oid < lastSeenOid) if (lastSeenOid != InvalidOid && assigned_oid < lastSeenOid)
return; return;
SpinAcquire(OidGenLockId); SpinAcquire(OidGenLockId);
if (assigned_oid < ShmemVariableCache->nextOid) if (assigned_oid < ShmemVariableCache->nextOid)
{ {
lastSeenOid = ShmemVariableCache->nextOid - 1; lastSeenOid = ShmemVariableCache->nextOid - 1;
...@@ -138,5 +149,4 @@ CheckMaxObjectId(Oid assigned_oid) ...@@ -138,5 +149,4 @@ CheckMaxObjectId(Oid assigned_oid)
ShmemVariableCache->nextOid = assigned_oid + 1; ShmemVariableCache->nextOid = assigned_oid + 1;
SpinRelease(OidGenLockId); SpinRelease(OidGenLockId);
} }
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.98 2001/02/26 00:50:07 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.99 2001/03/13 01:17:05 tgl Exp $
* *
* NOTES * NOTES
* Transaction aborts can now occur two ways: * Transaction aborts can now occur two ways:
...@@ -706,14 +706,18 @@ RecordTransactionCommit() ...@@ -706,14 +706,18 @@ RecordTransactionCommit()
} }
XLogFlush(recptr); XLogFlush(recptr);
/* Break the chain of back-links in the XLOG records I output */
MyLastRecPtr.xrecoff = 0; MyLastRecPtr.xrecoff = 0;
TransactionIdCommit(xid); TransactionIdCommit(xid);
MyProc->logRec.xrecoff = 0;
END_CRIT_SECTION(); END_CRIT_SECTION();
} }
/* Show myself as out of the transaction in PROC array */
MyProc->logRec.xrecoff = 0;
if (leak) if (leak)
ResetBufferPool(true); ResetBufferPool(true);
} }
...@@ -802,6 +806,10 @@ RecordTransactionAbort(void) ...@@ -802,6 +806,10 @@ RecordTransactionAbort(void)
{ {
TransactionId xid = GetCurrentTransactionId(); TransactionId xid = GetCurrentTransactionId();
/*
* Double check here is to catch case that we aborted partway through
* RecordTransactionCommit ...
*/
if (MyLastRecPtr.xrecoff != 0 && !TransactionIdDidCommit(xid)) if (MyLastRecPtr.xrecoff != 0 && !TransactionIdDidCommit(xid))
{ {
XLogRecData rdata; XLogRecData rdata;
...@@ -815,13 +823,19 @@ RecordTransactionAbort(void) ...@@ -815,13 +823,19 @@ RecordTransactionAbort(void)
rdata.next = NULL; rdata.next = NULL;
START_CRIT_SECTION(); START_CRIT_SECTION();
recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, &rdata); recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, &rdata);
TransactionIdAbort(xid); TransactionIdAbort(xid);
MyProc->logRec.xrecoff = 0;
END_CRIT_SECTION(); END_CRIT_SECTION();
} }
/* Break the chain of back-links in the XLOG records I output */
MyLastRecPtr.xrecoff = 0;
/* Show myself as out of the transaction in PROC array */
MyProc->logRec.xrecoff = 0;
/* /*
* Tell bufmgr and smgr to release resources. * Tell bufmgr and smgr to release resources.
*/ */
...@@ -1187,10 +1201,6 @@ AbortTransaction(void) ...@@ -1187,10 +1201,6 @@ AbortTransaction(void)
AtEOXact_CatCache(false); AtEOXact_CatCache(false);
AtAbort_Memory(); AtAbort_Memory();
AtEOXact_Files(); AtEOXact_Files();
/* Here we'll rollback xaction changes */
MyLastRecPtr.xrecoff = 0;
AtAbort_Locks(); AtAbort_Locks();
SharedBufferChanged = false; /* safest place to do it */ SharedBufferChanged = false; /* safest place to do it */
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -6,10 +6,12 @@ ...@@ -6,10 +6,12 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Header: /cvsroot/pgsql/src/backend/access/transam/xlogutils.c,v 1.14 2001/03/13 01:17:05 tgl Exp $
*
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include "postgres.h" #include "postgres.h"
#include "access/xlog.h" #include "access/xlog.h"
#include "access/transam.h" #include "access/transam.h"
#include "access/xact.h" #include "access/xact.h"
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.104 2001/01/24 19:42:51 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.105 2001/03/13 01:17:05 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -18,13 +18,12 @@ ...@@ -18,13 +18,12 @@
#include <time.h> #include <time.h>
#include <signal.h> #include <signal.h>
#include <setjmp.h> #include <setjmp.h>
#define BOOTSTRAP_INCLUDE /* mask out stuff in tcop/tcopprot.h */
#ifdef HAVE_GETOPT_H #ifdef HAVE_GETOPT_H
#include <getopt.h> #include <getopt.h>
#endif #endif
#define BOOTSTRAP_INCLUDE /* mask out stuff in tcop/tcopprot.h */
#include "access/genam.h" #include "access/genam.h"
#include "access/heapam.h" #include "access/heapam.h"
#include "access/xlog.h" #include "access/xlog.h"
...@@ -147,8 +146,6 @@ static MemoryContext nogc = NULL; /* special no-gc mem context */ ...@@ -147,8 +146,6 @@ static MemoryContext nogc = NULL; /* special no-gc mem context */
extern int optind; extern int optind;
extern char *optarg; extern char *optarg;
extern void SetRedoRecPtr(void);
/* /*
* At bootstrap time, we first declare all the indices to be built, and * At bootstrap time, we first declare all the indices to be built, and
* then build them. The IndexList structure stores enough information * then build them. The IndexList structure stores enough information
...@@ -294,8 +291,16 @@ BootstrapMain(int argc, char *argv[]) ...@@ -294,8 +291,16 @@ BootstrapMain(int argc, char *argv[])
else if (argc - optind == 1) else if (argc - optind == 1)
dbName = argv[optind]; dbName = argv[optind];
SetProcessingMode(BootstrapProcessing); if (dbName == NULL)
IgnoreSystemIndexes(true); {
dbName = getenv("USER");
if (dbName == NULL)
{
fputs("bootstrap backend: failed, no db name specified\n", stderr);
fputs(" and no USER enviroment variable\n", stderr);
proc_exit(1);
}
}
if (!IsUnderPostmaster) if (!IsUnderPostmaster)
{ {
...@@ -312,29 +317,52 @@ BootstrapMain(int argc, char *argv[]) ...@@ -312,29 +317,52 @@ BootstrapMain(int argc, char *argv[])
} }
Assert(DataDir); Assert(DataDir);
if (dbName == NULL) if (IsUnderPostmaster)
{ {
dbName = getenv("USER"); /*
if (dbName == NULL) * Properly accept or ignore signals the postmaster might send us
{ */
fputs("bootstrap backend: failed, no db name specified\n", stderr); pqsignal(SIGHUP, SIG_IGN);
fputs(" and no USER enviroment variable\n", stderr); pqsignal(SIGINT, SIG_IGN); /* ignore query-cancel */
proc_exit(1); pqsignal(SIGTERM, die);
} pqsignal(SIGQUIT, quickdie);
pqsignal(SIGUSR1, SIG_IGN);
pqsignal(SIGUSR2, SIG_IGN);
/*
* Reset some signals that are accepted by postmaster but not here
*/
pqsignal(SIGCHLD, SIG_IGN);
pqsignal(SIGTTIN, SIG_DFL);
pqsignal(SIGTTOU, SIG_DFL);
pqsignal(SIGCONT, SIG_DFL);
pqsignal(SIGWINCH, SIG_DFL);
/*
* Unblock signals (they were blocked when the postmaster forked us)
*/
PG_SETMASK(&UnBlockSig);
} }
else
XLOGPathInit();
BaseInit();
if (!IsUnderPostmaster)
{ {
/* Set up appropriately for interactive use */
pqsignal(SIGHUP, die); pqsignal(SIGHUP, die);
pqsignal(SIGINT, die); pqsignal(SIGINT, die);
pqsignal(SIGTERM, die); pqsignal(SIGTERM, die);
pqsignal(SIGQUIT, die); pqsignal(SIGQUIT, die);
/*
* Create lockfile for data directory.
*/
if (! CreateDataDirLockFile(DataDir, false))
proc_exit(1);
} }
SetProcessingMode(BootstrapProcessing);
IgnoreSystemIndexes(true);
XLOGPathInit();
BaseInit();
/* /*
* XLOG operations * XLOG operations
*/ */
......
...@@ -57,12 +57,25 @@ int* shmat(int memId,int m1,int m2) ...@@ -57,12 +57,25 @@ int* shmat(int memId,int m1,int m2)
} }
} }
/* Control a shared mem area : Used only to delete it */ /* Control a shared mem area */
int shmctl(int shmid,int flag, struct shmid_ds* dummy) int shmctl(int shmid, int flag, struct shmid_ds* dummy)
{ {
/* Delete the area */ if (flag == IPC_RMID)
delete_area(shmid); {
return 0; /* Delete the area */
delete_area(shmid);
return 0;
}
if (flag == IPC_STAT)
{
/* Is there a way to check existence of an area given its ID?
* For now, punt and assume it does not exist.
*/
errno = EINVAL;
return -1;
}
errno = EINVAL;
return -1;
} }
/* Get an area based on the IPC key */ /* Get an area based on the IPC key */
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/port/qnx4/Attic/shm.c,v 1.2 2000/04/12 17:15:30 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/port/qnx4/Attic/shm.c,v 1.3 2001/03/13 01:17:06 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -173,20 +173,25 @@ shmctl(int shmid, int cmd, struct shmid_ds * buf) ...@@ -173,20 +173,25 @@ shmctl(int shmid, int cmd, struct shmid_ds * buf)
struct shm_info info; struct shm_info info;
char name[NAME_MAX + 1]; char name[NAME_MAX + 1];
/* IPC_RMID supported only */ if (cmd == IPC_RMID)
if (cmd != IPC_RMID)
{ {
errno = EINVAL; if (shm_getinfo(shmid, &info) == -1)
return -1; {
errno = EACCES;
return -1;
}
return shm_unlink(itoa(info.key, name, 16));
} }
if (cmd == IPC_STAT)
if (shm_getinfo(shmid, &info) == -1)
{ {
errno = EACCES; /* Can we support IPC_STAT? We only need shm_nattch ...
* For now, punt and assume the shm seg does not exist.
*/
errno = EINVAL;
return -1; return -1;
} }
errno = EINVAL;
return shm_unlink(itoa(info.key, name, 16)); return -1;
} }
int int
......
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipc.c,v 1.62 2001/01/24 19:43:07 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipc.c,v 1.63 2001/03/13 01:17:06 tgl Exp $
* *
* NOTES * NOTES
* *
...@@ -626,6 +626,9 @@ InternalIpcMemoryCreate(IpcMemoryKey memKey, uint32 size, int permission) ...@@ -626,6 +626,9 @@ InternalIpcMemoryCreate(IpcMemoryKey memKey, uint32 size, int permission)
/* Register on-exit routine to detach new segment before deleting */ /* Register on-exit routine to detach new segment before deleting */
on_shmem_exit(IpcMemoryDetach, PointerGetDatum(memAddress)); on_shmem_exit(IpcMemoryDetach, PointerGetDatum(memAddress));
/* Record key and ID in lockfile for data directory. */
RecordSharedMemoryInLockFile(memKey, shmid);
return memAddress; return memAddress;
} }
...@@ -660,6 +663,41 @@ IpcMemoryDelete(int status, Datum shmId) ...@@ -660,6 +663,41 @@ IpcMemoryDelete(int status, Datum shmId)
*/ */
} }
/****************************************************************************/
/* SharedMemoryIsInUse(shmKey, shmId) Is a shared memory segment in use? */
/****************************************************************************/
bool
SharedMemoryIsInUse(IpcMemoryKey shmKey, IpcMemoryId shmId)
{
struct shmid_ds shmStat;
/*
* We detect whether a shared memory segment is in use by seeing whether
* it (a) exists and (b) has any processes are attached to it.
*
* If we are unable to perform the stat operation for a reason other than
* nonexistence of the segment (most likely, because it doesn't belong to
* our userid), assume it is in use.
*/
if (shmctl(shmId, IPC_STAT, &shmStat) < 0)
{
/*
* EINVAL actually has multiple possible causes documented in the
* shmctl man page, but we assume it must mean the segment no longer
* exists.
*/
if (errno == EINVAL)
return false;
/* Else assume segment is in use */
return true;
}
/* If it has attached processes, it's in use */
if (shmStat.shm_nattch != 0)
return true;
return false;
}
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* private memory support * private memory support
* *
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.209 2001/03/09 06:36:32 inoue Exp $ * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.210 2001/03/13 01:17:06 tgl Exp $
* *
* NOTES * NOTES
* this is the "main" module of the postgres backend and * this is the "main" module of the postgres backend and
...@@ -128,7 +128,6 @@ static void start_xact_command(void); ...@@ -128,7 +128,6 @@ static void start_xact_command(void);
static void finish_xact_command(void); static void finish_xact_command(void);
static void SigHupHandler(SIGNAL_ARGS); static void SigHupHandler(SIGNAL_ARGS);
static void FloatExceptionHandler(SIGNAL_ARGS); static void FloatExceptionHandler(SIGNAL_ARGS);
static void quickdie(SIGNAL_ARGS);
/* /*
* Flag to mark SIGHUP. Whenever the main loop comes around it * Flag to mark SIGHUP. Whenever the main loop comes around it
...@@ -895,12 +894,12 @@ finish_xact_command(void) ...@@ -895,12 +894,12 @@ finish_xact_command(void)
*/ */
/* /*
* quickdie() occurs when signalled SIGUSR1 by the postmaster. * quickdie() occurs when signalled SIGQUIT by the postmaster.
* *
* Some backend has bought the farm, * Some backend has bought the farm,
* so we need to stop what we're doing and exit. * so we need to stop what we're doing and exit.
*/ */
static void void
quickdie(SIGNAL_ARGS) quickdie(SIGNAL_ARGS)
{ {
PG_SETMASK(&BlockSig); PG_SETMASK(&BlockSig);
...@@ -917,7 +916,7 @@ quickdie(SIGNAL_ARGS) ...@@ -917,7 +916,7 @@ quickdie(SIGNAL_ARGS)
* Just nail the windows shut and get out of town. * Just nail the windows shut and get out of town.
* *
* Note we do exit(1) not exit(0). This is to force the postmaster * Note we do exit(1) not exit(0). This is to force the postmaster
* into a system reset cycle if some idiot DBA sends a manual SIGUSR1 * into a system reset cycle if some idiot DBA sends a manual SIGQUIT
* to a random backend. This is necessary precisely because we don't * to a random backend. This is necessary precisely because we don't
* clean up our shared memory state. * clean up our shared memory state.
*/ */
...@@ -987,8 +986,8 @@ QueryCancelHandler(SIGNAL_ARGS) ...@@ -987,8 +986,8 @@ QueryCancelHandler(SIGNAL_ARGS)
InterruptHoldoffCount++; InterruptHoldoffCount++;
if (LockWaitCancel()) if (LockWaitCancel())
{ {
InterruptHoldoffCount--;
DisableNotifyInterrupt(); DisableNotifyInterrupt();
InterruptHoldoffCount--;
ProcessInterrupts(); ProcessInterrupts();
} }
else else
...@@ -1205,9 +1204,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha ...@@ -1205,9 +1204,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
case 'D': /* PGDATA directory */ case 'D': /* PGDATA directory */
if (secure) if (secure)
{
potential_DataDir = optarg; potential_DataDir = optarg;
}
break; break;
case 'd': /* debug level */ case 'd': /* debug level */
...@@ -1243,13 +1240,10 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha ...@@ -1243,13 +1240,10 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
case 'F': case 'F':
/* -------------------- /* --------------------
* turn off fsync * turn off fsync
*
* 7.0 buffer manager can support different backends running
* with different fsync settings, so this no longer needs
* to be "if (secure)".
* -------------------- * --------------------
*/ */
enableFsync = false; if (secure)
enableFsync = false;
break; break;
case 'f': case 'f':
...@@ -1504,13 +1498,18 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha ...@@ -1504,13 +1498,18 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
* Note that postmaster blocked all signals before forking child process, * Note that postmaster blocked all signals before forking child process,
* so there is no race condition whereby we might receive a signal before * so there is no race condition whereby we might receive a signal before
* we have set up the handler. * we have set up the handler.
*
* Also note: it's best not to use any signals that are SIG_IGNored in
* the postmaster. If such a signal arrives before we are able to change
* the handler to non-SIG_IGN, it'll get dropped. If necessary, make a
* dummy handler in the postmaster to reserve the signal.
*/ */
pqsignal(SIGHUP, SigHupHandler); /* set flag to read config file */ pqsignal(SIGHUP, SigHupHandler); /* set flag to read config file */
pqsignal(SIGINT, QueryCancelHandler); /* cancel current query */ pqsignal(SIGINT, QueryCancelHandler); /* cancel current query */
pqsignal(SIGTERM, die); /* cancel current query and exit */ pqsignal(SIGTERM, die); /* cancel current query and exit */
pqsignal(SIGQUIT, die); /* could reassign this sig for another use */ pqsignal(SIGQUIT, quickdie); /* hard crash time */
pqsignal(SIGALRM, HandleDeadLock); pqsignal(SIGALRM, HandleDeadLock); /* check for deadlock after timeout */
/* /*
* Ignore failure to write to frontend. Note: if frontend closes * Ignore failure to write to frontend. Note: if frontend closes
...@@ -1519,7 +1518,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha ...@@ -1519,7 +1518,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
* midst of output during who-knows-what operation... * midst of output during who-knows-what operation...
*/ */
pqsignal(SIGPIPE, SIG_IGN); pqsignal(SIGPIPE, SIG_IGN);
pqsignal(SIGUSR1, quickdie); pqsignal(SIGUSR1, SIG_IGN); /* this signal available for use */
pqsignal(SIGUSR2, Async_NotifyHandler); /* flush also sinval cache */ pqsignal(SIGUSR2, Async_NotifyHandler); /* flush also sinval cache */
pqsignal(SIGFPE, FloatExceptionHandler); pqsignal(SIGFPE, FloatExceptionHandler);
pqsignal(SIGCHLD, SIG_IGN); /* ignored (may get this in system() calls) */ pqsignal(SIGCHLD, SIG_IGN); /* ignored (may get this in system() calls) */
...@@ -1534,14 +1533,14 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha ...@@ -1534,14 +1533,14 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
pqinitmask(); pqinitmask();
/* We allow SIGUSR1 (quickdie) at all times */ /* We allow SIGQUIT (quickdie) at all times */
#ifdef HAVE_SIGPROCMASK #ifdef HAVE_SIGPROCMASK
sigdelset(&BlockSig, SIGUSR1); sigdelset(&BlockSig, SIGQUIT);
#else #else
BlockSig &= ~(sigmask(SIGUSR1)); BlockSig &= ~(sigmask(SIGQUIT));
#endif #endif
PG_SETMASK(&BlockSig); /* block everything except SIGUSR1 */ PG_SETMASK(&BlockSig); /* block everything except SIGQUIT */
if (IsUnderPostmaster) if (IsUnderPostmaster)
...@@ -1693,7 +1692,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha ...@@ -1693,7 +1692,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
if (!IsUnderPostmaster) if (!IsUnderPostmaster)
{ {
puts("\nPOSTGRES backend interactive interface "); puts("\nPOSTGRES backend interactive interface ");
puts("$Revision: 1.209 $ $Date: 2001/03/09 06:36:32 $\n"); puts("$Revision: 1.210 $ $Date: 2001/03/13 01:17:06 $\n");
} }
/* /*
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
# Makefile for utils/hash # Makefile for utils/hash
# #
# IDENTIFICATION # IDENTIFICATION
# $Header: /cvsroot/pgsql/src/backend/utils/hash/Makefile,v 1.9 2000/08/31 16:10:51 petere Exp $ # $Header: /cvsroot/pgsql/src/backend/utils/hash/Makefile,v 1.10 2001/03/13 01:17:06 tgl Exp $
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
...@@ -12,7 +12,7 @@ subdir = src/backend/utils/hash ...@@ -12,7 +12,7 @@ subdir = src/backend/utils/hash
top_builddir = ../../../.. top_builddir = ../../../..
include $(top_builddir)/src/Makefile.global include $(top_builddir)/src/Makefile.global
OBJS = dynahash.o hashfn.o OBJS = dynahash.o hashfn.o pg_crc.o
all: SUBSYS.o all: SUBSYS.o
......
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/init/globals.c,v 1.53 2001/01/24 19:43:16 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/init/globals.c,v 1.54 2001/03/13 01:17:06 tgl Exp $
* *
* NOTES * NOTES
* Globals used all over the place should be declared here and not * Globals used all over the place should be declared here and not
...@@ -16,14 +16,14 @@ ...@@ -16,14 +16,14 @@
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include "postgres.h"
#include <fcntl.h> #include <fcntl.h>
#include <sys/file.h> #include <sys/file.h>
#include <sys/types.h> #include <sys/types.h>
#include <math.h> #include <math.h>
#include <unistd.h> #include <unistd.h>
#include "postgres.h"
#include "catalog/catname.h" #include "catalog/catname.h"
#include "catalog/indexing.h" #include "catalog/indexing.h"
#include "libpq/pqcomm.h" #include "libpq/pqcomm.h"
...@@ -119,49 +119,3 @@ char *SharedSystemRelationNames[] = { ...@@ -119,49 +119,3 @@ char *SharedSystemRelationNames[] = {
VariableRelationName, VariableRelationName,
0 0
}; };
uint32 crc_table[] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.61 2001/01/27 00:05:31 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.62 2001/03/13 01:17:06 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -41,7 +41,8 @@ unsigned char RecodeBackTable[128]; ...@@ -41,7 +41,8 @@ unsigned char RecodeBackTable[128];
ProcessingMode Mode = InitProcessing; ProcessingMode Mode = InitProcessing;
/* Note: we rely on this to initialize as zeroes */ /* Note: we rely on these to initialize as zeroes */
static char directoryLockFile[MAXPGPATH];
static char socketLockFile[MAXPGPATH]; static char socketLockFile[MAXPGPATH];
...@@ -458,6 +459,9 @@ GetUserName(Oid userid) ...@@ -458,6 +459,9 @@ GetUserName(Oid userid)
* The path is also just for informational purposes (so that a socket lockfile * The path is also just for informational purposes (so that a socket lockfile
* can be more easily traced to the associated postmaster). * can be more easily traced to the associated postmaster).
* *
* A data-directory lockfile can optionally contain a third line, containing
* the key and ID for the shared memory block used by this postmaster.
*
* On successful lockfile creation, a proc_exit callback to remove the * On successful lockfile creation, a proc_exit callback to remove the
* lockfile is automatically created. * lockfile is automatically created.
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
...@@ -476,16 +480,18 @@ UnlinkLockFile(int status, Datum filename) ...@@ -476,16 +480,18 @@ UnlinkLockFile(int status, Datum filename)
/* /*
* Create a lockfile, if possible * Create a lockfile, if possible
* *
* Call CreateLockFile with the name of the lockfile to be created. If * Call CreateLockFile with the name of the lockfile to be created.
* successful, it returns zero. On detecting a collision, it returns * Returns true if successful, false if not (with a message on stderr).
* the PID or negated PID of the lockfile owner --- the caller is responsible *
* for producing an appropriate error message. * amPostmaster is used to determine how to encode the output PID.
* isDDLock and refName are used to determine what error message to produce.
*/ */
static int static bool
CreateLockFile(const char *filename, bool amPostmaster) CreateLockFile(const char *filename, bool amPostmaster,
bool isDDLock, const char *refName)
{ {
int fd; int fd;
char buffer[MAXPGPATH + 32]; char buffer[MAXPGPATH + 100];
int len; int len;
int encoded_pid; int encoded_pid;
pid_t other_pid; pid_t other_pid;
...@@ -539,11 +545,61 @@ CreateLockFile(const char *filename, bool amPostmaster) ...@@ -539,11 +545,61 @@ CreateLockFile(const char *filename, bool amPostmaster)
{ {
if (kill(other_pid, 0) == 0 || if (kill(other_pid, 0) == 0 ||
errno != ESRCH) errno != ESRCH)
return encoded_pid; /* lockfile belongs to a live process */ {
/* lockfile belongs to a live process */
fprintf(stderr, "Lock file \"%s\" already exists.\n",
filename);
if (isDDLock)
fprintf(stderr,
"Is another %s (pid %d) running in \"%s\"?\n",
(encoded_pid < 0 ? "postgres" : "postmaster"),
other_pid, refName);
else
fprintf(stderr,
"Is another %s (pid %d) using \"%s\"?\n",
(encoded_pid < 0 ? "postgres" : "postmaster"),
other_pid, refName);
return false;
}
}
/*
* No, the creating process did not exist. However, it could be that
* the postmaster crashed (or more likely was kill -9'd by a clueless
* admin) but has left orphan backends behind. Check for this by
* looking to see if there is an associated shmem segment that is
* still in use.
*/
if (isDDLock)
{
char *ptr;
unsigned long shmKey,
shmId;
ptr = strchr(buffer, '\n');
if (ptr != NULL &&
(ptr = strchr(ptr+1, '\n')) != NULL)
{
ptr++;
if (sscanf(ptr, "%lu %lu", &shmKey, &shmId) == 2)
{
if (SharedMemoryIsInUse((IpcMemoryKey) shmKey,
(IpcMemoryId) shmId))
{
fprintf(stderr,
"Found a pre-existing shared memory block (ID %d) still in use.\n"
"If you're sure there are no old backends still running,\n"
"remove the shared memory block with ipcrm(1), or just\n"
"delete \"%s\".\n",
(int) shmId, filename);
return false;
}
}
}
} }
/* /*
* No, the process did not exist. Unlink the file and try again to * Looks like nobody's home. Unlink the file and try again to
* create it. Need a loop because of possible race condition against * create it. Need a loop because of possible race condition against
* other would-be creators. * other would-be creators.
*/ */
...@@ -576,28 +632,19 @@ CreateLockFile(const char *filename, bool amPostmaster) ...@@ -576,28 +632,19 @@ CreateLockFile(const char *filename, bool amPostmaster)
*/ */
on_proc_exit(UnlinkLockFile, PointerGetDatum(strdup(filename))); on_proc_exit(UnlinkLockFile, PointerGetDatum(strdup(filename)));
return 0; /* Success! */ return true; /* Success! */
} }
bool bool
CreateDataDirLockFile(const char *datadir, bool amPostmaster) CreateDataDirLockFile(const char *datadir, bool amPostmaster)
{ {
char lockfile[MAXPGPATH]; char lockfile[MAXPGPATH];
int encoded_pid;
snprintf(lockfile, sizeof(lockfile), "%s/postmaster.pid", datadir); snprintf(lockfile, sizeof(lockfile), "%s/postmaster.pid", datadir);
encoded_pid = CreateLockFile(lockfile, amPostmaster); if (! CreateLockFile(lockfile, amPostmaster, true, datadir))
if (encoded_pid != 0)
{
fprintf(stderr, "Lock file \"%s\" already exists.\n", lockfile);
if (encoded_pid < 0)
fprintf(stderr, "Is another postgres (pid %d) running in \"%s\"?\n",
-encoded_pid, datadir);
else
fprintf(stderr, "Is another postmaster (pid %d) running in \"%s\"?\n",
encoded_pid, datadir);
return false; return false;
} /* Save name of lockfile for RecordSharedMemoryInLockFile */
strcpy(directoryLockFile, lockfile);
return true; return true;
} }
...@@ -605,21 +652,10 @@ bool ...@@ -605,21 +652,10 @@ bool
CreateSocketLockFile(const char *socketfile, bool amPostmaster) CreateSocketLockFile(const char *socketfile, bool amPostmaster)
{ {
char lockfile[MAXPGPATH]; char lockfile[MAXPGPATH];
int encoded_pid;
snprintf(lockfile, sizeof(lockfile), "%s.lock", socketfile); snprintf(lockfile, sizeof(lockfile), "%s.lock", socketfile);
encoded_pid = CreateLockFile(lockfile, amPostmaster); if (! CreateLockFile(lockfile, amPostmaster, false, socketfile))
if (encoded_pid != 0)
{
fprintf(stderr, "Lock file \"%s\" already exists.\n", lockfile);
if (encoded_pid < 0)
fprintf(stderr, "Is another postgres (pid %d) using \"%s\"?\n",
-encoded_pid, socketfile);
else
fprintf(stderr, "Is another postmaster (pid %d) using \"%s\"?\n",
encoded_pid, socketfile);
return false; return false;
}
/* Save name of lockfile for TouchSocketLockFile */ /* Save name of lockfile for TouchSocketLockFile */
strcpy(socketLockFile, lockfile); strcpy(socketLockFile, lockfile);
return true; return true;
...@@ -650,6 +686,78 @@ TouchSocketLockFile(void) ...@@ -650,6 +686,78 @@ TouchSocketLockFile(void)
} }
} }
/*
* Append information about a shared memory segment to the data directory
* lock file (if we have created one).
*
* This may be called multiple times in the life of a postmaster, if we
* delete and recreate shmem due to backend crash. Therefore, be prepared
* to overwrite existing information. (As of 7.1, a postmaster only creates
* one shm seg anyway; but for the purposes here, if we did have more than
* one then any one of them would do anyway.)
*/
void
RecordSharedMemoryInLockFile(IpcMemoryKey shmKey, IpcMemoryId shmId)
{
int fd;
int len;
char *ptr;
char buffer[BLCKSZ];
/*
* Do nothing if we did not create a lockfile (probably because we
* are running standalone).
*/
if (directoryLockFile[0] == '\0')
return;
fd = open(directoryLockFile, O_RDWR | PG_BINARY, 0);
if (fd < 0)
{
elog(DEBUG, "Failed to rewrite %s: %m", directoryLockFile);
return;
}
len = read(fd, buffer, sizeof(buffer) - 100);
if (len <= 0)
{
elog(DEBUG, "Failed to read %s: %m", directoryLockFile);
close(fd);
return;
}
buffer[len] = '\0';
/*
* Skip over first two lines (PID and path).
*/
ptr = strchr(buffer, '\n');
if (ptr == NULL ||
(ptr = strchr(ptr+1, '\n')) == NULL)
{
elog(DEBUG, "Bogus data in %s", directoryLockFile);
close(fd);
return;
}
ptr++;
/*
* Append shm key and ID. Format to try to keep it the same length
* always (trailing junk won't hurt, but might confuse humans).
*/
sprintf(ptr, "%9lu %9lu\n",
(unsigned long) shmKey, (unsigned long) shmId);
/*
* And rewrite the data. Since we write in a single kernel call,
* this update should appear atomic to onlookers.
*/
len = strlen(buffer);
if (lseek(fd, (off_t) 0, SEEK_SET) != 0 ||
(int) write(fd, buffer, len) != len)
{
elog(DEBUG, "Failed to write %s: %m", directoryLockFile);
close(fd);
return;
}
close(fd);
}
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* Version checking support * Version checking support
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* Support for grand unified configuration scheme, including SET * Support for grand unified configuration scheme, including SET
* command, configuration file, and command line options. * command, configuration file, and command line options.
* *
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.31 2001/02/26 00:50:07 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.32 2001/03/13 01:17:06 tgl Exp $
* *
* Copyright 2000 by PostgreSQL Global Development Group * Copyright 2000 by PostgreSQL Global Development Group
* Written by Peter Eisentraut <peter_e@gmx.net>. * Written by Peter Eisentraut <peter_e@gmx.net>.
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
/* XXX should be in a header file */ /* XXX should be in a header file */
extern bool Log_connections; extern bool Log_connections;
extern int CheckPointSegments;
extern int CheckPointTimeout; extern int CheckPointTimeout;
extern int XLOGbuffers; extern int XLOGbuffers;
extern int XLOGfiles; extern int XLOGfiles;
...@@ -279,13 +280,16 @@ ConfigureNamesInt[] = ...@@ -279,13 +280,16 @@ ConfigureNamesInt[] =
{"unix_socket_permissions", PGC_POSTMASTER, &Unix_socket_permissions, {"unix_socket_permissions", PGC_POSTMASTER, &Unix_socket_permissions,
0777, 0000, 0777}, 0777, 0000, 0777},
{"checkpoint_timeout", PGC_POSTMASTER, &CheckPointTimeout, {"checkpoint_segments", PGC_SIGHUP, &CheckPointSegments,
3, 1, INT_MAX},
{"checkpoint_timeout", PGC_SIGHUP, &CheckPointTimeout,
300, 30, 3600}, 300, 30, 3600},
{"wal_buffers", PGC_POSTMASTER, &XLOGbuffers, {"wal_buffers", PGC_POSTMASTER, &XLOGbuffers,
8, 4, INT_MAX}, 8, 4, INT_MAX},
{"wal_files", PGC_POSTMASTER, &XLOGfiles, {"wal_files", PGC_SIGHUP, &XLOGfiles,
0, 0, 64}, 0, 0, 64},
{"wal_debug", PGC_SUSET, &XLOG_DEBUG, {"wal_debug", PGC_SUSET, &XLOG_DEBUG,
......
...@@ -110,6 +110,7 @@ ...@@ -110,6 +110,7 @@
#wal_debug = 0 # range 0-16 #wal_debug = 0 # range 0-16
#commit_delay = 0 # range 0-100000 #commit_delay = 0 # range 0-100000
#commit_siblings = 5 # range 1-1000 #commit_siblings = 5 # range 1-1000
#checkpoint_segments = 3 # in logfile segments (16MB each), min 1
#checkpoint_timeout = 300 # in seconds, range 30-3600 #checkpoint_timeout = 300 # in seconds, range 30-3600
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: transam.h,v 1.29 2001/01/24 19:43:19 momjian Exp $ * $Id: transam.h,v 1.30 2001/03/13 01:17:06 tgl Exp $
* *
* NOTES * NOTES
* Transaction System Version 101 now support proper oid * Transaction System Version 101 now support proper oid
...@@ -79,7 +79,7 @@ typedef unsigned char XidStatus;/* (2 bits) */ ...@@ -79,7 +79,7 @@ typedef unsigned char XidStatus;/* (2 bits) */
* their numbering at 512. * their numbering at 512.
* *
* The first 4 bytes of this relation store the version * The first 4 bytes of this relation store the version
* number of the transction system. * number of the transaction system.
* ---------------- * ----------------
*/ */
typedef struct LogRelationContentsData typedef struct LogRelationContentsData
...@@ -100,13 +100,16 @@ typedef LogRelationContentsData *LogRelationContents; ...@@ -100,13 +100,16 @@ typedef LogRelationContentsData *LogRelationContents;
* is updated in place whenever the variables change. * is updated in place whenever the variables change.
* *
* The first 4 bytes of this relation store the version * The first 4 bytes of this relation store the version
* number of the transction system. * number of the transaction system.
* *
* Currently, the relation has only one page and the next * Currently, the relation has only one page and the next
* available xid, the last committed xid and the next * available xid, the last committed xid and the next
* available oid are stored there. * available oid are stored there.
*
* XXX As of 7.1, pg_variable isn't used anymore; this is dead code.
* ---------------- * ----------------
*/ */
#ifdef NOT_USED
typedef struct VariableRelationContentsData typedef struct VariableRelationContentsData
{ {
XLogRecPtr LSN; XLogRecPtr LSN;
...@@ -117,6 +120,7 @@ typedef struct VariableRelationContentsData ...@@ -117,6 +120,7 @@ typedef struct VariableRelationContentsData
} VariableRelationContentsData; } VariableRelationContentsData;
typedef VariableRelationContentsData *VariableRelationContents; typedef VariableRelationContentsData *VariableRelationContents;
#endif /* NOT_USED */
/* /*
* VariableCache is placed in shmem and used by * VariableCache is placed in shmem and used by
...@@ -124,8 +128,9 @@ typedef VariableRelationContentsData *VariableRelationContents; ...@@ -124,8 +128,9 @@ typedef VariableRelationContentsData *VariableRelationContents;
*/ */
typedef struct VariableCacheData typedef struct VariableCacheData
{ {
TransactionId nextXid; TransactionId nextXid; /* next XID to assign */
Oid nextOid; uint32 xidCount; /* XIDs available before must do XLOG work */
Oid nextOid; /* and similarly for OIDs */
uint32 oidCount; uint32 oidCount;
} VariableCacheData; } VariableCacheData;
...@@ -184,7 +189,8 @@ extern int RecoveryCheckingEnableState; ...@@ -184,7 +189,8 @@ extern int RecoveryCheckingEnableState;
extern bool AMI_OVERRIDE; extern bool AMI_OVERRIDE;
/* in varsup.c */ /* in varsup.c */
extern int OidGenLockId; extern SPINLOCK OidGenLockId;
extern SPINLOCK XidGenLockId;
extern VariableCache ShmemVariableCache; extern VariableCache ShmemVariableCache;
#endif /* TRAMSAM_H */ #endif /* TRAMSAM_H */
...@@ -3,7 +3,10 @@ ...@@ -3,7 +3,10 @@
* *
* PostgreSQL transaction log manager * PostgreSQL transaction log manager
* *
* $Header: /cvsroot/pgsql/src/include/access/xlog.h,v 1.18 2001/02/26 00:50:07 tgl Exp $ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: xlog.h,v 1.19 2001/03/13 01:17:06 tgl Exp $
*/ */
#ifndef XLOG_H #ifndef XLOG_H
#define XLOG_H #define XLOG_H
...@@ -11,97 +14,126 @@ ...@@ -11,97 +14,126 @@
#include "access/rmgr.h" #include "access/rmgr.h"
#include "access/transam.h" #include "access/transam.h"
#include "access/xlogdefs.h" #include "access/xlogdefs.h"
#include "access/xlogutils.h" #include "utils/pg_crc.h"
typedef struct crc64
{
uint32 crc1;
uint32 crc2;
} crc64;
/*
* Header for each record in XLOG
*
* NOTE: xl_len counts only the rmgr data, not the XLogRecord header,
* and also not any backup blocks appended to the record (which are signaled
* by xl_info flag bits). The total space needed for an XLOG record is
* really:
*
* SizeOfXLogRecord + xl_len + n_backup_blocks * (sizeof(BkpBlock) + BLCKSZ)
*/
typedef struct XLogRecord typedef struct XLogRecord
{ {
crc64 xl_crc; crc64 xl_crc; /* CRC for this record */
XLogRecPtr xl_prev; /* ptr to previous record in log */ XLogRecPtr xl_prev; /* ptr to previous record in log */
XLogRecPtr xl_xact_prev; /* ptr to previous record of this xact */ XLogRecPtr xl_xact_prev; /* ptr to previous record of this xact */
TransactionId xl_xid; /* xact id */ TransactionId xl_xid; /* xact id */
uint16 xl_len; /* total len of record *data* */ uint16 xl_len; /* total len of rmgr data */
uint8 xl_info; uint8 xl_info; /* flag bits, see below */
RmgrId xl_rmid; /* resource manager inserted this record */ RmgrId xl_rmid; /* resource manager for this record */
/* ACTUAL LOG DATA FOLLOWS AT END OF STRUCT */ /* ACTUAL LOG DATA FOLLOWS AT END OF STRUCT */
} XLogRecord; } XLogRecord;
#define SizeOfXLogRecord DOUBLEALIGN(sizeof(XLogRecord)) #define SizeOfXLogRecord MAXALIGN(sizeof(XLogRecord))
#define MAXLOGRECSZ (2 * BLCKSZ) #define MAXLOGRECSZ 65535 /* the most that'll fit in xl_len */
#define XLogRecGetData(record) \ #define XLogRecGetData(record) ((char*) (record) + SizeOfXLogRecord)
((char*)record + SizeOfXLogRecord)
/* /*
* When there is no space on current page we continue * XLOG uses only low 4 bits of xl_info. High 4 bits may be used by rmgr.
* on the next page with subrecord.
*/ */
typedef struct XLogSubRecord #define XLR_INFO_MASK 0x0F
{
uint16 xl_len; /* len of data left */
/* ACTUAL LOG DATA FOLLOWS AT END OF STRUCT */
} XLogSubRecord;
#define SizeOfXLogSubRecord DOUBLEALIGN(sizeof(XLogSubRecord))
/* /*
* XLOG uses only low 4 bits of xl_info. * We support backup of up to 2 disk blocks per XLOG record (could support
* High 4 bits may be used by rmgr... * more if we cared to dedicate more xl_info bits for this purpose; currently
* * do not need more than 2 anyway). If we backed up any disk blocks then we
* We support backup of 2 blocks per record only. * use flag bits in xl_info to signal it.
* If we backed up some of these blocks then we use
* flags below to signal rmgr about this on recovery.
*/ */
#define XLR_SET_BKP_BLOCK(iblk) (0x08 >> iblk) #define XLR_BKP_BLOCK_MASK 0x0C /* all info bits used for bkp blocks */
#define XLR_MAX_BKP_BLOCKS 2
#define XLR_SET_BKP_BLOCK(iblk) (0x08 >> (iblk))
#define XLR_BKP_BLOCK_1 XLR_SET_BKP_BLOCK(0) /* 0x08 */ #define XLR_BKP_BLOCK_1 XLR_SET_BKP_BLOCK(0) /* 0x08 */
#define XLR_BKP_BLOCK_2 XLR_SET_BKP_BLOCK(1) /* 0x04 */ #define XLR_BKP_BLOCK_2 XLR_SET_BKP_BLOCK(1) /* 0x04 */
#define XLR_INFO_MASK 0x0F
/* /*
* Sometimes we log records which are out of transaction control. * Sometimes we log records which are out of transaction control.
* Rmgr may use flag below for this purpose. * Rmgr may "or" XLOG_NO_TRAN into info passed to XLogInsert to indicate this.
*/ */
#define XLOG_NO_TRAN XLR_INFO_MASK #define XLOG_NO_TRAN XLR_INFO_MASK
#define XLOG_PAGE_MAGIC 0x17345168 /*
* Header info for a backup block appended to an XLOG record.
*
* Note that the backup block has its own CRC, and is not covered by
* the CRC of the XLOG record proper. Also note that we don't attempt
* to align either the BkpBlock struct or the block's data.
*/
typedef struct BkpBlock
{
crc64 crc;
RelFileNode node;
BlockNumber block;
} BkpBlock;
typedef struct XLogPageHeaderData /*
* When there is not enough space on current page for whole record, we
* continue on the next page with continuation record. (However, the
* XLogRecord header will never be split across pages; if there's less than
* SizeOfXLogRecord space left at the end of a page, we just waste it.)
*
* Note that xl_rem_len includes backup-block data, unlike xl_len in the
* initial header.
*/
typedef struct XLogContRecord
{ {
uint32 xlp_magic; uint32 xl_rem_len; /* total len of remaining data for record */
uint16 xlp_info;
} XLogPageHeaderData;
#define SizeOfXLogPHD DOUBLEALIGN(sizeof(XLogPageHeaderData)) /* ACTUAL LOG DATA FOLLOWS AT END OF STRUCT */
typedef XLogPageHeaderData *XLogPageHeader; } XLogContRecord;
/* When record crosses page boundary */ #define SizeOfXLogContRecord MAXALIGN(sizeof(XLogContRecord))
#define XLP_FIRST_IS_SUBRECORD 0x0001
#define XLByteLT(left, right) \ /*
(right.xlogid > left.xlogid || \ * Each page of XLOG file has a header like this:
(right.xlogid == left.xlogid && right.xrecoff > left.xrecoff)) */
#define XLOG_PAGE_MAGIC 0x17345169 /* can be used as WAL version indicator */
#define XLByteLE(left, right) \ typedef struct XLogPageHeaderData
(right.xlogid > left.xlogid || \ {
(right.xlogid == left.xlogid && right.xrecoff >= left.xrecoff)) uint32 xlp_magic; /* magic value for correctness checks */
uint16 xlp_info; /* flag bits, see below */
} XLogPageHeaderData;
#define XLByteEQ(left, right) \ #define SizeOfXLogPHD MAXALIGN(sizeof(XLogPageHeaderData))
(right.xlogid == left.xlogid && right.xrecoff == left.xrecoff)
extern StartUpID ThisStartUpID; /* current SUI */ typedef XLogPageHeaderData *XLogPageHeader;
extern bool InRecovery;
extern XLogRecPtr MyLastRecPtr; /* When record crosses page boundary, set this flag in new page's header */
#define XLP_FIRST_IS_CONTRECORD 0x0001
/*
* We break each logical log file (xlogid value) into 16Mb segments.
* One possible segment at the end of each log file is wasted, to ensure
* that we don't have problems representing last-byte-position-plus-1.
*/
#define XLogSegSize ((uint32) (16*1024*1024))
#define XLogSegsPerFile (((uint32) 0xffffffff) / XLogSegSize)
#define XLogFileSize (XLogSegsPerFile * XLogSegSize)
/*
* Method table for resource managers.
*
* RmgrTable[] is indexed by RmgrId values (see rmgr.h).
*/
typedef struct RmgrData typedef struct RmgrData
{ {
char *rm_name; char *rm_name;
...@@ -112,12 +144,19 @@ typedef struct RmgrData ...@@ -112,12 +144,19 @@ typedef struct RmgrData
extern RmgrData RmgrTable[]; extern RmgrData RmgrTable[];
/* /*--------------------
* List of these structs is used to pass data to XLOG. * List of these structs is used to pass data to XLogInsert().
* If buffer is valid then XLOG will check if buffer must *
* be backup-ed. For backup-ed buffer data will not be * If buffer is valid then XLOG will check if buffer must be backed up
* inserted into record (and XLOG sets * (ie, whether this is first change of that page since last checkpoint).
* XLR_BKP_BLOCK_X bit in xl_info). * If so, the whole page contents are attached to the XLOG record, and XLOG
* sets XLR_BKP_BLOCK_X bit in xl_info. Note that the buffer must be pinned
* and locked while this is going on, so that it won't change under us.
* NB: when this happens, we do not bother to insert the associated data into
* the XLOG record, since we assume it's present in the buffer. Therefore,
* rmgr redo routines MUST pay attention to XLR_BKP_BLOCK_X to know what
* is actually stored in the XLOG record.
*--------------------
*/ */
typedef struct XLogRecData typedef struct XLogRecData
{ {
...@@ -127,11 +166,13 @@ typedef struct XLogRecData ...@@ -127,11 +166,13 @@ typedef struct XLogRecData
struct XLogRecData *next; struct XLogRecData *next;
} XLogRecData; } XLogRecData;
extern StartUpID ThisStartUpID; /* current SUI */
extern bool InRecovery;
extern XLogRecPtr MyLastRecPtr;
extern XLogRecPtr XLogInsert(RmgrId rmid, uint8 info, XLogRecData *rdata); extern XLogRecPtr XLogInsert(RmgrId rmid, uint8 info, XLogRecData *rdata);
extern void XLogFlush(XLogRecPtr RecPtr); extern void XLogFlush(XLogRecPtr RecPtr);
extern void CreateCheckPoint(bool shutdown);
extern void xlog_redo(XLogRecPtr lsn, XLogRecord *record); extern void xlog_redo(XLogRecPtr lsn, XLogRecord *record);
extern void xlog_undo(XLogRecPtr lsn, XLogRecord *record); extern void xlog_undo(XLogRecPtr lsn, XLogRecord *record);
extern void xlog_desc(char *buf, uint8 xl_info, char* rec); extern void xlog_desc(char *buf, uint8 xl_info, char* rec);
...@@ -145,6 +186,10 @@ extern void StartupXLOG(void); ...@@ -145,6 +186,10 @@ extern void StartupXLOG(void);
extern void ShutdownXLOG(void); extern void ShutdownXLOG(void);
extern void CreateCheckPoint(bool shutdown); extern void CreateCheckPoint(bool shutdown);
extern void SetThisStartUpID(void); extern void SetThisStartUpID(void);
extern void XLogPutNextXid(TransactionId nextXid);
extern void XLogPutNextOid(Oid nextOid);
extern void SetRedoRecPtr(void);
extern void GetRedoRecPtr(void);
/* in storage/ipc/sinval.c, but don't want to declare in sinval.h because /* in storage/ipc/sinval.c, but don't want to declare in sinval.h because
* we'd have to include xlog.h into that ... * we'd have to include xlog.h into that ...
......
/* /*
*
* xlogdefs.h * xlogdefs.h
* *
* Postgres transaction log manager record pointer and * Postgres transaction log manager record pointer and
* system stratup number definitions * system startup number definitions
*
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: xlogdefs.h,v 1.2 2001/03/13 01:17:06 tgl Exp $
*/ */
#ifndef XLOG_DEFS_H #ifndef XLOG_DEFS_H
#define XLOG_DEFS_H #define XLOG_DEFS_H
/*
* Pointer to a location in the XLOG. These pointers are 64 bits wide,
* because we don't want them ever to overflow.
*
* NOTE: xrecoff == 0 is used to indicate an invalid pointer. This is OK
* because we use page headers in the XLOG, so no XLOG record can start
* right at the beginning of a file.
*
* NOTE: the "log file number" is somewhat misnamed, since the actual files
* making up the XLOG are much smaller than 4Gb. Each actual file is an
* XLogSegSize-byte "segment" of a logical log file having the indicated
* xlogid. The log file number and segment number together identify a
* physical XLOG file. Segment number and offset within the physical file
* are computed from xrecoff div and mod XLogSegSize.
*/
typedef struct XLogRecPtr typedef struct XLogRecPtr
{ {
uint32 xlogid; /* log file #, 0 based */ uint32 xlogid; /* log file #, 0 based */
uint32 xrecoff; /* offset of record in log file */ uint32 xrecoff; /* byte offset of location in log file */
} XLogRecPtr; } XLogRecPtr;
/*
* Macros for comparing XLogRecPtrs
*
* Beware of passing expressions with side-effects to these macros,
* since the arguments may be evaluated multiple times.
*/
#define XLByteLT(a, b) \
((a).xlogid < (b).xlogid || \
((a).xlogid == (b).xlogid && (a).xrecoff < (b).xrecoff))
#define XLByteLE(a, b) \
((a).xlogid < (b).xlogid || \
((a).xlogid == (b).xlogid && (a).xrecoff <= (b).xrecoff))
#define XLByteEQ(a, b) \
((a).xlogid == (b).xlogid && (a).xrecoff == (b).xrecoff)
/* /*
* StartUpID (SUI) - system startups counter. It's to allow removing * StartUpID (SUI) - system startups counter. It's to allow removing
* pg_log after shutdown, in future. * pg_log after shutdown, in future.
......
/*
* xlogutils.h
*
* PostgreSQL transaction log manager utility routines
*
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: xlogutils.h,v 1.6 2001/03/13 01:17:06 tgl Exp $
*/
#ifndef XLOG_UTILS_H #ifndef XLOG_UTILS_H
#define XLOG_UTILS_H #define XLOG_UTILS_H
......
/*-------------------------------------------------------------------------
*
* pg_control.h
* The system control file "pg_control" is not a heap relation.
* However, we define it here so that the format is documented.
*
*
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_control.h,v 1.1 2001/03/13 01:17:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef PG_CONTROL_H
#define PG_CONTROL_H
#include <time.h>
#include "access/xlogdefs.h"
#include "utils/pg_crc.h"
/* Version identifier for this pg_control format */
#define PG_CONTROL_VERSION 71
/*
* Body of CheckPoint XLOG records. This is declared here because we keep
* a copy of the latest one in pg_control for possible disaster recovery.
*/
typedef struct CheckPoint
{
XLogRecPtr redo; /* next RecPtr available when we */
/* began to create CheckPoint */
/* (i.e. REDO start point) */
XLogRecPtr undo; /* first record of oldest in-progress */
/* transaction when we started */
/* (i.e. UNDO end point) */
StartUpID ThisStartUpID; /* current SUI */
TransactionId nextXid; /* next free XID */
Oid nextOid; /* next free OID */
time_t time; /* time stamp of checkpoint */
} CheckPoint;
/* XLOG info values for XLOG rmgr */
#define XLOG_CHECKPOINT_SHUTDOWN 0x00
#define XLOG_CHECKPOINT_ONLINE 0x10
#define XLOG_NEXTXID 0x20
#define XLOG_NEXTOID 0x30
/* System status indicator */
typedef enum DBState
{
DB_STARTUP = 0,
DB_SHUTDOWNED,
DB_SHUTDOWNING,
DB_IN_RECOVERY,
DB_IN_PRODUCTION
} DBState;
#define LOCALE_NAME_BUFLEN 128
/*
* Contents of pg_control.
*
* NOTE: try to keep this under 512 bytes so that it will fit on one physical
* sector of typical disk drives. This reduces the odds of corruption due to
* power failure midway through a write. Currently it fits comfortably,
* but we could probably reduce LOCALE_NAME_BUFLEN if things get tight.
*/
typedef struct ControlFileData
{
crc64 crc; /* CRC for remainder of struct */
/*
* Version identifier information. Keep these fields at the front,
* especially pg_control_version; they won't be real useful if they
* move around.
*
* pg_control_version identifies the format of pg_control itself.
* catalog_version_no identifies the format of the system catalogs.
*
* There are additional version identifiers in individual files;
* for example, WAL logs contain per-page magic numbers that can serve
* as version cues for the WAL log.
*/
uint32 pg_control_version; /* PG_CONTROL_VERSION */
uint32 catalog_version_no; /* see catversion.h */
/*
* System status data
*/
DBState state; /* see enum above */
time_t time; /* time stamp of last pg_control update */
uint32 logId; /* current log file id */
uint32 logSeg; /* current log file segment, + 1 */
XLogRecPtr checkPoint; /* last check point record ptr */
XLogRecPtr prevCheckPoint; /* previous check point record ptr */
CheckPoint checkPointCopy; /* copy of last check point record */
/*
* This data is used to make sure that configuration of this database
* is compatible with the backend executable.
*/
uint32 blcksz; /* block size for this DB */
uint32 relseg_size; /* blocks per segment of large relation */
/* active locales --- "C" if compiled without USE_LOCALE: */
char lc_collate[LOCALE_NAME_BUFLEN];
char lc_ctype[LOCALE_NAME_BUFLEN];
} ControlFileData;
#endif /* PG_CONTROL_H */
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: miscadmin.h,v 1.81 2001/02/10 02:31:28 tgl Exp $ * $Id: miscadmin.h,v 1.82 2001/03/13 01:17:06 tgl Exp $
* *
* NOTES * NOTES
* some of the information in this file should be moved to * some of the information in this file should be moved to
...@@ -283,6 +283,8 @@ extern ProcessingMode Mode; ...@@ -283,6 +283,8 @@ extern ProcessingMode Mode;
extern bool CreateDataDirLockFile(const char *datadir, bool amPostmaster); extern bool CreateDataDirLockFile(const char *datadir, bool amPostmaster);
extern bool CreateSocketLockFile(const char *socketfile, bool amPostmaster); extern bool CreateSocketLockFile(const char *socketfile, bool amPostmaster);
extern void TouchSocketLockFile(void); extern void TouchSocketLockFile(void);
extern void RecordSharedMemoryInLockFile(IpcMemoryKey shmKey,
IpcMemoryId shmId);
extern void ValidatePgVersion(const char *path); extern void ValidatePgVersion(const char *path);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: ipc.h,v 1.47 2001/02/10 02:31:28 tgl Exp $ * $Id: ipc.h,v 1.48 2001/03/13 01:17:06 tgl Exp $
* *
* Some files that would normally need to include only sys/ipc.h must * Some files that would normally need to include only sys/ipc.h must
* instead include this file because on Ultrix, sys/ipc.h is not designed * instead include this file because on Ultrix, sys/ipc.h is not designed
...@@ -105,6 +105,8 @@ extern int IpcSemaphoreGetValue(IpcSemaphoreId semId, int sem); ...@@ -105,6 +105,8 @@ extern int IpcSemaphoreGetValue(IpcSemaphoreId semId, int sem);
extern PGShmemHeader *IpcMemoryCreate(uint32 size, bool makePrivate, extern PGShmemHeader *IpcMemoryCreate(uint32 size, bool makePrivate,
int permission); int permission);
extern bool SharedMemoryIsInUse(IpcMemoryKey shmKey, IpcMemoryId shmId);
/* ipci.c */ /* ipci.c */
extern void CreateSharedMemoryAndSemaphores(bool makePrivate, extern void CreateSharedMemoryAndSemaphores(bool makePrivate,
int maxBackends); int maxBackends);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: tcopprot.h,v 1.38 2001/01/24 19:43:28 momjian Exp $ * $Id: tcopprot.h,v 1.39 2001/03/13 01:17:06 tgl Exp $
* *
* OLD COMMENTS * OLD COMMENTS
* This file was created so that other c files could get the two * This file was created so that other c files could get the two
...@@ -41,6 +41,7 @@ extern void pg_exec_query_string(char *query_string, ...@@ -41,6 +41,7 @@ extern void pg_exec_query_string(char *query_string,
#endif /* BOOTSTRAP_INCLUDE */ #endif /* BOOTSTRAP_INCLUDE */
extern void die(SIGNAL_ARGS); extern void die(SIGNAL_ARGS);
extern void quickdie(SIGNAL_ARGS);
extern int PostgresMain(int argc, char *argv[], extern int PostgresMain(int argc, char *argv[],
int real_argc, char *real_argv[], const char *username); int real_argc, char *real_argv[], const char *username);
extern void ResetUsage(void); extern void ResetUsage(void);
......
/*
* pg_crc.h
*
* PostgreSQL 64-bit CRC support
*
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_crc.h,v 1.1 2001/03/13 01:17:06 tgl Exp $
*/
#ifndef PG_CRC_H
#define PG_CRC_H
/*
* If we have a 64-bit integer type, then a 64-bit CRC looks just like the
* usual sort of implementation. (See Ross Williams' excellent introduction
* A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS, available from
* ftp://ftp.rocksoft.com/papers/crc_v3.txt or several other net sites.)
* If we have no working 64-bit type, then fake it with two 32-bit registers.
*
* The present implementation is a normal (not "reflected", in Williams'
* terms) 64-bit CRC, using initial all-ones register contents and a final
* bit inversion. The chosen polynomial is borrowed from the DLT1 spec
* (ECMA-182, available from http://www.ecma.ch/ecma1/STAND/ECMA-182.HTM):
*
* x^64 + x^62 + x^57 + x^55 + x^54 + x^53 + x^52 + x^47 + x^46 + x^45 +
* x^40 + x^39 + x^38 + x^37 + x^35 + x^33 + x^32 + x^31 + x^29 + x^27 +
* x^24 + x^23 + x^22 + x^21 + x^19 + x^17 + x^13 + x^12 + x^10 + x^9 +
* x^7 + x^4 + x + 1
*/
#ifdef INT64_IS_BUSTED
/*
* crc0 represents the LSBs of the 64-bit value, crc1 the MSBs. Note that
* with crc0 placed first, the output of 32-bit and 64-bit implementations
* will be bit-compatible only on little-endian architectures. If it were
* important to make the two possible implementations bit-compatible on
* all machines, we could do a configure test to decide how to order the
* two fields, but it seems not worth the trouble.
*/
typedef struct crc64
{
uint32 crc0;
uint32 crc1;
} crc64;
/* Initialize a CRC accumulator */
#define INIT_CRC64(crc) ((crc).crc0 = 0xffffffff, (crc).crc1 = 0xffffffff)
/* Finish a CRC calculation */
#define FIN_CRC64(crc) ((crc).crc0 ^= 0xffffffff, (crc).crc1 ^= 0xffffffff)
/* Accumulate some (more) bytes into a CRC */
#define COMP_CRC64(crc, data, len) \
do { \
uint32 __crc0 = (crc).crc0; \
uint32 __crc1 = (crc).crc1; \
unsigned char *__data = (unsigned char *) (data); \
uint32 __len = (len); \
\
while (__len-- > 0) \
{ \
int __tab_index = ((int) (__crc1 >> 24) ^ *__data++) & 0xFF; \
__crc1 = crc_table1[__tab_index] ^ ((__crc1 << 8) | (__crc0 >> 24)); \
__crc0 = crc_table0[__tab_index] ^ (__crc0 << 8); \
} \
(crc).crc0 = __crc0; \
(crc).crc1 = __crc1; \
} while (0)
/* Check for equality of two CRCs */
#define EQ_CRC64(c1,c2) ((c1).crc0 == (c2).crc0 && (c1).crc1 == (c2).crc1)
/* Constant table for CRC calculation */
extern const uint32 crc_table0[];
extern const uint32 crc_table1[];
#else /* int64 works */
typedef struct crc64
{
uint64 crc0;
} crc64;
/* Initialize a CRC accumulator */
#define INIT_CRC64(crc) ((crc).crc0 = (uint64) 0xffffffffffffffff)
/* Finish a CRC calculation */
#define FIN_CRC64(crc) ((crc).crc0 ^= (uint64) 0xffffffffffffffff)
/* Accumulate some (more) bytes into a CRC */
#define COMP_CRC64(crc, data, len) \
do { \
uint64 __crc0 = (crc).crc0; \
unsigned char *__data = (unsigned char *) (data); \
uint32 __len = (len); \
\
while (__len-- > 0) \
{ \
int __tab_index = ((int) (__crc0 >> 56) ^ *__data++) & 0xFF; \
__crc0 = crc_table[__tab_index] ^ (__crc0 << 8); \
} \
(crc).crc0 = __crc0; \
} while (0)
/* Check for equality of two CRCs */
#define EQ_CRC64(c1,c2) ((c1).crc0 == (c2).crc0)
/* Constant table for CRC calculation */
extern const uint64 crc_table[];
#endif /* INT64_IS_BUSTED */
#endif /* PG_CRC_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment