diff --git a/doc/src/sgml/backup.sgml b/doc/src/sgml/backup.sgml
index 3c5e0d5a8ecd7ede50052e059b2521860eae3d41..9055517af543114ac8e780dbc58a24152651ac18 100644
--- a/doc/src/sgml/backup.sgml
+++ b/doc/src/sgml/backup.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/backup.sgml,v 2.152 2010/04/20 00:26:06 rhaas Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/backup.sgml,v 2.153 2010/04/28 16:10:39 heikki Exp $ -->
 
 <chapter id="backup">
  <title>Backup and Restore</title>
@@ -689,8 +689,7 @@ archive_command = 'test ! -f /mnt/server/archivedir/%f &amp;&amp; cp %p /mnt/ser
    </para>
 
    <para>
-    When <varname>archive_mode</> is <literal>off</> and <xref
-    linkend="guc-max-wal-senders"> is zero some SQL commands
+    When <varname>wal_level</> is <literal>minimal</> some SQL commands
     are optimized to avoid WAL logging, as described in <xref
     linkend="populate-pitr">.  If archiving or streaming replication were
     turned on during execution of one of these statements, WAL would not
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 71bab707da856f5c62ae92b0109a9f6a4bee3308..93c9ff183c2775bc6569759261fab6dcf017ff81 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.270 2010/04/26 10:51:59 rhaas Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.271 2010/04/28 16:10:39 heikki Exp $ -->
 
 <chapter Id="runtime-config">
   <title>Server Configuration</title>
@@ -1353,6 +1353,45 @@ SET ENABLE_SEQSCAN TO OFF;
      <title>Settings</title>
      <variablelist>
      
+     <varlistentry id="guc-wal-level" xreflabel="wal_level">
+      <term><varname>wal_level</varname> (<type>enum</type>)</term>
+      <indexterm>
+       <primary><varname>wal_level</> configuration parameter</primary>
+      </indexterm>
+      <listitem>
+       <para>
+        <varname>wal_level</> determines how much information is written
+        to the WAL. The default value is <literal>minimal</>, which writes
+        only minimal information needed to recover from a crash or immediate
+        shutdown. <literal>archive</> adds logging required for WAL archiving,
+        and <literal>hot_standby</> further adds information required to run
+        read-only queries on a standby server.
+        This parameter can only be set at server start.
+       </para>
+       <para>
+        In <literal>minimal</> level, WAL-logging of some bulk operations, like
+        <command>CREATE INDEX</>, <command>CLUSTER</> and <command>COPY</> on
+        a table that was created or truncated in the same transaction can be
+        safely skipped, which can make those operations much faster (see
+        <xref linkend="populate-pitr">). But minimal WAL does not contain
+        enough information to reconstruct the data from a base backup and the
+        WAL logs, so at least <literal>archive</> level must be used to enable
+        WAL archiving (<xref linkend="guc-archive-mode">) and streaming
+        replication.
+       </para>
+       <para>
+        In <literal>hot_standby</> level, the same information is logged as
+        with <literal>archive</>, plus information needed to reconstruct
+        the status of running transactions from the WAL. To enable read-only
+        queries on a standby server, <varname>wal_level</> must be set to
+        <literal>hot_standby</> on the primary. It is thought that there is
+        little measurable difference in performance from using
+        <literal>hot_standby</> level over <literal>archive</>, so feedback
+        is welcome if any production impacts are noticeable.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry id="guc-fsync" xreflabel="fsync">
       <indexterm>
        <primary><varname>fsync</> configuration parameter</primary>
@@ -1726,7 +1765,9 @@ SET ENABLE_SEQSCAN TO OFF;
         <varname>archive_mode</> and <varname>archive_command</> are
         separate variables so that <varname>archive_command</> can be
         changed without leaving archiving mode.
-        This parameter can only be set at server start.
+        This parameter can only be set at server start. <varname>wal_level</>
+        must be set to <literal>archive</> or <literal>hot_standby</> to
+        enable <varname>archive_mode</>.
        </para>
       </listitem>
      </varlistentry>
@@ -1818,7 +1859,9 @@ SET ENABLE_SEQSCAN TO OFF;
         Specifies the maximum number of concurrent connections from standby
         servers (i.e., the maximum number of simultaneously running WAL sender
         processes). The default is zero. This parameter can only be set at
-        server start.
+        server start. <varname>wal_level</> must be set to <literal>archive</>
+        or <literal>hot_standby</> to allow connections from standby
+        connections.
        </para>
        </listitem>
       </varlistentry>
@@ -1884,16 +1927,11 @@ SET ENABLE_SEQSCAN TO OFF;
       </indexterm>
       <listitem>
        <para>
-        Parameter has two roles. During recovery, specifies whether or not
-        you can connect and run queries to enable <xref linkend="hot-standby">.
-        During normal running, specifies whether additional information is written
-        to WAL to allow recovery connections on a standby server that reads
-        WAL data generated by this server. The default value is
-        <literal>on</literal>.  It is thought that there is little
-        measurable difference in performance from using this feature, so
-        feedback is welcome if any production impacts are noticeable.
-        It is likely that this parameter will be removed in later releases.
-        This parameter can only be set at server start.
+        Specifies whether or not you can connect and run queries during
+        recovery, for <xref linkend="hot-standby">. The default value is
+        <literal>on</literal>.
+        This parameter can only be set at server start. It only has effect
+        during archive recovery or in standby mode.
        </para>
       </listitem>
      </varlistentry>
diff --git a/doc/src/sgml/high-availability.sgml b/doc/src/sgml/high-availability.sgml
index 463bac1f4808881394bf7503d3c3f29d40759a4a..da0d4d5de5fec8a0ca8b646ebd128e9b988219c5 100644
--- a/doc/src/sgml/high-availability.sgml
+++ b/doc/src/sgml/high-availability.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/high-availability.sgml,v 1.63 2010/04/26 19:09:25 momjian Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/high-availability.sgml,v 1.64 2010/04/28 16:10:40 heikki Exp $ -->
 
 <chapter id="high-availability">
  <title>High Availability, Load Balancing, and Replication</title>
@@ -1593,9 +1593,9 @@ LOG:  database system is ready to accept read only connections
 </programlisting>
 
     Consistency information is recorded once per checkpoint on the primary, as long
-    as <varname>recovery_connections</> is enabled on the primary.  It is not possible
+    as <varname>wal_level</> is set to <literal>hot_standby</> on the primary.  It is not possible
     to enable recovery connections on the standby when reading WAL written during the
-    period that <varname>recovery_connections</> was disabled on the primary.
+    period that <varname>wal_level</> was not set to <literal>hot_standby</> on the primary.
     Reaching a consistent state can also be delayed in the presence
     of both of these conditions:
 
@@ -1842,7 +1842,7 @@ LOG:  database system is ready to accept read only connections
    </para>
 
    <para>
-    On the primary, parameters <varname>recovery_connections</> and
+    On the primary, parameters <varname>wal_level</> and
     <varname>vacuum_defer_cleanup_age</> can be used.
     <varname>max_standby_delay</> has no effect if set on the primary.
    </para>
diff --git a/doc/src/sgml/perform.sgml b/doc/src/sgml/perform.sgml
index ccccb3fefb0036945b13dc5f17f8642cecec221d..bd93cb0dd2ed58b072dd189310e7dd1fcaa7951e 100644
--- a/doc/src/sgml/perform.sgml
+++ b/doc/src/sgml/perform.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/perform.sgml,v 1.76 2010/04/20 00:26:06 rhaas Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/perform.sgml,v 1.77 2010/04/28 16:10:40 heikki Exp $ -->
 
  <chapter id="performance-tips">
   <title>Performance Tips</title>
@@ -835,10 +835,9 @@ SELECT * FROM x, y, a, b, c WHERE something AND somethingelse;
     <command>TRUNCATE</command> command. In such cases no WAL
     needs to be written, because in case of an error, the files
     containing the newly loaded data will be removed anyway.
-    However, this consideration does not apply when
-    <xref linkend="guc-archive-mode"> is on or streaming replication
-    is allowed (i.e., <xref linkend="guc-max-wal-senders"> is more
-    than or equal to one), as all commands must write WAL in that case.
+    However, this consideration only applies when
+    <xref linkend="guc-wal-level"> is <literal>minimal</> as all commands
+    must write WAL otherwise.
    </para>
 
   </sect2>
@@ -910,29 +909,27 @@ SELECT * FROM x, y, a, b, c WHERE something AND somethingelse;
   </sect2>
 
   <sect2 id="populate-pitr">
-   <title>Turn off <varname>archive_mode</varname> and streaming replication</title>
+   <title>Disable WAL archival and streaming replication</title>
 
    <para>
     When loading large amounts of data into an installation that uses
-    WAL archiving or streaming replication, you might want to disable
-    archiving (turn off the <xref linkend="guc-archive-mode">
-    configuration variable) and replication (zero the
-    <xref linkend="guc-max-wal-senders"> configuration variable)
-    while loading.  It might be
-    faster to take a new base backup after the load has completed
-    than to process a large amount of incremental WAL data.
-    But note that changing either of these variables requires
-    a server restart.
+    WAL archiving or streaming replication, it might be faster to take a
+    new base backup after the load has completed than to process a large
+    amount of incremental WAL data. You might want to disable archiving
+    and streaming replication while loading, by setting
+    <xref linkend="guc-wal-level"> to <literal>minimal</>,
+    <xref linkend="guc-archive-mode"> <literal>off</>, and
+    <xref linkend="guc-max-wal-senders"> to zero).
+    But note that changing these settings requires a server restart.
    </para>
 
    <para>
     Aside from avoiding the time for the archiver or WAL sender to
     process the WAL data,
     doing this will actually make certain commands faster, because they
-    are designed not to write WAL at all if <varname>archive_mode</varname>
-    is off and <varname>max_wal_senders</varname> is zero.  (They can
-    guarantee crash safety more cheaply by doing an
-    <function>fsync</> at the end than by writing WAL.)
+    are designed not to write WAL at all if <varname>wal_level</varname>
+    is <literal>minimal</>.  (They can guarantee crash safety more cheaply
+    by doing an <function>fsync</> at the end than by writing WAL.)
     This applies to the following commands:
     <itemizedlist>
      <listitem>
@@ -1014,10 +1011,12 @@ SELECT * FROM x, y, a, b, c WHERE something AND somethingelse;
      </listitem>
      <listitem>
       <para>
-       If using WAL archiving, consider disabling it during the restore.
-       To do that, turn off <varname>archive_mode</varname> before loading the
-       dump script, and afterwards turn it back on
-       and take a fresh base backup.
+       If using WAL archiving or streaming replication, consider disabling
+       them during the restore. To do that, set <varname>arcive_mode</> off,
+       <varname>wal_level</varname> to <literal>minimal</>, and
+       <varname>max_wal_senders</> zero before loading the dump script,
+       and afterwards set them back to the right values and take a fresh
+       base backup.
       </para>
      </listitem>
      <listitem>
diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c
index 5c60c1f130da91df6c49f40f36f254371ec3cc07..e35fbeb9b1ae3faec79ea49a0aaa271633c73534 100644
--- a/src/backend/access/heap/rewriteheap.c
+++ b/src/backend/access/heap/rewriteheap.c
@@ -96,7 +96,7 @@
  * Portions Copyright (c) 1994-5, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/access/heap/rewriteheap.c,v 1.21 2010/02/26 02:00:33 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/heap/rewriteheap.c,v 1.22 2010/04/28 16:10:40 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -278,16 +278,6 @@ end_heap_rewrite(RewriteState state)
 				   (char *) state->rs_buffer, true);
 	}
 
-	/* Write an XLOG UNLOGGED record if WAL-logging was skipped */
-	if (!state->rs_use_wal && !state->rs_new_rel->rd_istemp)
-	{
-		char		reason[NAMEDATALEN + 30];
-
-		snprintf(reason, sizeof(reason), "heap rewrite on \"%s\"",
-				 RelationGetRelationName(state->rs_new_rel));
-		XLogReportUnloggedStatement(reason);
-	}
-
 	/*
 	 * If the rel isn't temp, must fsync before commit.  We use heap_sync to
 	 * ensure that the toast table gets fsync'd too.
diff --git a/src/backend/access/nbtree/nbtsort.c b/src/backend/access/nbtree/nbtsort.c
index 84540b7353046f927fd11b2b33d6379265f17a73..15964e127e5f946f47ecea9eadcb7410fd7e3416 100644
--- a/src/backend/access/nbtree/nbtsort.c
+++ b/src/backend/access/nbtree/nbtsort.c
@@ -59,7 +59,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsort.c,v 1.124 2010/02/26 02:00:34 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsort.c,v 1.125 2010/04/28 16:10:40 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -215,19 +215,6 @@ _bt_leafbuild(BTSpool *btspool, BTSpool *btspool2)
 	 */
 	wstate.btws_use_wal = XLogIsNeeded() && !wstate.index->rd_istemp;
 
-	/*
-	 * Write an XLOG UNLOGGED record if WAL-logging was skipped because WAL
-	 * archiving is not enabled.
-	 */
-	if (!wstate.btws_use_wal && !wstate.index->rd_istemp)
-	{
-		char		reason[NAMEDATALEN + 20];
-
-		snprintf(reason, sizeof(reason), "b-tree build on \"%s\"",
-				 RelationGetRelationName(wstate.index));
-		XLogReportUnloggedStatement(reason);
-	}
-
 	/* reserve the metapage */
 	wstate.btws_pages_alloced = BTREE_METAPAGE + 1;
 	wstate.btws_pages_written = 0;
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 6812cf5e9a4c8bebcf067ec4d080a311a85e770c..2d3dab39fe597493cb1fdcd22f5525c738cf5977 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.404 2010/04/27 09:25:18 heikki Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.405 2010/04/28 16:10:40 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -76,6 +76,7 @@ int			MaxStandbyDelay = 30;
 bool		fullPageWrites = true;
 bool		log_checkpoints = false;
 int			sync_method = DEFAULT_SYNC_METHOD;
+int			wal_level = WAL_LEVEL_MINIMAL;
 
 #ifdef WAL_DEBUG
 bool		XLOG_DEBUG = false;
@@ -97,6 +98,13 @@ bool		XLOG_DEBUG = false;
 /*
  * GUC support
  */
+const struct config_enum_entry wal_level_options[] = {
+	{"minimal", WAL_LEVEL_MINIMAL, false},
+	{"archive", WAL_LEVEL_ARCHIVE, false},
+	{"hot_standby", WAL_LEVEL_HOT_STANDBY, false},
+	{NULL, 0, false}
+};
+
 const struct config_enum_entry sync_method_options[] = {
 	{"fsync", SYNC_METHOD_FSYNC, false},
 #ifdef HAVE_FSYNC_WRITETHROUGH
@@ -500,6 +508,18 @@ static bool reachedMinRecoveryPoint = false;
 
 static bool InRedo = false;
 
+/*
+ * Information logged when we detect a change in one of the parameters
+ * important for Hot Standby.
+ */
+typedef struct xl_parameter_change
+{
+	int			MaxConnections;
+	int			max_prepared_xacts;
+	int			max_locks_per_xact;
+	int			wal_level;
+} xl_parameter_change;
+
 /*
  * Flags set by interrupt handlers for later service in the redo loop.
  */
@@ -522,7 +542,8 @@ static void readRecoveryCommandFile(void);
 static void exitArchiveRecovery(TimeLineID endTLI,
 					uint32 endLogId, uint32 endLogSeg);
 static bool recoveryStopsHere(XLogRecord *record, bool *includeThis);
-static void CheckRequiredParameterValues(CheckPoint checkPoint);
+static void CheckRequiredParameterValues(void);
+static void XLogReportParameters(void);
 static void LocalSetXLogInsertAllowed(void);
 static void CheckPointGuts(XLogRecPtr checkPointRedo, int flags);
 
@@ -4922,6 +4943,13 @@ BootStrapXLOG(void)
 	ControlFile->time = checkPoint.time;
 	ControlFile->checkPoint = checkPoint.redo;
 	ControlFile->checkPointCopy = checkPoint;
+
+	/* Set important parameter values for use when replaying WAL */
+	ControlFile->MaxConnections = MaxConnections;
+	ControlFile->max_prepared_xacts = max_prepared_xacts;
+	ControlFile->max_locks_per_xact = max_locks_per_xact;
+	ControlFile->wal_level = wal_level;
+
 	/* some additional ControlFile fields are set in WriteControlFile() */
 
 	WriteControlFile();
@@ -5539,17 +5567,18 @@ GetLatestXLogTime(void)
 }
 
 /*
- * Note that text field supplied is a parameter name and does not require translation
+ * Note that text field supplied is a parameter name and does not require
+ * translation
  */
-#define RecoveryRequiresIntParameter(param_name, currValue, checkpointValue) \
+#define RecoveryRequiresIntParameter(param_name, currValue, minValue) \
 { \
-	if (currValue < checkpointValue) \
+	if (currValue < minValue) \
 		ereport(ERROR, \
 			(errmsg("recovery connections cannot continue because " \
 					"%s = %u is a lower setting than on WAL source server (value was %u)", \
 					param_name, \
 					currValue, \
-					checkpointValue))); \
+					minValue))); \
 }
 
 /*
@@ -5557,21 +5586,37 @@ GetLatestXLogTime(void)
  * for various aspects of recovery operation.
  */
 static void
-CheckRequiredParameterValues(CheckPoint checkPoint)
+CheckRequiredParameterValues(void)
 {
-	/* We ignore autovacuum_max_workers when we make this test. */
-	RecoveryRequiresIntParameter("max_connections",
-								 MaxConnections, checkPoint.MaxConnections);
+	/*
+	 * For archive recovery, the WAL must be generated with at least
+	 * 'archive' wal_level.
+	 */
+	if (InArchiveRecovery && ControlFile->wal_level == WAL_LEVEL_MINIMAL)
+	{
+		ereport(WARNING,
+				(errmsg("WAL was generated with wal_level='minimal', data may be missing"),
+				 errhint("This happens if you temporarily set wal_level='minimal' without taking a new base backup.")));
+	}
 
-	RecoveryRequiresIntParameter("max_prepared_xacts",
-						  max_prepared_xacts, checkPoint.max_prepared_xacts);
-	RecoveryRequiresIntParameter("max_locks_per_xact",
-						  max_locks_per_xact, checkPoint.max_locks_per_xact);
+	/*
+	 * For Hot Standby, the WAL must be generated with 'hot_standby' mode,
+	 * and we must have at least as many backend slots as the primary.
+	 */
+	if (InArchiveRecovery && XLogRequestRecoveryConnections)
+	{
+		if (ControlFile->wal_level < WAL_LEVEL_HOT_STANDBY)
+			ereport(ERROR,
+					(errmsg("recovery connections cannot start because wal_level was not set to 'hot_standby' on the WAL source server")));
 
-	if (!checkPoint.XLogStandbyInfoMode)
-		ereport(ERROR,
-				(errmsg("recovery connections cannot start because the recovery_connections "
-						"parameter is disabled on the WAL source server")));
+		/* We ignore autovacuum_max_workers when we make this test. */
+		RecoveryRequiresIntParameter("max_connections",
+									 MaxConnections, ControlFile->MaxConnections);
+		RecoveryRequiresIntParameter("max_prepared_xacts",
+									 max_prepared_xacts, ControlFile->max_prepared_xacts);
+		RecoveryRequiresIntParameter("max_locks_per_xact",
+									 max_locks_per_xact, ControlFile->max_locks_per_xact);
+	}
 }
 
 /*
@@ -5904,6 +5949,9 @@ StartupXLOG(void)
 								BACKUP_LABEL_FILE, BACKUP_LABEL_OLD)));
 		}
 
+		/* Check that the GUCs used to generate the WAL allow recovery */
+		CheckRequiredParameterValues();
+
 		/*
 		 * Initialize recovery connections, if enabled. We won't let backends
 		 * in yet, not until we've reached the min recovery point specified in
@@ -5915,8 +5963,6 @@ StartupXLOG(void)
 			TransactionId *xids;
 			int			nxids;
 
-			CheckRequiredParameterValues(checkPoint);
-
 			ereport(DEBUG1,
 					(errmsg("initializing recovery connections")));
 
@@ -6400,6 +6446,13 @@ StartupXLOG(void)
 		readRecordBufSize = 0;
 	}
 
+	/*
+	 * If any of the critical GUCs have changed, log them before we allow
+	 * backends to write WAL.
+	 */
+	LocalSetXLogInsertAllowed();
+	XLogReportParameters();
+
 	/*
 	 * All done.  Allow backends to write WAL.	(Although the bool flag is
 	 * probably atomic in itself, we use the info_lck here to ensure that
@@ -6998,12 +7051,6 @@ CreateCheckPoint(int flags)
 	MemSet(&checkPoint, 0, sizeof(checkPoint));
 	checkPoint.time = (pg_time_t) time(NULL);
 
-	/* Set important parameter values for use when replaying WAL */
-	checkPoint.MaxConnections = MaxConnections;
-	checkPoint.max_prepared_xacts = max_prepared_xacts;
-	checkPoint.max_locks_per_xact = max_locks_per_xact;
-	checkPoint.XLogStandbyInfoMode = XLogStandbyInfoActive();
-
 	/*
 	 * We must hold WALInsertLock while examining insert state to determine
 	 * the checkpoint REDO pointer.
@@ -7647,28 +7694,49 @@ RequestXLogSwitch(void)
 }
 
 /*
- * Write an XLOG UNLOGGED record, indicating that some operation was
- * performed on data that we fsync()'d directly to disk, skipping
- * WAL-logging.
- *
- * Such operations screw up archive recovery, so we complain if we see
- * these records during archive recovery. That shouldn't happen in a
- * correctly configured server, but you can induce it by temporarily
- * disabling archiving and restarting, so it's good to at least get a
- * warning of silent data loss in such cases. These records serve no
- * other purpose and are simply ignored during crash recovery.
+ * Check if any of the GUC parameters that are critical for hot standby
+ * have changed, and update the value in pg_control file if necessary.
  */
-void
-XLogReportUnloggedStatement(char *reason)
+static void
+XLogReportParameters(void)
 {
-	XLogRecData rdata;
+	if (wal_level != ControlFile->wal_level ||
+		MaxConnections != ControlFile->MaxConnections ||
+		max_prepared_xacts != ControlFile->max_prepared_xacts ||
+		max_locks_per_xact != max_locks_per_xact)
+	{
+		/*
+		 * The change in number of backend slots doesn't need to be
+		 * WAL-logged if archiving is not enabled, as you can't start
+		 * archive recovery with wal_level='minimal' anyway. We don't
+		 * really care about the values in pg_control either if
+		 * wal_level='minimal', but seems better to keep them up-to-date
+		 * to avoid confusion.
+		 */
+		if (wal_level != ControlFile->wal_level || XLogIsNeeded())
+		{
+			XLogRecData rdata;
+			xl_parameter_change xlrec;
 
-	rdata.buffer = InvalidBuffer;
-	rdata.data = reason;
-	rdata.len = strlen(reason) + 1;
-	rdata.next = NULL;
+			xlrec.MaxConnections = MaxConnections;
+			xlrec.max_prepared_xacts = max_prepared_xacts;
+			xlrec.max_locks_per_xact = max_locks_per_xact;
+			xlrec.wal_level = wal_level;
+
+			rdata.buffer = InvalidBuffer;
+			rdata.data = (char *) &xlrec;
+			rdata.len = sizeof(xlrec);
+			rdata.next = NULL;
+
+			XLogInsert(RM_XLOG_ID, XLOG_PARAMETER_CHANGE, &rdata);
+		}
 
-	XLogInsert(RM_XLOG_ID, XLOG_UNLOGGED, &rdata);
+		ControlFile->MaxConnections = MaxConnections;
+		ControlFile->max_prepared_xacts = max_prepared_xacts;
+		ControlFile->max_locks_per_xact = max_locks_per_xact;
+		ControlFile->wal_level = wal_level;
+		UpdateControlFile();
+	}
 }
 
 /*
@@ -7709,10 +7777,6 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record)
 							  checkPoint.nextMultiOffset);
 		SetTransactionIdLimit(checkPoint.oldestXid, checkPoint.oldestXidDB);
 
-		/* Check to see if any changes to max_connections give problems */
-		if (standbyState != STANDBY_DISABLED)
-			CheckRequiredParameterValues(checkPoint);
-
 		/*
 		 * If we see a shutdown checkpoint while waiting for an
 		 * end-of-backup record, the backup was cancelled and the
@@ -7844,18 +7908,21 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record)
 			LWLockRelease(ControlFileLock);
 		}
 	}
-	else if (info == XLOG_UNLOGGED)
+	else if (info == XLOG_PARAMETER_CHANGE)
 	{
-		if (InArchiveRecovery)
-		{
-			/*
-			 * Note: We don't print the reason string from the record, because
-			 * that gets added as a line using xlog_desc()
-			 */
-			ereport(WARNING,
-				(errmsg("unlogged operation performed, data may be missing"),
-				 errhint("This can happen if you temporarily disable archive_mode without taking a new base backup.")));
-		}
+		xl_parameter_change xlrec;
+
+		/* Update our copy of the parameters in pg_control */
+		memcpy(&xlrec, XLogRecGetData(record), sizeof(xl_parameter_change));
+
+		ControlFile->MaxConnections = xlrec.MaxConnections;
+		ControlFile->max_prepared_xacts = xlrec.max_prepared_xacts;
+		ControlFile->max_locks_per_xact = xlrec.max_locks_per_xact;
+		ControlFile->wal_level = xlrec.wal_level;
+		UpdateControlFile();
+
+		/* Check to see if any changes to max_connections give problems */
+		CheckRequiredParameterValues();
 	}
 }
 
@@ -7906,11 +7973,30 @@ xlog_desc(StringInfo buf, uint8 xl_info, char *rec)
 		appendStringInfo(buf, "backup end: %X/%X",
 						 startpoint.xlogid, startpoint.xrecoff);
 	}
-	else if (info == XLOG_UNLOGGED)
+	else if (info == XLOG_PARAMETER_CHANGE)
 	{
-		char	   *reason = rec;
+		xl_parameter_change xlrec;
+		const char *wal_level_str;
+		const struct config_enum_entry *entry;
+
+		memcpy(&xlrec, rec, sizeof(xl_parameter_change));
+
+		/* Find a string representation for wal_level */
+		wal_level_str = "?";
+		for (entry = wal_level_options; entry->name; entry++)
+		{
+			if (entry->val == xlrec.wal_level)
+			{
+				wal_level_str = entry->name;
+				break;
+			}
+		}
 
-		appendStringInfo(buf, "unlogged operation: %s", reason);
+		appendStringInfo(buf, "parameter change: max_connections=%d max_prepared_xacts=%d max_locks_per_xact=%d wal_level=%s",
+						 xlrec.MaxConnections,
+						 xlrec.max_prepared_xacts,
+						 xlrec.max_locks_per_xact,
+						 wal_level_str);
 	}
 	else
 		appendStringInfo(buf, "UNKNOWN");
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index 78df9a8da8565bef0649027aa1f5b88cc0f7c655..7a1b8e885bea622851d0702484f23c42f3398a9d 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.202 2010/02/26 02:00:37 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.203 2010/04/28 16:10:41 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -787,23 +787,6 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex,
 	 */
 	use_wal = XLogIsNeeded() && !NewHeap->rd_istemp;
 
-	/*
-	 * Write an XLOG UNLOGGED record if WAL-logging was skipped because WAL
-	 * archiving is not enabled.
-	 */
-	if (!use_wal && !NewHeap->rd_istemp)
-	{
-		char		reason[NAMEDATALEN + 32];
-
-		if (OldIndex != NULL)
-			snprintf(reason, sizeof(reason), "CLUSTER on \"%s\"",
-					 RelationGetRelationName(NewHeap));
-		else
-			snprintf(reason, sizeof(reason), "VACUUM FULL on \"%s\"",
-					 RelationGetRelationName(NewHeap));
-		XLogReportUnloggedStatement(reason);
-	}
-
 	/* use_wal off requires smgr_targblock be initially invalid */
 	Assert(RelationGetTargetBlock(NewHeap) == InvalidBlockNumber);
 
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 9031cd1fa5113afd7002406c58bd0cc7b6042429..4e95a8315cecbaa4fc1a8da078ab63393d10d508 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.326 2010/02/26 02:00:38 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.327 2010/04/28 16:10:41 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2223,14 +2223,7 @@ CopyFrom(CopyState cstate)
 	 * indexes since those use WAL anyway)
 	 */
 	if (hi_options & HEAP_INSERT_SKIP_WAL)
-	{
-		char		reason[NAMEDATALEN + 30];
-
-		snprintf(reason, sizeof(reason), "COPY FROM on \"%s\"",
-				 RelationGetRelationName(cstate->rel));
-		XLogReportUnloggedStatement(reason);
 		heap_sync(cstate->rel);
-	}
 }
 
 
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index dda0b2e847eab35046a59e556b2269ae2aa38c3f..18e2f571283efb660cc2819689f08fac6dcc6cdc 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.329 2010/03/20 00:43:42 rhaas Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.330 2010/04/28 16:10:41 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -3272,14 +3272,7 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap)
 
 		/* If we skipped writing WAL, then we need to sync the heap. */
 		if (hi_options & HEAP_INSERT_SKIP_WAL)
-		{
-			char		reason[NAMEDATALEN + 30];
-
-			snprintf(reason, sizeof(reason), "table rewrite on \"%s\"",
-					 RelationGetRelationName(newrel));
-			XLogReportUnloggedStatement(reason);
 			heap_sync(newrel);
-		}
 
 		heap_close(newrel, NoLock);
 	}
@@ -7021,20 +7014,6 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace)
 
 	heap_close(pg_class, RowExclusiveLock);
 
-	/*
-	 * Write an XLOG UNLOGGED record if WAL-logging was skipped because WAL
-	 * archiving is not enabled.
-	 */
-	if (!XLogIsNeeded() && !rel->rd_istemp)
-	{
-		char		reason[NAMEDATALEN + 40];
-
-		snprintf(reason, sizeof(reason), "ALTER TABLE SET TABLESPACE on \"%s\"",
-				 RelationGetRelationName(rel));
-
-		XLogReportUnloggedStatement(reason);
-	}
-
 	relation_close(rel, NoLock);
 
 	/* Make sure the reltablespace change is visible */
@@ -7063,10 +7042,6 @@ copy_relation_data(SMgrRelation src, SMgrRelation dst,
 	/*
 	 * We need to log the copied data in WAL iff WAL archiving/streaming is
 	 * enabled AND it's not a temp rel.
-	 *
-	 * Note: If you change the conditions here, update the conditions in
-	 * ATExecSetTableSpace() for when an XLOG UNLOGGED record is written to
-	 * match.
 	 */
 	use_wal = XLogIsNeeded() && !istemp;
 
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 151299555cf02f2f05cb368ab249662b6d08e6b9..0b6cbcc4af0484f8d07f0263c01444af577efe59 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -26,7 +26,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.348 2010/02/26 02:00:41 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.349 2010/04/28 16:10:42 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2241,14 +2241,7 @@ CloseIntoRel(QueryDesc *queryDesc)
 
 		/* If we skipped using WAL, must heap_sync before commit */
 		if (myState->hi_options & HEAP_INSERT_SKIP_WAL)
-		{
-			char		reason[NAMEDATALEN + 30];
-
-			snprintf(reason, sizeof(reason), "SELECT INTO on \"%s\"",
-					 RelationGetRelationName(myState->rel));
-			XLogReportUnloggedStatement(reason);
 			heap_sync(myState->rel);
-		}
 
 		/* close rel, but keep lock until commit */
 		heap_close(myState->rel, NoLock);
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index d77ffd07438d81397a4d546a6a1c5ea389555706..f5396df0668f32d4ad19d9fa4747403a984dea79 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -37,7 +37,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.605 2010/04/08 01:39:37 rhaas Exp $
+ *	  $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.606 2010/04/28 16:10:42 heikki Exp $
  *
  * NOTES
  *
@@ -728,6 +728,12 @@ PostmasterMain(int argc, char *argv[])
 		write_stderr("%s: superuser_reserved_connections must be less than max_connections\n", progname);
 		ExitPostmaster(1);
 	}
+	if (XLogArchiveMode && wal_level == WAL_LEVEL_MINIMAL)
+		ereport(ERROR,
+				(errmsg("WAL archival (archive_mode='on') requires wal_level 'archive' or 'hot_standby'")));
+	if (max_wal_senders > 0 && wal_level == WAL_LEVEL_MINIMAL)
+		ereport(ERROR,
+				(errmsg("WAL streaming (max_wal_senders > 0) requires wal_level 'archive' or 'hot_standby")));
 
 	/*
 	 * Other one-time internal sanity checks can go here, if they are fast.
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 1c1e9f17d2dba06d258f43a22fcd42116a94feec..6c41844b5f8e92916fa0b4459f098d324840e0de 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -30,7 +30,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/replication/walsender.c,v 1.17 2010/04/21 00:51:56 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/replication/walsender.c,v 1.18 2010/04/28 16:10:42 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -253,6 +253,24 @@ WalSndHandshake(void)
 					{
 						StringInfoData buf;
 
+						/*
+						 * Check that we're logging enough information in the
+						 * WAL for log-shipping.
+						 *
+						 * NOTE: This only checks the current value of
+						 * wal_level. Even if the current setting is not
+						 * 'minimal', there can be old WAL in the pg_xlog
+						 * directory that was created with 'minimal'.
+						 * So this is not bulletproof, the purpose is
+						 * just to give a user-friendly error message that
+						 * hints how to configure the system correctly.
+						 */
+						if (wal_level == WAL_LEVEL_MINIMAL)
+							ereport(FATAL,
+									(errcode(ERRCODE_CANNOT_CONNECT_NOW),
+									 errmsg("standby connections not allowed because wal_level='minimal'")));
+
+
 						/* Send a CopyOutResponse message, and start streaming */
 						pq_beginmessage(&buf, 'H');
 						pq_sendbyte(&buf, 0);
diff --git a/src/backend/storage/ipc/standby.c b/src/backend/storage/ipc/standby.c
index e8a4fc2e938f413075f4b5bca5786b4f2dc7e34c..30723327cd287b1537064d467000cb21709062a3 100644
--- a/src/backend/storage/ipc/standby.c
+++ b/src/backend/storage/ipc/standby.c
@@ -11,7 +11,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/storage/ipc/standby.c,v 1.19 2010/04/23 23:21:44 rhaas Exp $
+ *	  $PostgreSQL: pgsql/src/backend/storage/ipc/standby.c,v 1.20 2010/04/28 16:10:42 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -256,7 +256,7 @@ ResolveRecoveryConflictWithSnapshot(TransactionId latestRemovedXid, RelFileNode
 	 */
 	if (!TransactionIdIsValid(latestRemovedXid))
 	{
-		elog(DEBUG1, "Invalid latestremovexXid reported, using latestcompletedxid instead");
+		elog(DEBUG1, "invalid latestremovexXid reported, using latestcompletedxid instead");
 
 		LWLockAcquire(ProcArrayLock, LW_SHARED);
 		latestRemovedXid = ShmemVariableCache->latestCompletedXid;
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index e7266d5fb10393a85a8b2d40db5242d798e25c48..2404da844195321a3ecbaf3fc8d3d037e33a4560 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -10,7 +10,7 @@
  * Written by Peter Eisentraut <peter_e@gmx.net>.
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.551 2010/04/22 19:40:03 petere Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.552 2010/04/28 16:10:42 heikki Exp $
  *
  *--------------------------------------------------------------------
  */
@@ -340,6 +340,7 @@ static const struct config_enum_entry constraint_exclusion_options[] = {
 /*
  * Options for enum values stored in other modules
  */
+extern const struct config_enum_entry wal_level_options[];
 extern const struct config_enum_entry sync_method_options[];
 
 /*
@@ -2784,6 +2785,15 @@ static struct config_enum ConfigureNamesEnum[] =
 		TRACK_FUNC_OFF, track_function_options, NULL, NULL
 	},
 
+	{
+		{"wal_level", PGC_POSTMASTER, WAL_SETTINGS,
+			gettext_noop("Set the level of information written to the WAL."),
+			NULL
+		},
+		&wal_level,
+		WAL_LEVEL_MINIMAL, wal_level_options, NULL
+	},
+
 	{
 		{"wal_sync_method", PGC_SIGHUP, WAL_SETTINGS,
 			gettext_noop("Selects the method used for forcing WAL updates to disk."),
@@ -7862,7 +7872,7 @@ pg_timezone_abbrev_initialize(void)
 static const char *
 show_archive_command(void)
 {
-	if (XLogArchiveMode)
+	if (XLogArchivingActive())
 		return XLogArchiveCommand;
 	else
 		return "(disabled)";
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 92763eb523a251134db689bf7aa43c3dc25613a5..57497115689e631f2b3f923c78622e9527dc7158 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -150,6 +150,7 @@
 
 # - Settings -
 
+#wal_level = minimal			# minimal, archive, or hot_standby
 #fsync = on				# turns forced synchronization on or off
 #synchronous_commit = on		# immediate fsync at commit
 #wal_sync_method = fsync		# the default is the first option 
diff --git a/src/bin/pg_controldata/pg_controldata.c b/src/bin/pg_controldata/pg_controldata.c
index 2735a6611e2755a9b65317ff23e2925a5cdaca68..839de98842b92f1835d7532d80c0618f7d81adcf 100644
--- a/src/bin/pg_controldata/pg_controldata.c
+++ b/src/bin/pg_controldata/pg_controldata.c
@@ -6,15 +6,16 @@
  * copyright (c) Oliver Elphick <olly@lfix.co.uk>, 2001;
  * licence: BSD
  *
- * $PostgreSQL: pgsql/src/bin/pg_controldata/pg_controldata.c,v 1.46 2010/01/04 12:50:49 heikki Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_controldata/pg_controldata.c,v 1.47 2010/04/28 16:10:43 heikki Exp $
  */
-#include "postgres_fe.h"
+#include "postgres.h"
 
 #include <unistd.h>
 #include <time.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 
+#include "access/xlog.h"
 #include "catalog/pg_control.h"
 
 
@@ -60,6 +61,21 @@ dbState(DBState state)
 	return _("unrecognized status code");
 }
 
+static const char *
+wal_level_str(WalLevel wal_level)
+{
+	switch (wal_level)
+	{
+		case WAL_LEVEL_MINIMAL:
+			return "minimal";
+		case WAL_LEVEL_ARCHIVE:
+			return "archive";
+		case WAL_LEVEL_HOT_STANDBY:
+			return "hot_standby";
+	}
+	return _("unrecognized wal_level");
+}
+
 
 int
 main(int argc, char *argv[])
@@ -206,6 +222,14 @@ main(int argc, char *argv[])
 	printf(_("Backup start location:                %X/%X\n"),
 		   ControlFile.backupStartPoint.xlogid,
 		   ControlFile.backupStartPoint.xrecoff);
+	printf(_("Last wal_level setting:               %s\n"),
+		   wal_level_str(ControlFile.wal_level));
+	printf(_("Last max_connections setting:         %d\n"),
+		   ControlFile.MaxConnections);
+	printf(_("Last max_prepared_xacts setting:      %d\n"),
+		   ControlFile.max_prepared_xacts);
+	printf(_("Last max_locks_per_xact setting:      %d\n"),
+		   ControlFile.max_locks_per_xact);
 	printf(_("Maximum data alignment:               %u\n"),
 		   ControlFile.maxAlign);
 	/* we don't print floatFormat since can't say much useful about it */
diff --git a/src/bin/pg_resetxlog/pg_resetxlog.c b/src/bin/pg_resetxlog/pg_resetxlog.c
index d14df9cec8b328c2c1133252ae46285fc446ad06..a8a43c44f005bf126c9dae0f45209ca781bafb3c 100644
--- a/src/bin/pg_resetxlog/pg_resetxlog.c
+++ b/src/bin/pg_resetxlog/pg_resetxlog.c
@@ -23,7 +23,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/bin/pg_resetxlog/pg_resetxlog.c,v 1.78 2010/02/26 02:01:17 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_resetxlog/pg_resetxlog.c,v 1.79 2010/04/28 16:10:43 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -628,6 +628,15 @@ RewriteControlFile(void)
 	ControlFile.backupStartPoint.xlogid = 0;
 	ControlFile.backupStartPoint.xrecoff = 0;
 
+	/*
+	 * Use the defaults for max_* settings. The values don't matter
+	 * as long as wal_level='minimal'.
+	 */
+	ControlFile.MaxConnections = 100;
+	ControlFile.max_prepared_xacts = 0;
+	ControlFile.max_locks_per_xact = 64;
+	ControlFile.wal_level = WAL_LEVEL_MINIMAL;
+
 	/* Now we can force the recorded xlog seg size to the right thing. */
 	ControlFile.xlog_seg_size = XLogSegSize;
 
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index 4812997659f38bb374f3217ff3c733cc7cc775eb..6936a2a5791c05f36e5cb18adfda0172e8c1c439 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/xlog.h,v 1.109 2010/04/20 11:15:06 rhaas Exp $
+ * $PostgreSQL: pgsql/src/include/access/xlog.h,v 1.110 2010/04/28 16:10:43 heikki Exp $
  */
 #ifndef XLOG_H
 #define XLOG_H
@@ -195,24 +195,26 @@ extern int	XLogArchiveTimeout;
 extern bool log_checkpoints;
 extern bool XLogRequestRecoveryConnections;
 extern int	MaxStandbyDelay;
+/* WAL levels */
+typedef enum WalLevel
+{
+	WAL_LEVEL_MINIMAL = 0,
+	WAL_LEVEL_ARCHIVE,
+	WAL_LEVEL_HOT_STANDBY
+} WalLevel;
+extern int	wal_level;
 
-#define XLogArchivingActive()	(XLogArchiveMode)
+#define XLogArchivingActive()	(XLogArchiveMode && wal_level >= WAL_LEVEL_ARCHIVE)
 #define XLogArchiveCommandSet() (XLogArchiveCommand[0] != '\0')
 
 /*
- * This is in walsender.c, but declared here so that we don't need to include
- * walsender.h in all files that check XLogIsNeeded()
- */
-extern int	max_wal_senders;
-
-/*
- * Is WAL-logging necessary? We need to log an XLOG record iff either
- * WAL archiving is enabled or XLOG streaming is allowed.
+ * Is WAL-logging necessary for archival or log-shipping, or can we skip
+ * WAL-logging if we fsync() the data before committing instead?
  */
-#define XLogIsNeeded() (XLogArchivingActive() || (max_wal_senders > 0))
+#define XLogIsNeeded() (wal_level >= WAL_LEVEL_ARCHIVE)
 
 /* Do we need to WAL-log information required only for Hot Standby? */
-#define XLogStandbyInfoActive() (XLogRequestRecoveryConnections && XLogIsNeeded())
+#define XLogStandbyInfoActive() (wal_level >= WAL_LEVEL_HOT_STANDBY)
 
 #ifdef WAL_DEBUG
 extern bool XLOG_DEBUG;
@@ -293,7 +295,6 @@ extern void InitXLOGAccess(void);
 extern void CreateCheckPoint(int flags);
 extern bool CreateRestartPoint(int flags);
 extern void XLogPutNextOid(Oid nextOid);
-extern void XLogReportUnloggedStatement(char *reason);
 extern XLogRecPtr GetRedoRecPtr(void);
 extern XLogRecPtr GetInsertRecPtr(void);
 extern XLogRecPtr GetWriteRecPtr(void);
diff --git a/src/include/access/xlog_internal.h b/src/include/access/xlog_internal.h
index fa21f0a916a3348bcb4cf702601cdeed02b33f9d..3f0930f3951eee844fce4f91c0fb57036c0bd058 100644
--- a/src/include/access/xlog_internal.h
+++ b/src/include/access/xlog_internal.h
@@ -11,7 +11,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/xlog_internal.h,v 1.32 2010/04/12 10:40:43 heikki Exp $
+ * $PostgreSQL: pgsql/src/include/access/xlog_internal.h,v 1.33 2010/04/28 16:10:43 heikki Exp $
  */
 #ifndef XLOG_INTERNAL_H
 #define XLOG_INTERNAL_H
@@ -71,7 +71,7 @@ typedef struct XLogContRecord
 /*
  * Each page of XLOG file has a header like this:
  */
-#define XLOG_PAGE_MAGIC 0x9003	/* can be used as WAL version indicator */
+#define XLOG_PAGE_MAGIC 0xD064	/* can be used as WAL version indicator */
 
 typedef struct XLogPageHeaderData
 {
diff --git a/src/include/catalog/pg_control.h b/src/include/catalog/pg_control.h
index 7342468d055074bd64b250635f7632776350ed99..8deef6d354d55ad80566bbdbba88baf39fbb248d 100644
--- a/src/include/catalog/pg_control.h
+++ b/src/include/catalog/pg_control.h
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_control.h,v 1.53 2010/04/23 20:21:31 sriggs Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_control.h,v 1.54 2010/04/28 16:10:43 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,7 +21,7 @@
 
 
 /* Version identifier for this pg_control format */
-#define PG_CONTROL_VERSION	901
+#define PG_CONTROL_VERSION	902
 
 /*
  * Body of CheckPoint XLOG records.  This is declared here because we keep
@@ -41,12 +41,6 @@ typedef struct CheckPoint
 	Oid			oldestXidDB;	/* database with minimum datfrozenxid */
 	pg_time_t	time;			/* time stamp of checkpoint */
 
-	/* Important parameter settings at time of shutdown checkpoints */
-	int			MaxConnections;
-	int			max_prepared_xacts;
-	int			max_locks_per_xact;
-	bool		XLogStandbyInfoMode;
-
 	/*
 	 * Oldest XID still running. This is only needed to initialize hot standby
 	 * mode from an online checkpoint, so we only bother calculating this for
@@ -63,7 +57,7 @@ typedef struct CheckPoint
 #define XLOG_NEXTOID					0x30
 #define XLOG_SWITCH						0x40
 #define XLOG_BACKUP_END					0x50
-#define XLOG_UNLOGGED					0x60
+#define XLOG_PARAMETER_CHANGE			0x60
 
 
 /* System status indicator */
@@ -141,6 +135,15 @@ typedef struct ControlFileData
 	XLogRecPtr	minRecoveryPoint;
 	XLogRecPtr	backupStartPoint;
 
+	/*
+	 * Parameter settings that determine if the WAL can be used for archival
+	 * or hot standby.
+	 */
+	int			wal_level;
+	int			MaxConnections;
+	int			max_prepared_xacts;
+	int			max_locks_per_xact;
+
 	/*
 	 * This data is used to check for hardware-architecture compatibility of
 	 * the database and the backend executable.  We need not check endianness
diff --git a/src/include/replication/walsender.h b/src/include/replication/walsender.h
index abb8312ecf78eb07c5e3302eb0d0ae5149830523..d43ad912e762ea5d9da62bb0af47b4027695eeab 100644
--- a/src/include/replication/walsender.h
+++ b/src/include/replication/walsender.h
@@ -5,7 +5,7 @@
  *
  * Portions Copyright (c) 2010-2010, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/include/replication/walsender.h,v 1.2 2010/02/26 02:01:27 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/replication/walsender.h,v 1.3 2010/04/28 16:10:43 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -39,6 +39,7 @@ extern bool am_walsender;
 
 /* user-settable parameters */
 extern int	WalSndDelay;
+extern int	max_wal_senders;
 
 extern int	WalSenderMain(void);
 extern void WalSndSignals(void);