Hi all

After spending a while working on the BDR extension I've found that the
current documentation on the SPI and bgworkers could use some more detail.

In the process I've put cross reference labels in for most chapter
headings, as I got sick of seeing "Chapter 33" (or whatever) everywhere in
the docs. I'd like to progressively add them to every section, refentry,
chapter, etc that has an id.

I hope this is useful.

-- 
 Craig Ringer                   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services
From c73d1303cb3474ccc799eeda252eeef1fc3d9026 Mon Sep 17 00:00:00 2001
From: Craig Ringer <cr...@2ndquadrant.com>
Date: Mon, 16 Feb 2015 18:17:48 +1300
Subject: [PATCH 1/4] Add xreflabel to most chapter entries

---
 doc/src/sgml/array.sgml              | 2 +-
 doc/src/sgml/backup.sgml             | 2 +-
 doc/src/sgml/brin.sgml               | 2 +-
 doc/src/sgml/catalogs.sgml           | 2 +-
 doc/src/sgml/client-auth.sgml        | 2 +-
 doc/src/sgml/config.sgml             | 2 +-
 doc/src/sgml/datatype.sgml           | 2 +-
 doc/src/sgml/ddl.sgml                | 2 +-
 doc/src/sgml/diskusage.sgml          | 2 +-
 doc/src/sgml/dml.sgml                | 2 +-
 doc/src/sgml/errcodes.sgml           | 2 +-
 doc/src/sgml/event-trigger.sgml      | 2 +-
 doc/src/sgml/extend.sgml             | 2 +-
 doc/src/sgml/features.sgml           | 2 +-
 doc/src/sgml/func.sgml               | 2 +-
 doc/src/sgml/gin.sgml                | 2 +-
 doc/src/sgml/gist.sgml               | 2 +-
 doc/src/sgml/high-availability.sgml  | 2 +-
 doc/src/sgml/indices.sgml            | 2 +-
 doc/src/sgml/information_schema.sgml | 2 +-
 doc/src/sgml/json.sgml               | 2 +-
 doc/src/sgml/keywords.sgml           | 2 +-
 doc/src/sgml/libpq.sgml              | 2 +-
 doc/src/sgml/lobj.sgml               | 2 +-
 doc/src/sgml/logicaldecoding.sgml    | 2 +-
 doc/src/sgml/maintenance.sgml        | 2 +-
 doc/src/sgml/manage-ag.sgml          | 2 +-
 doc/src/sgml/monitoring.sgml         | 2 +-
 doc/src/sgml/mvcc.sgml               | 2 +-
 doc/src/sgml/perform.sgml            | 2 +-
 doc/src/sgml/plperl.sgml             | 2 +-
 doc/src/sgml/plpgsql.sgml            | 2 +-
 doc/src/sgml/plpython.sgml           | 2 +-
 doc/src/sgml/pltcl.sgml              | 2 +-
 doc/src/sgml/rangetypes.sgml         | 2 +-
 doc/src/sgml/recovery-config.sgml    | 2 +-
 doc/src/sgml/reference.sgml          | 2 +-
 doc/src/sgml/regress.sgml            | 2 +-
 doc/src/sgml/release.sgml            | 2 +-
 doc/src/sgml/rowtypes.sgml           | 2 +-
 doc/src/sgml/rules.sgml              | 2 +-
 doc/src/sgml/runtime.sgml            | 2 +-
 doc/src/sgml/spgist.sgml             | 2 +-
 doc/src/sgml/spi.sgml                | 4 ++--
 doc/src/sgml/sql.sgml                | 2 +-
 doc/src/sgml/storage.sgml            | 2 +-
 doc/src/sgml/syntax.sgml             | 2 +-
 doc/src/sgml/textsearch.sgml         | 2 +-
 doc/src/sgml/trigger.sgml            | 2 +-
 doc/src/sgml/typeconv.sgml           | 2 +-
 doc/src/sgml/user-manag.sgml         | 2 +-
 doc/src/sgml/wal.sgml                | 2 +-
 doc/src/sgml/xaggr.sgml              | 2 +-
 doc/src/sgml/xfunc.sgml              | 6 +++---
 doc/src/sgml/xoper.sgml              | 2 +-
 doc/src/sgml/xplang.sgml             | 2 +-
 doc/src/sgml/xtypes.sgml             | 2 +-
 57 files changed, 60 insertions(+), 60 deletions(-)

diff --git a/doc/src/sgml/array.sgml b/doc/src/sgml/array.sgml
index 9ea1068..7c68828 100644
--- a/doc/src/sgml/array.sgml
+++ b/doc/src/sgml/array.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/array.sgml -->
 
-<sect1 id="arrays">
+<sect1 id="arrays" xreflabel="Arrays">
  <title>Arrays</title>
 
  <indexterm>
diff --git a/doc/src/sgml/backup.sgml b/doc/src/sgml/backup.sgml
index 07ca0dc..c1ade01 100644
--- a/doc/src/sgml/backup.sgml
+++ b/doc/src/sgml/backup.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/backup.sgml -->
 
-<chapter id="backup">
+<chapter id="backup" xreflabel="Backup and Restore">
  <title>Backup and Restore</title>
 
  <indexterm zone="backup"><primary>backup</></>
diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml
index 1ac282c..ae6f3f5 100644
--- a/doc/src/sgml/brin.sgml
+++ b/doc/src/sgml/brin.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/brin.sgml -->
 
-<chapter id="BRIN">
+<chapter id="BRIN" xreflabel="BRIN Indexes">
 <title>BRIN Indexes</title>
 
    <indexterm>
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 515a40e..599d524 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -3,7 +3,7 @@
  Documentation of the system catalogs, directed toward PostgreSQL developers
  -->
 
-<chapter id="catalogs">
+<chapter id="catalogs" xreflabel="System Catalogs">
  <title>System Catalogs</title>
 
   <para>
diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml
index 7704f73..22cfc05 100644
--- a/doc/src/sgml/client-auth.sgml
+++ b/doc/src/sgml/client-auth.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/client-auth.sgml -->
 
-<chapter id="client-authentication">
+<chapter id="client-authentication" xreflabel="Client Authentication">
  <title>Client Authentication</title>
 
  <indexterm zone="client-authentication">
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 6bcb106..7d86014 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/config.sgml -->
 
-<chapter id="runtime-config">
+<chapter id="runtime-config" xreflabel="Server Configuration">
   <title>Server Configuration</title>
 
   <indexterm>
diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml
index edf636b..2c2dc9d 100644
--- a/doc/src/sgml/datatype.sgml
+++ b/doc/src/sgml/datatype.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/datatype.sgml -->
 
- <chapter id="datatype">
+ <chapter id="datatype" xreflabel="Data Types">
   <title>Data Types</title>
 
   <indexterm zone="datatype">
diff --git a/doc/src/sgml/ddl.sgml b/doc/src/sgml/ddl.sgml
index 570a003..964e158 100644
--- a/doc/src/sgml/ddl.sgml
+++ b/doc/src/sgml/ddl.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/ddl.sgml -->
 
-<chapter id="ddl">
+<chapter id="ddl" xreflabel="Data Definition">
  <title>Data Definition</title>
 
  <para>
diff --git a/doc/src/sgml/diskusage.sgml b/doc/src/sgml/diskusage.sgml
index 461deb9..20ee0b9 100644
--- a/doc/src/sgml/diskusage.sgml
+++ b/doc/src/sgml/diskusage.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/diskusage.sgml -->
 
-<chapter id="diskusage">
+<chapter id="diskusage" xreflabel="Monitoring Disk Usage">
  <title>Monitoring Disk Usage</title>
 
  <para>
diff --git a/doc/src/sgml/dml.sgml b/doc/src/sgml/dml.sgml
index cd36a73..4472957 100644
--- a/doc/src/sgml/dml.sgml
+++ b/doc/src/sgml/dml.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/dml.sgml -->
 
-<chapter id="dml">
+<chapter id="dml" xreflabel="Data Manipulation">
  <title>Data Manipulation</title>
 
  <remark>
diff --git a/doc/src/sgml/errcodes.sgml b/doc/src/sgml/errcodes.sgml
index 40b4191..31116c2 100644
--- a/doc/src/sgml/errcodes.sgml
+++ b/doc/src/sgml/errcodes.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/errcodes.sgml -->
 
-<appendix id="errcodes-appendix">
+<appendix id="errcodes-appendix" xreflabel="Error Codes">
  <title><productname>PostgreSQL</productname> Error Codes</title>
 
  <indexterm zone="errcodes-appendix">
diff --git a/doc/src/sgml/event-trigger.sgml b/doc/src/sgml/event-trigger.sgml
index 156c463..a0d3505 100644
--- a/doc/src/sgml/event-trigger.sgml
+++ b/doc/src/sgml/event-trigger.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/event-trigger.sgml -->
 
- <chapter id="event-triggers">
+ <chapter id="event-triggers" xreflabel="Event Triggers">
   <title>Event Triggers</title>
 
   <indexterm zone="event-triggers">
diff --git a/doc/src/sgml/extend.sgml b/doc/src/sgml/extend.sgml
index be10252..48814bc 100644
--- a/doc/src/sgml/extend.sgml
+++ b/doc/src/sgml/extend.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/extend.sgml -->
 
- <chapter id="extend">
+ <chapter id="extend" xreflabel="Extending SQL">
   <title>Extending <acronym>SQL</acronym></title>
 
   <indexterm zone="extend">
diff --git a/doc/src/sgml/features.sgml b/doc/src/sgml/features.sgml
index 6c22d69..e4c6b3f 100644
--- a/doc/src/sgml/features.sgml
+++ b/doc/src/sgml/features.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/features.sgml -->
 
-<appendix id="features">
+<appendix id="features" xreflabel="SQL Conformance">
  <title>SQL Conformance</title>
 
  <para>
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index da2ed67..fd8f642 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/func.sgml -->
 
- <chapter id="functions">
+ <chapter id="functions" xreflabel="Functions and Operators">
   <title>Functions and Operators</title>
 
   <indexterm zone="functions">
diff --git a/doc/src/sgml/gin.sgml b/doc/src/sgml/gin.sgml
index 262f1e4..28e7d5e 100644
--- a/doc/src/sgml/gin.sgml
+++ b/doc/src/sgml/gin.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/gin.sgml -->
 
-<chapter id="GIN">
+<chapter id="GIN" xreflabel="GIN Indexes">
 <title>GIN Indexes</title>
 
    <indexterm>
diff --git a/doc/src/sgml/gist.sgml b/doc/src/sgml/gist.sgml
index 31ce279..50721f3 100644
--- a/doc/src/sgml/gist.sgml
+++ b/doc/src/sgml/gist.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/gist.sgml -->
 
-<chapter id="GiST">
+<chapter id="GiST" xreflabel="GiST indexes">
 <title>GiST Indexes</title>
 
    <indexterm>
diff --git a/doc/src/sgml/high-availability.sgml b/doc/src/sgml/high-availability.sgml
index d249959..d07b6e5 100644
--- a/doc/src/sgml/high-availability.sgml
+++ b/doc/src/sgml/high-availability.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/high-availability.sgml -->
 
-<chapter id="high-availability">
+<chapter id="high-availability" xreflabel="High Availability, Load Balancing, and Replication">
  <title>High Availability, Load Balancing, and Replication</title>
 
  <indexterm><primary>high availability</></>
diff --git a/doc/src/sgml/indices.sgml b/doc/src/sgml/indices.sgml
index b73463a..585241d 100644
--- a/doc/src/sgml/indices.sgml
+++ b/doc/src/sgml/indices.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/indices.sgml -->
 
-<chapter id="indexes">
+<chapter id="indexes" xreflabel="Indexes">
  <title>Indexes</title>
 
  <indexterm zone="indexes">
diff --git a/doc/src/sgml/information_schema.sgml b/doc/src/sgml/information_schema.sgml
index 22f43c8..8a3b317 100644
--- a/doc/src/sgml/information_schema.sgml
+++ b/doc/src/sgml/information_schema.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/information_schema.sgml -->
 
-<chapter id="information-schema">
+<chapter id="information-schema" xreflabel="The Information Schema">
  <title>The Information Schema</title>
 
  <indexterm zone="information-schema">
diff --git a/doc/src/sgml/json.sgml b/doc/src/sgml/json.sgml
index 6282ab8..1833e76 100644
--- a/doc/src/sgml/json.sgml
+++ b/doc/src/sgml/json.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/json.sgml -->
 
-<sect1 id="datatype-json">
+<sect1 id="datatype-json" xreflabel="JSON types">
  <title><acronym>JSON</> Types</title>
 
  <indexterm zone="datatype-json">
diff --git a/doc/src/sgml/keywords.sgml b/doc/src/sgml/keywords.sgml
index b0dfd5f..f8345bc 100644
--- a/doc/src/sgml/keywords.sgml
+++ b/doc/src/sgml/keywords.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/keywords.sgml -->
 
-<appendix id="sql-keywords-appendix">
+<appendix id="sql-keywords-appendix" xreflabel="SQL Key Words">
  <title><acronym>SQL</acronym> Key Words</title>
 
  <indexterm zone="sql-keywords-appendix">
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 39aede4..92b4a92 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/libpq.sgml -->
 
-<chapter id="libpq">
+<chapter id="libpq" xreflabel="libpq">
  <title><application>libpq</application> - C Library</title>
 
  <indexterm zone="libpq">
diff --git a/doc/src/sgml/lobj.sgml b/doc/src/sgml/lobj.sgml
index d6fb8c5..cd5df8b 100644
--- a/doc/src/sgml/lobj.sgml
+++ b/doc/src/sgml/lobj.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/lobj.sgml -->
 
- <chapter id="largeObjects">
+ <chapter id="largeObjects" xreflabel="Large Objects">
   <title>Large Objects</title>
 
   <indexterm zone="largeobjects"><primary>large object</></>
diff --git a/doc/src/sgml/logicaldecoding.sgml b/doc/src/sgml/logicaldecoding.sgml
index 3650567..7a70270 100644
--- a/doc/src/sgml/logicaldecoding.sgml
+++ b/doc/src/sgml/logicaldecoding.sgml
@@ -1,5 +1,5 @@
 <!-- doc/src/sgml/logicaldecoding.sgml -->
- <chapter id="logicaldecoding">
+ <chapter id="logicaldecoding" xreflabel="Logical Decoding">
   <title>Logical Decoding</title>
   <indexterm zone="logicaldecoding">
    <primary>Logical Decoding</primary>
diff --git a/doc/src/sgml/maintenance.sgml b/doc/src/sgml/maintenance.sgml
index 8764e00..8d8bbad 100644
--- a/doc/src/sgml/maintenance.sgml
+++ b/doc/src/sgml/maintenance.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/maintenance.sgml -->
 
-<chapter id="maintenance">
+<chapter id="maintenance" xreflabel="Routine Database Maintenance Tasks">
  <title>Routine Database Maintenance Tasks</title>
 
  <indexterm zone="maintenance">
diff --git a/doc/src/sgml/manage-ag.sgml b/doc/src/sgml/manage-ag.sgml
index 78ec509..795d407 100644
--- a/doc/src/sgml/manage-ag.sgml
+++ b/doc/src/sgml/manage-ag.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/manage-ag.sgml -->
 
-<chapter id="managing-databases">
+<chapter id="managing-databases" xreflabel="Managing Databases">
  <title>Managing Databases</title>
 
  <indexterm zone="managing-databases"><primary>database</></>
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 3ce7e80..f062fc3 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/monitoring.sgml -->
 
-<chapter id="monitoring">
+<chapter id="monitoring" xreflabel="Monitoring Database Activity">
  <title>Monitoring Database Activity</title>
 
  <indexterm zone="monitoring">
diff --git a/doc/src/sgml/mvcc.sgml b/doc/src/sgml/mvcc.sgml
index a0d6867..00dcdf9 100644
--- a/doc/src/sgml/mvcc.sgml
+++ b/doc/src/sgml/mvcc.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/mvcc.sgml -->
 
- <chapter id="mvcc">
+ <chapter id="mvcc" xreflabel="Concurrency Control">
   <title>Concurrency Control</title>
 
   <indexterm>
diff --git a/doc/src/sgml/perform.sgml b/doc/src/sgml/perform.sgml
index 5a087fb..0b1b1c3 100644
--- a/doc/src/sgml/perform.sgml
+++ b/doc/src/sgml/perform.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/perform.sgml -->
 
- <chapter id="performance-tips">
+ <chapter id="performance-tips" xreflabel="Peformance Tips">
   <title>Performance Tips</title>
 
   <indexterm zone="performance-tips">
diff --git a/doc/src/sgml/plperl.sgml b/doc/src/sgml/plperl.sgml
index 9117769..6f37b82 100644
--- a/doc/src/sgml/plperl.sgml
+++ b/doc/src/sgml/plperl.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/plperl.sgml -->
 
- <chapter id="plperl">
+ <chapter id="plperl" xreflabel="PL/Perl">
   <title>PL/Perl - Perl Procedural Language</title>
 
   <indexterm zone="plperl">
diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml
index 69a0885..9837a42 100644
--- a/doc/src/sgml/plpgsql.sgml
+++ b/doc/src/sgml/plpgsql.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/plpgsql.sgml -->
 
-<chapter id="plpgsql">
+<chapter id="plpgsql" xreflabel="PL/PgSQL">
   <title><application>PL/pgSQL</application> - <acronym>SQL</acronym> Procedural Language</title>
 
  <indexterm zone="plpgsql">
diff --git a/doc/src/sgml/plpython.sgml b/doc/src/sgml/plpython.sgml
index c838c7b..50f6d51 100644
--- a/doc/src/sgml/plpython.sgml
+++ b/doc/src/sgml/plpython.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/plpython.sgml -->
 
-<chapter id="plpython">
+<chapter id="plpython" xreflabel="PL/Python">
  <title>PL/Python - Python Procedural Language</title>
 
  <indexterm zone="plpython"><primary>PL/Python</></>
diff --git a/doc/src/sgml/pltcl.sgml b/doc/src/sgml/pltcl.sgml
index d2175d5..94e96d8 100644
--- a/doc/src/sgml/pltcl.sgml
+++ b/doc/src/sgml/pltcl.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/pltcl.sgml -->
 
- <chapter id="pltcl">
+ <chapter id="pltcl" xreflabel="PL/TCL">
   <title>PL/Tcl - Tcl Procedural Language</title>
 
   <indexterm zone="pltcl">
diff --git a/doc/src/sgml/rangetypes.sgml b/doc/src/sgml/rangetypes.sgml
index d112561..d7e613a 100644
--- a/doc/src/sgml/rangetypes.sgml
+++ b/doc/src/sgml/rangetypes.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/rangetypes.sgml -->
 
-<sect1 id="rangetypes">
+<sect1 id="rangetypes" xreflabel="Range Types">
  <title>Range Types</title>
 
  <indexterm>
diff --git a/doc/src/sgml/recovery-config.sgml b/doc/src/sgml/recovery-config.sgml
index 0c64ff2..7c99c2d 100644
--- a/doc/src/sgml/recovery-config.sgml
+++ b/doc/src/sgml/recovery-config.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/recovery-config.sgml -->
 
-<chapter id="recovery-config">
+<chapter id="recovery-config" xreflabel="Recovery Configuration">
   <title>Recovery Configuration</title>
 
   <indexterm>
diff --git a/doc/src/sgml/reference.sgml b/doc/src/sgml/reference.sgml
index 10c9a6d..389dbcd 100644
--- a/doc/src/sgml/reference.sgml
+++ b/doc/src/sgml/reference.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/reference.sgml -->
 
-<part id="reference">
+<part id="reference" xreflabel="Reference">
  <title>Reference</title>
 
  <partintro>
diff --git a/doc/src/sgml/regress.sgml b/doc/src/sgml/regress.sgml
index 504d8da..a7b0f41 100644
--- a/doc/src/sgml/regress.sgml
+++ b/doc/src/sgml/regress.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/regress.sgml -->
 
- <chapter id="regress">
+ <chapter id="regress" xreflabel="Regression Tests">
   <title>Regression Tests</title>
 
   <indexterm zone="regress">
diff --git a/doc/src/sgml/release.sgml b/doc/src/sgml/release.sgml
index 8385220..8423209 100644
--- a/doc/src/sgml/release.sgml
+++ b/doc/src/sgml/release.sgml
@@ -38,7 +38,7 @@ For new features, add links to the documentation sections.
 
 -->
 
-<appendix id="release">
+<appendix id="release" xreflabel="Release Notes">
  <title>Release Notes</title>
 
   <para>
diff --git a/doc/src/sgml/rowtypes.sgml b/doc/src/sgml/rowtypes.sgml
index 605dc71..cad88a5 100644
--- a/doc/src/sgml/rowtypes.sgml
+++ b/doc/src/sgml/rowtypes.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/rowtypes.sgml -->
 
-<sect1 id="rowtypes">
+<sect1 id="rowtypes" xreflabel="Composite Types">
  <title>Composite Types</title>
 
  <indexterm>
diff --git a/doc/src/sgml/rules.sgml b/doc/src/sgml/rules.sgml
index 973db74..2ac30e9 100644
--- a/doc/src/sgml/rules.sgml
+++ b/doc/src/sgml/rules.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/rules.sgml -->
 
-<chapter id="rules">
+<chapter id="rules" xreflabel="The Rule System">
 <title>The Rule System</title>
 
  <indexterm zone="rules">
diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml
index 026850a..d90c2ae 100644
--- a/doc/src/sgml/runtime.sgml
+++ b/doc/src/sgml/runtime.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/runtime.sgml -->
 
-<chapter id="runtime">
+<chapter id="runtime" xreflabel="Server Setup and Operation">
  <title>Server Setup and Operation</title>
 
  <para>
diff --git a/doc/src/sgml/spgist.sgml b/doc/src/sgml/spgist.sgml
index 56827e5..424785f 100644
--- a/doc/src/sgml/spgist.sgml
+++ b/doc/src/sgml/spgist.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/spgist.sgml -->
 
-<chapter id="SPGiST">
+<chapter id="SPGiST" xreflabel="SP-GiST indexes">
 <title>SP-GiST Indexes</title>
 
    <indexterm>
diff --git a/doc/src/sgml/spi.sgml b/doc/src/sgml/spi.sgml
index c099fcf..cb85086 100644
--- a/doc/src/sgml/spi.sgml
+++ b/doc/src/sgml/spi.sgml
@@ -1,7 +1,7 @@
 <!-- doc/src/sgml/spi.sgml -->
 
-<chapter id="spi">
- <title>Server Programming Interface</title>
+<chapter id="spi" xreflabel="Server Programming Interface (SPI)">
+ <title>Server Programming Interface (<acronym>SPI</acronym>)</title>
 
  <indexterm zone="spi">
   <primary>SPI</primary>
diff --git a/doc/src/sgml/sql.sgml b/doc/src/sgml/sql.sgml
index 57396d7..88534e8 100644
--- a/doc/src/sgml/sql.sgml
+++ b/doc/src/sgml/sql.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/sql.sgml -->
 
- <chapter id="sql-intro">
+ <chapter id="sql-intro" xreflabel="SQL">
   <title>SQL</title>
 
   <abstract>
diff --git a/doc/src/sgml/storage.sgml b/doc/src/sgml/storage.sgml
index cb76b98..614798e 100644
--- a/doc/src/sgml/storage.sgml
+++ b/doc/src/sgml/storage.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/storage.sgml -->
 
-<chapter id="storage">
+<chapter id="storage" xreflabel="Database Physical Storage">
 
 <title>Database Physical Storage</title>
 
diff --git a/doc/src/sgml/syntax.sgml b/doc/src/sgml/syntax.sgml
index 4b81b08..4d1f075 100644
--- a/doc/src/sgml/syntax.sgml
+++ b/doc/src/sgml/syntax.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/syntax.sgml -->
 
-<chapter id="sql-syntax">
+<chapter id="sql-syntax" xreflabel="SQL Syntax">
  <title>SQL Syntax</title>
 
  <indexterm zone="sql-syntax">
diff --git a/doc/src/sgml/textsearch.sgml b/doc/src/sgml/textsearch.sgml
index 0bc7e7b..5beb7fa 100644
--- a/doc/src/sgml/textsearch.sgml
+++ b/doc/src/sgml/textsearch.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/textsearch.sgml -->
 
-<chapter id="textsearch">
+<chapter id="textsearch" xreflabel="Full Text Search">
  <title>Full Text Search</title>
 
   <indexterm zone="textsearch">
diff --git a/doc/src/sgml/trigger.sgml b/doc/src/sgml/trigger.sgml
index f94aea1..685bce0 100644
--- a/doc/src/sgml/trigger.sgml
+++ b/doc/src/sgml/trigger.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/trigger.sgml -->
 
- <chapter id="triggers">
+ <chapter id="triggers" xreflabel="Triggers">
   <title>Triggers</title>
 
   <indexterm zone="triggers">
diff --git a/doc/src/sgml/typeconv.sgml b/doc/src/sgml/typeconv.sgml
index ed37772..5381a39 100644
--- a/doc/src/sgml/typeconv.sgml
+++ b/doc/src/sgml/typeconv.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/typeconv.sgml -->
 
-<chapter id="typeconv">
+<chapter id="typeconv" xreflabel="Type Conversion">
 <title>Type Conversion</title>
 
 <indexterm zone="typeconv">
diff --git a/doc/src/sgml/user-manag.sgml b/doc/src/sgml/user-manag.sgml
index 177ac7a..eb1a887 100644
--- a/doc/src/sgml/user-manag.sgml
+++ b/doc/src/sgml/user-manag.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/user-manag.sgml -->
 
-<chapter id="user-manag">
+<chapter id="user-manag" xreflabel="Database Roles">
  <title>Database Roles</title>
 
  <para>
diff --git a/doc/src/sgml/wal.sgml b/doc/src/sgml/wal.sgml
index 1254c03..0f237cc 100644
--- a/doc/src/sgml/wal.sgml
+++ b/doc/src/sgml/wal.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/wal.sgml -->
 
-<chapter id="wal">
+<chapter id="wal" xreflabel="Reliability and the Write-Ahead Log">
  <title>Reliability and the Write-Ahead Log</title>
 
  <para>
diff --git a/doc/src/sgml/xaggr.sgml b/doc/src/sgml/xaggr.sgml
index ef7cff4..7709764 100644
--- a/doc/src/sgml/xaggr.sgml
+++ b/doc/src/sgml/xaggr.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/xaggr.sgml -->
 
- <sect1 id="xaggr">
+ <sect1 id="xaggr" xreflabel="User-defined Aggregates">
   <title>User-defined Aggregates</title>
 
   <indexterm zone="xaggr">
diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml
index f40504c..6eada92 100644
--- a/doc/src/sgml/xfunc.sgml
+++ b/doc/src/sgml/xfunc.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/xfunc.sgml -->
 
- <sect1 id="xfunc">
+ <sect1 id="xfunc" xreflabel="user-defined functions">
   <title>User-defined Functions</title>
 
   <indexterm zone="xfunc">
@@ -3304,7 +3304,7 @@ CREATE FUNCTION make_array(anyelement) RETURNS anyarray
     </para>
    </sect2>
 
-   <sect2>
+   <sect2 id="xfunc-shmem-lwlocks" xreflabel="shared memory and LWLocks in user-defined C functions">
     <title>Shared Memory and LWLocks</title>
 
     <para>
@@ -3350,7 +3350,7 @@ if (!ptr)
     </para>
    </sect2>
 
-   <sect2 id="extend-Cpp">
+   <sect2 id="extend-Cpp" xreflabel="using C++ for extensibility">
     <title>Using C++ for Extensibility</title>
 
     <indexterm zone="extend-Cpp">
diff --git a/doc/src/sgml/xoper.sgml b/doc/src/sgml/xoper.sgml
index 8568e21..c6fcbd8 100644
--- a/doc/src/sgml/xoper.sgml
+++ b/doc/src/sgml/xoper.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/xoper.sgml -->
 
- <sect1 id="xoper">
+ <sect1 id="xoper" xreflabel="User-defined Operators">
   <title>User-defined Operators</title>
 
   <indexterm zone="xoper">
diff --git a/doc/src/sgml/xplang.sgml b/doc/src/sgml/xplang.sgml
index 68220bf..55ba40a 100644
--- a/doc/src/sgml/xplang.sgml
+++ b/doc/src/sgml/xplang.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/xplang.sgml -->
 
- <chapter id="xplang">
+ <chapter id="xplang" xreflabel="Procedural Languages">
   <title>Procedural Languages</title>
 
   <indexterm zone="xplang">
diff --git a/doc/src/sgml/xtypes.sgml b/doc/src/sgml/xtypes.sgml
index e1340ba..44340ab 100644
--- a/doc/src/sgml/xtypes.sgml
+++ b/doc/src/sgml/xtypes.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/xtypes.sgml -->
 
- <sect1 id="xtypes">
+ <sect1 id="xtypes" xreflabel="User-defined Types">
   <title>User-defined Types</title>
 
   <indexterm zone="xtypes">
-- 
2.1.0

From 6e2103b211aee44780c6106e307ea4a561d11fde Mon Sep 17 00:00:00 2001
From: Craig Ringer <cr...@2ndquadrant.com>
Date: Mon, 16 Feb 2015 18:17:59 +1300
Subject: [PATCH 2/4] Document how to build with the website style

---
 doc/src/sgml/docguide.sgml | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/doc/src/sgml/docguide.sgml b/doc/src/sgml/docguide.sgml
index e0ae262..6f896b5 100644
--- a/doc/src/sgml/docguide.sgml
+++ b/doc/src/sgml/docguide.sgml
@@ -584,6 +584,15 @@ checking for osx... osx
    </para>
 
    <para>
+    To produce HTML documentation with the stylesheet used on <ulink
+    url="http://postgresql.org/docs/current";>postgresql.org</> instead of the
+    default simple style use:
+<screen>
+<prompt>doc/src/sgml$ </prompt><userinput>make STYLE=website html</userinput>
+</screen>
+   </para>
+
+   <para>
     To create a proper index, the build might process several identical
     stages.  If you do not care about the index, and just want to
     proof-read the output, use <literal>draft</>:
-- 
2.1.0

From fc93f92fbd1a72534c671ea3f76d4f7ec9ddeaa5 Mon Sep 17 00:00:00 2001
From: Craig Ringer <cr...@2ndquadrant.com>
Date: Mon, 16 Feb 2015 18:37:02 +1300
Subject: [PATCH 3/4] Add some index terms in function docs

---
 doc/src/sgml/xfunc.sgml | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml
index 6eada92..6437ab1 100644
--- a/doc/src/sgml/xfunc.sgml
+++ b/doc/src/sgml/xfunc.sgml
@@ -3307,6 +3307,15 @@ CREATE FUNCTION make_array(anyelement) RETURNS anyarray
    <sect2 id="xfunc-shmem-lwlocks" xreflabel="shared memory and LWLocks in user-defined C functions">
     <title>Shared Memory and LWLocks</title>
 
+    <indexterm zone="xfunc-shmem-lwlocks">
+     <primary>Shared memory in extensions</primary>
+    </indexterm>
+
+    <indexterm zone="xfunc-shmem-lwlocks">
+     <primary>LWLocks (extensions)</primary>
+     <secondary>Lightweight locks (extensions)</secondary>
+    </indexterm>
+
     <para>
      Add-ins can reserve LWLocks and an allocation of shared memory on server
      startup.  The add-in's shared library must be preloaded by specifying
-- 
2.1.0

From 04e1cbe49268e22886e2b30fe412fef0cb9dcc65 Mon Sep 17 00:00:00 2001
From: Craig Ringer <cr...@2ndquadrant.com>
Date: Mon, 16 Feb 2015 18:37:19 +1300
Subject: [PATCH 4/4] Document SPI use from bgworkers in greater detail

---
 doc/src/sgml/bgworker.sgml           | 164 +++++++++++++++++++++++++++--------
 doc/src/sgml/contrib.sgml            |   1 +
 doc/src/sgml/example-worker-spi.sgml |  26 ++++++
 doc/src/sgml/filelist.sgml           |   1 +
 doc/src/sgml/spi.sgml                | 151 +++++++++++++++++++++++++++++++-
 doc/src/sgml/xfunc.sgml              |  54 ++++++++++++
 6 files changed, 357 insertions(+), 40 deletions(-)
 create mode 100644 doc/src/sgml/example-worker-spi.sgml

diff --git a/doc/src/sgml/bgworker.sgml b/doc/src/sgml/bgworker.sgml
index ef28f72..d0e7dc0 100644
--- a/doc/src/sgml/bgworker.sgml
+++ b/doc/src/sgml/bgworker.sgml
@@ -34,18 +34,21 @@
   <productname>PostgreSQL</> is started by including the module name in
   <varname>shared_preload_libraries</>.  A module wishing to run a background
   worker can register it by calling
+  <indexterm><primary>RegisterBackgroundWorker</primary></indexterm>
   <function>RegisterBackgroundWorker(<type>BackgroundWorker *worker</type>)</function>
   from its <function>_PG_init()</>.  Background workers can also be started
   after the system is up and running by calling the function
+  <indexterm><primary>RegisterDynamicBackgroundWorker</primary></indexterm>
   <function>RegisterDynamicBackgroundWorker(<type>BackgroundWorker
   *worker, BackgroundWorkerHandle **handle</type>)</function>.  Unlike
   <function>RegisterBackgroundWorker</>, which can only be called from within
   the postmaster, <function>RegisterDynamicBackgroundWorker</function> must be
-  called from a regular backend.
+  called from a regular backend (which might be another background worker).
  </para>
 
  <para>
-  The structure <structname>BackgroundWorker</structname> is defined thus:
+  The structure <indexterm><primary>BackgroundWorker</primary></indexterm>
+  <structname>BackgroundWorker</structname> is defined thus:
 <programlisting>
 typedef void (*bgworker_main_type)(Datum main_arg);
 typedef struct BackgroundWorker
@@ -64,22 +67,46 @@ typedef struct BackgroundWorker
   </para>
 
   <para>
-   <structfield>bgw_name</> is a string to be used in log messages, process
+   <indexterm><primary>bgw_name</></><structfield>bgw_name</> is a string to be used in log messages, process
    listings and similar contexts.
   </para>
 
   <para>
    <structfield>bgw_flags</> is a bitwise-or'd bit mask indicating the
-   capabilities that the module wants.  Possible values are
-   <literal>BGWORKER_SHMEM_ACCESS</literal> (requesting shared memory access)
-   and <literal>BGWORKER_BACKEND_DATABASE_CONNECTION</literal> (requesting the
-   ability to establish a database connection, through which it can later run
-   transactions and queries). A background worker using
-   <literal>BGWORKER_BACKEND_DATABASE_CONNECTION</literal> to connect to
-   a database must also attach shared memory using
-   <literal>BGWORKER_SHMEM_ACCESS</literal>, or worker start-up will fail.
+   capabilities that the module wants.  Possible values are:
+   <variablelist>
+
+    <varlistentry>
+     <term><literal>BGWORKER_SHMEM_ACCESS</literal></term>
+     <listitem>
+      <para>
+       <indexterm><primary>BGWORKER_SHMEM_ACCESS</primary></indexterm>
+       Requests shared memory access. This flag is also required to use
+       lightweight locks (LWlocks). For more information on shared memory access
+       from bgworkers and extensions see <xref linkend="xfunc-shmem-lwlocks">.
+      </para>
+     </listitem>
+    </varlistentry>
+
+    <varlistentry>
+     <term><literal>BGWORKER_BACKEND_DATABASE_CONNECTION</literal></term>
+     <listitem>
+      <para>
+       <indexterm><primary>BGWORKER_BACKEND_DATABASE_CONNECTION</primary></indexterm>
+       Requests the ability to establish a database connection through which it
+       can later run transactions and queries.  A background worker using
+       <literal>BGWORKER_BACKEND_DATABASE_CONNECTION</literal> to connect to a
+       database must also attach shared memory using
+       <literal>BGWORKER_SHMEM_ACCESS</literal>, or worker start-up will fail.
+      </para>
+     </listitem>
+    </varlistentry>
+
+   </variablelist>
+
   </para>
 
+
   <para>
    <structfield>bgw_start_time</structfield> is the server state during which
    <command>postgres</> should start the process; it can be one of
@@ -105,58 +132,113 @@ typedef struct BackgroundWorker
   </para>
 
   <para>
-   <structfield>bgw_main</structfield> is a pointer to the function to run when
-   the process is started.  This function must take a single argument of type
-   <type>Datum</> and return <type>void</>.
-   <structfield>bgw_main_arg</structfield> will be passed to it as its only
-   argument.  Note that the global variable <literal>MyBgworkerEntry</literal>
-   points to a copy of the <structname>BackgroundWorker</structname> structure
-   passed at registration time. <structfield>bgw_main</structfield> may be
-   NULL; in that case, <structfield>bgw_library_name</structfield> and
-   <structfield>bgw_function_name</structfield> will be used to determine
-   the entry point.  This is useful for background workers launched after
-   postmaster startup, where the postmaster does not have the requisite
-   library loaded.
+   <structfield>bgw_main</structfield> specifies the function to run when the
+   background worker is started. If non-NULL,
+   <structfield>bgw_main</structfield> will take precedence over
+   <structfield>bgw_library_name</structfield> and
+   <structfield>bgw_function_name</structfield>.
+   <warning>
+    <para>
+     Use of this field is deprecated. It should be set to
+     <literal>NULL</literal> then <structfield>bgw_library_name</structfield>
+     and <structfield>bgw_function_name</structfield> should be used instead.
+    </para>
+    <para>
+     Specifying the background worker entry point using a function pointer will
+     not work correctly on Windows (or with <literal>EXEC_BACKEND</literal>
+     defined). It may also malfunction when used to point to a function in a
+     dynamically loaded shared library used by a dynamic background worker.
+    </para>
+   </warning>
   </para>
 
   <para>
    <structfield>bgw_library_name</structfield> is the name of a library in
    which the initial entry point for the background worker should be sought.
-   It is ignored unless <structfield>bgw_main</structfield> is NULL.
-   But if <structfield>bgw_main</structfield> is NULL, then the named library
-   will be dynamically loaded by the worker process and
-   <structfield>bgw_function_name</structfield> will be used to identify
-   the function to be called.
+   The named library will be dynamically loaded by the worker process and
+   <structfield>bgw_function_name</structfield> will be used to identify the
+   function to be called.  <structfield>bgw_library_name</structfield> is
+   ignored if <structfield>bgw_main</structfield> is non-NULL.
   </para>
 
   <para>
    <structfield>bgw_function_name</structfield> is the name of a function in
    a dynamically loaded library which should be used as the initial entry point
-   for a new background worker.  It is ignored unless
+   for a new background worker.
+
+   This function must take a single argument of type <type>Datum</> and return
+   <type>void</>.  <structfield>bgw_main_arg</structfield> will be passed to it
+   as its only argument. It signature is:
+
+   <programlisting>
+   /* Declaration */
+   PGDLLEXPORT extern void bgw_main_func_name(Datum main_arg);
+
+   /* Definition */
+   void bgw_main_func_name(Datum main_arg)
+   {
+     /* ... */
+   }
+   </programlisting>
+
+   Note that the global variable <literal>MyBgworkerEntry</literal>
+   points to a copy of the <structname>BackgroundWorker</structname> structure
+   passed at registration time. <structfield>bgw_main</structfield> should be
+   NULL; in that case, <structfield>bgw_library_name</structfield> and
+   <structfield>bgw_function_name</structfield> will be used to determine
+   the entry point.
+
+   <structfield>bgw_function_name</structfield> is ignored unless
    <structfield>bgw_main</structfield> is NULL.
   </para>
 
   <para>
+   <structfield>bgw_main_arg</structfield> is the <type>Datum</> argument
+   to the background worker main function. It should be set and fetched with
+   the Datum accessors, e.g. for an integer you should use
+   <function>Int32GetDatum</function> to set it and
+   <function>DatumGetInt32</function> to read it.
+   <warning>
+    <para>
+     On Windows (and anywhere else where <literal>EXEC_BACKEND</literal> is
+     defined) or in dynamic background workers it is not safe to pass a
+     <type>Datum</> by reference, only by value. If an argument is required is
+     safest to pass an int32 or other small value and use that as an index into
+     an array allocated in shared memory. If a value like a <type>cstring</> or
+     <type>text</type> is passed then the pointer won't be valid from the
+     postmaster and/or the new background worker process, leading to
+     crashes or undefined behavour.</para>
+   </warning>
+  </para>
+
+  <para>
    <structfield>bgw_notify_pid</structfield> is the PID of a PostgreSQL
    backend process to which the postmaster should send <literal>SIGUSR1</>
-   when the process is started or exits.  It should be 0 for workers registered
-   at postmaster startup time, or when the backend registering the worker does
+   when the process is started or exits, causing the notified process's latch
+   to be set.  It should be 0 for workers registered
+   at postmaster startup time, when the backend registering the worker does
    not wish to wait for the worker to start up.  Otherwise, it should be
    initialized to <literal>MyProcPid</>.
   </para>
 
   <para>Once running, the process can connect to a database by calling
+   <indexterm><primary>BackgroundWorkerInitializeConnection</primary></indexterm>
    <function>BackgroundWorkerInitializeConnection(<parameter>char *dbname</parameter>, <parameter>char *username</parameter>)</function> or
+   <indexterm><primary>BackgroundWorkerInitializeConnectionByOid</primary></indexterm>
    <function>BackgroundWorkerInitializeConnectionByOid(<parameter>Oid dboid</parameter>, <parameter>Oid useroid</parameter>)</function>.
    This allows the process to run transactions and queries using the
-   <literal>SPI</literal> interface.  If <varname>dbname</> is NULL or
+   <link linkend="spi">the Server Programming Interface (<acronym>SPI</acronym>)</link>. See <xref linkend="spi-bgworker">
+   for details. If <varname>dbname</> is NULL or
    <varname>dboid</> is <literal>InvalidOid</>, the session is not connected
-   to any particular database, but shared catalogs can be accessed.
+   to any particular database, but shared catalogs (tables where
+   <varname>relisshared</varname> is <literal>true</literal> in
+   <varname>pg_class</varname>) can be accessed.
    If <varname>username</> is NULL or <varname>useroid</> is
    <literal>InvalidOid</>, the process will run as the superuser created
    during <command>initdb</>.
    A background worker can only call one of these two functions, and only
-   once.  It is not possible to switch databases.
+   once.  It is not possible to switch databases without exiting and restarting
+   the background worker.
   </para>
 
   <para>
@@ -224,12 +306,22 @@ typedef struct BackgroundWorker
   </para>
 
   <para>
-   The <filename>worker_spi</> contrib module contains a working example,
-   which demonstrates some useful techniques.
+   Use of <link linkend="spi">the <acronym>SPI</acronym></link> to perform queries and access
+   database tables in a database-connected background worker requires explicit
+   management of transactions and snapshots. See <xref linkend="spi-bgworker">.
+   The same requirements apply to low-level access via direct scans.
+  </para>
+
+  <para>
+   The <link linkend="example-worker-spi">worker-spi</link> sample extension
+   contains a working example of a background worker that uses the
+   <acronym>SPI</acronym> and shared memory as well as some other useful
+   techniques.
   </para>
 
   <para>
    The maximum number of registered background workers is limited by
    <xref linkend="guc-max-worker-processes">.
   </para>
+
 </chapter>
diff --git a/doc/src/sgml/contrib.sgml b/doc/src/sgml/contrib.sgml
index a698d0f..4564274 100644
--- a/doc/src/sgml/contrib.sgml
+++ b/doc/src/sgml/contrib.sgml
@@ -136,6 +136,7 @@ CREATE EXTENSION <replaceable>module_name</> FROM unpackaged;
  &seg;
  &sepgsql;
  &contrib-spi;
+ &example-worker-spi;
  &sslinfo;
  &tablefunc;
  &tcn;
diff --git a/doc/src/sgml/example-worker-spi.sgml b/doc/src/sgml/example-worker-spi.sgml
new file mode 100644
index 0000000..63d8f3d
--- /dev/null
+++ b/doc/src/sgml/example-worker-spi.sgml
@@ -0,0 +1,26 @@
+<!-- doc/src/sgml/example-worker-spi.sgml -->
+
+<sect1 id="example-worker-spi" xreflabel="worker-spi">
+ <title>worker-spi example</title>
+
+ <indexterm zone="example-worker-spi">
+  <primary>Background worker with SPI</primary>
+  <secondary>SPI in background worker</secondary>
+ </indexterm>
+
+ <para>
+  The <application>worker-spi</> module provides a complete and working
+  example of a background worker that uses the SPI to query databases and
+  uses shared memory for communication. It is not intended for use except
+  as an example for developers.
+ </para>
+
+ <para>
+  It is located in <filename>src/test/modules/worker_spi</filename>.
+ </para>
+
+ <para>
+  Relevant documentation for this example module is in <xref linkend="bgworker"/>, <xref linkend="spi"/>, <xref linkend="xfunc"/> and <xref linkend="extend"/>.
+ </para>
+
+</sect1>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index f03b72a..7fa1896 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -142,6 +142,7 @@
 <!ENTITY postgres-fdw    SYSTEM "postgres-fdw.sgml">
 <!ENTITY seg             SYSTEM "seg.sgml">
 <!ENTITY contrib-spi     SYSTEM "contrib-spi.sgml">
+<!ENTITY example-worker-spi     SYSTEM "example-worker-spi.sgml">
 <!ENTITY sepgsql         SYSTEM "sepgsql.sgml">
 <!ENTITY sslinfo         SYSTEM "sslinfo.sgml">
 <!ENTITY tablefunc       SYSTEM "tablefunc.sgml">
diff --git a/doc/src/sgml/spi.sgml b/doc/src/sgml/spi.sgml
index cb85086..57914be 100644
--- a/doc/src/sgml/spi.sgml
+++ b/doc/src/sgml/spi.sgml
@@ -10,7 +10,8 @@
  <para>
   The <firstterm>Server Programming Interface</firstterm>
   (<acronym>SPI</acronym>) gives writers of user-defined
-  <acronym>C</acronym> functions the ability to run
+  <acronym>C</acronym> functions and <xref linkend="bgworker"/>
+  the ability to run
   <acronym>SQL</acronym> commands inside their functions.
   <acronym>SPI</acronym> is a set of
   interface functions to simplify access to the parser, planner,
@@ -363,6 +364,7 @@ SPI_execute("INSERT INTO foo SELECT * FROM bar RETURNING *", false, 5);
    or the command counter, and it allows only plain <command>SELECT</>
    commands to appear in the command string.  The commands are executed
    using the snapshot previously established for the surrounding query.
+   Additional steps are required for <xref linkend="spi-bgworker"/>.
    This execution mode is somewhat faster than the read/write mode due
    to eliminating per-command overhead.  It also allows genuinely
    <firstterm>stable</> functions to be built: since successive executions
@@ -822,7 +824,9 @@ int SPI_execute_with_args(const char *<parameter>command</parameter>,
    <varlistentry>
     <term><literal>bool <parameter>read_only</parameter></literal></term>
     <listitem>
-     <para><literal>true</> for read-only execution</para>
+     <para><literal>true</> for read-only execution with no snapshot
+     or command counter management. See <function>SPI_execute</function>
+     for details.</para>
     </listitem>
    </varlistentry>
 
@@ -3361,7 +3365,8 @@ char * SPI_getnspname(Relation <parameter>rel</parameter>)
    <quote>upper executor context</quote>, that is, the memory context
    that was current when <function>SPI_connect</function> was called,
    which is precisely the right context for a value returned from your
-   procedure.
+   procedure. For direct control over the context used for allocation,
+   <function>MemoryContextAlloc</function> may be used.
   </para>
 
   <para>
@@ -4092,6 +4097,143 @@ INSERT INTO a SELECT * FROM a;
   </para>
  </sect1>
 
+ <sect1 id="spi-bgworker" xreflabel="SPI in background workers">
+  <title>Using the SPI from background workers</title>
+
+  <para>
+   Using the SPI from <link linkend="bgworker">background workers</>
+   requires some additional steps that are not required from SPI-using
+   procedures invoked via SQL from normal user backends. When using the SPI
+   from an SQL-callable function it is safe to assume that a transaction is
+   already open, there is already a snapshot, and that PostgreSQL's statistics
+   have been updated. None of these things may be assumed for use of the SPI
+   from a bgworker.
+  </para>
+
+  <para>
+   To safely use the SPI from a bgworker you must ensure that:
+  <itemizedlist>
+   <listitem><para>A transaction is open (in progress)</para></listitem>
+   <listitem><para>The SPI is connected</para></listitem>
+   <listitem><para>There is an active snapshot or <parameter>read_only</parameter> is set to <literal>false</literal> in SPI calls</para></listitem>
+  </itemizedlist>
+   You should also update the statement start and end timestamps for use in
+   <literal>pg_stat_activity</> using <function>pgstat_report_activity</>.
+  </para>
+
+  <para>
+   Attempting to use the SPI without an open transaction or using the SPI
+   in <parameter>read_only</parameter> mode without setting a snapshot will
+   generally <emphasis>not</emphasis> cause obvious failures or, in a
+   <literal>--enable-cassert</literal> build, assertions. Instead it will
+   usually appear to work for simple cases but may produce incorrect
+   results or be unstable. Users of background workers should generally
+   prefix SPI use with
+<programlisting>
+Assert(IsTransactionState());
+</programlisting>
+   if the function does not its self establish a transaction.
+  </para>
+
+  <para>
+   Typical SPI use from a background worker involves setting up a transaction,
+   setting the statement start timestamp, connecting to the SPI, updating
+   pg_stat_activity, establishing a snapshot, running the query/queries,
+   then performing matching cleanup actions. For example:
+  </para>
+
+<programlisting>
+const char * some_sql = "SELECT 1;";
+
+/* setup */
+StartTransactionCommand();
+SetCurrentStatementStartTimestamp();
+SPI_connect();
+PushActiveSnapshot(GetTransactionSnapshot());
+
+pgstat_report_activity(STATE_RUNNING, some_sql);
+
+/* Run queries with SPI, read_only = false ... */
+spi_ret = SPI_execute(some_sql, false);
+if (spi_ret != SPI_OK_TUPLES)
+    elog(ERROR, "SPI error: %d", spi_ret);
+
+/* ... process results, run more queries, etc ... */
+
+/* cleanup */
+SPI_finish();
+PopActiveSnapshot();
+CommitTransactionCommand();
+pgstat_report_activity(STATE_IDLE, NULL);
+</programlisting>
+
+  <para>
+   In more complex cases the function may need to check if a transaction is
+   already open with <function>IsTransactionState()</function> and only perform
+   transaction management if there is no current transaction. If the SPI may
+   already connected by the caller the function should use
+   <function>SPI_push_conditional</function> before <function>SPI_connect</function> and
+   <function>SPI_pop_conditional</function> after <function>SPI_finish</function>. Snapshot
+   state may also be conditionally handled. The resulting procedure will
+   look more like:
+  </para>
+
+<programlisting>
+const char * some_sql = "SELECT 1;";
+bool tx_started = false,
+     snapshot_pushed = false,
+     spi_pushed;
+
+/* setup */
+if (!IsTransactionCommand())
+{
+  StartTransactionCommand();
+  tx_started = true;
+}
+SetCurrentStatementStartTimestamp();
+if (!ActiveSnapshotSet())
+{
+  PushActiveSnapshot(GetTransactionSnapshot());
+  snapshot_pushed = true;
+}
+spi_pushed = SPI_push_conditional();
+SPI_connect();
+
+pgstat_report_activity(STATE_RUNNING, some_sql);
+
+/* Run queries with SPI, read_only = false... */
+spi_ret = SPI_execute(some_sql, false);
+if (spi_ret != SPI_OK_TUPLES)
+    elog(ERROR, "SPI error: %d", spi_ret);
+
+/* ... process results, run more queries, etc ... */
+
+/* cleanup */
+SPI_finish();
+if (snapshot_pushed)
+  PopActiveSnapshot();
+SPI_pop_conditional(spi_pushed);
+if (tx_started)
+  CommitTransactionCommand();
+pgstat_report_activity(STATE_IDLE, NULL);
+</programlisting>
+
+  <para>
+   If <parameter>read_only</parameter> is <literal>true</literal> for the SPI
+   execution functions then the caller should also manage the snapshot using
+   <function>PushActiveSnapshot</function> and
+   <function>PopActiveSnapshot</function>. If only <literal>read_only =
+   false</literal> SPI procedures are used then there is generally no need for
+   SPI users to explicitly manage snapshots.
+  </para>
+
+  <para>
+   See the <xref linkend="example-worker-spi"> module for a more detailed example of
+   SPI use in background workers.
+  </para>
+
+</sect1>
+
  <sect1 id="spi-examples">
   <title>Examples</title>
 
@@ -4103,7 +4245,8 @@ INSERT INTO a SELECT * FROM a;
    that were processed by the command.  You can find more complex
    examples for SPI in the source tree in
    <filename>src/test/regress/regress.c</filename> and in the
-   <xref linkend="contrib-spi"> module.
+   <xref linkend="contrib-spi"> module. For background-worker
+   specific SPI examples see <xref linkend="spi-bgworker"/>.
   </para>
 
 <programlisting>
diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml
index 6437ab1..39e6a15 100644
--- a/doc/src/sgml/xfunc.sgml
+++ b/doc/src/sgml/xfunc.sgml
@@ -3357,6 +3357,60 @@ if (!ptr)
 }
 </programlisting>
     </para>
+
+    <para>
+     Extensions registered to run at startup
+     using <xref linkend="guc-shared-preload-libraries"> should instead install a
+     <literal>shmem_startup_hook</> from <function>_PG_init</>.  This will be
+     invoked once shared memory is ready but before user backends or background
+     workers get launched. The hook function invoked should use a pattern like
+     that shown for shared memory initialization above then call the next hook
+     function, e.g. declare:
+<programlisting>
+static shmem_startup_hook_type prev_shmem_startup_hook = NULL;
+</programlisting>
+     then from <function>_PG_init</>, after any
+     <function>RequestAddinShmemSpace</> and <function>RequestAddinLWLocks</>
+     install the hook:
+<programlisting>
+     prev_shmem_startup_hook = shmem_startup_hook;
+     shmem_startup_hook = my_worker_shmem_startup;
+</programlisting>
+     where <function>my_worker_shmem_startup</function> is a <type>void</> function
+     with <type>void</> arguments that calls the next hook (if any):
+<programlisting>
+     if (prev_shmem_startup_hook != NULL)
+         prev_shmem_startup_hook();
+</programlisting>
+     then calls <function>ShmemInitStruct</> per the example shown above. An
+     example of this usage can be found in the initialisation of the <xref
+     linkend="pgstatstatements"> extension.
+    </para>
+
+     <caution>
+      <title>Shared memory is zeroed on postmaster restart</title>
+      <para>
+       If the postmaster restarts - usually due to the crash of a backend
+       process like a user backend or a background worker - then it zeroes
+       shared memory on restart then re-invokes any shared memory setup hooks
+       that have been installed by extensions. Extensions using shared memory
+       must be prepared for this.
+      </para>
+      <para>
+       Background workers are not unregistered if the postmaster restarts
+       due to the crash of a background worker or user backend. This can lead
+       to background workers accessing shared memory that has been reinitialized.
+       Care must be taken to ensure that initialisation of shared memory produces
+       stable results when re-run or workers must detect the postmaster restart
+       using a generation counter and exit. In particular if parameters are being
+       passed to a bgworker via shared memory the background worker
+       <structfield>bgw_main_arg</structfield> should always be an index into an
+       array allocated in shared memory, rather than a pointer, and repeated
+       initialisations of the shared memory segment must produce the same range
+       of valid indexes in the same order.
+      </para>
+     </caution>
+
    </sect2>
 
    <sect2 id="extend-Cpp" xreflabel="using C++ for extensibility">
-- 
2.1.0

-- 
Sent via pgsql-docs mailing list (pgsql-docs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-docs

Reply via email to