summaryrefslogtreecommitdiffstats
path: root/doc/src/sgml/generic-wal.sgml
diff options
context:
space:
mode:
Diffstat (limited to 'doc/src/sgml/generic-wal.sgml')
-rw-r--r--doc/src/sgml/generic-wal.sgml160
1 files changed, 160 insertions, 0 deletions
diff --git a/doc/src/sgml/generic-wal.sgml b/doc/src/sgml/generic-wal.sgml
new file mode 100644
index 0000000..7a02849
--- /dev/null
+++ b/doc/src/sgml/generic-wal.sgml
@@ -0,0 +1,160 @@
+<!-- doc/src/sgml/generic-wal.sgml -->
+
+<chapter id="generic-wal">
+ <title>Generic WAL Records</title>
+
+ <para>
+ Although all built-in WAL-logged modules have their own types of WAL
+ records, there is also a generic WAL record type, which describes changes
+ to pages in a generic way. This is useful for extensions that provide
+ custom access methods, because they cannot register their own WAL redo
+ routines.
+ </para>
+
+ <para>
+ The API for constructing generic WAL records is defined in
+ <filename>access/generic_xlog.h</filename> and implemented
+ in <filename>access/transam/generic_xlog.c</filename>.
+ </para>
+
+ <para>
+ To perform a WAL-logged data update using the generic WAL record
+ facility, follow these steps:
+
+ <orderedlist>
+ <listitem>
+ <para>
+ <function>state = GenericXLogStart(relation)</function> &mdash; start
+ construction of a generic WAL record for the given relation.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ <function>page = GenericXLogRegisterBuffer(state, buffer, flags)</function>
+ &mdash; register a buffer to be modified within the current generic WAL
+ record. This function returns a pointer to a temporary copy of the
+ buffer's page, where modifications should be made. (Do not modify the
+ buffer's contents directly.) The third argument is a bit mask of flags
+ applicable to the operation. Currently the only such flag is
+ <literal>GENERIC_XLOG_FULL_IMAGE</literal>, which indicates that a full-page
+ image rather than a delta update should be included in the WAL record.
+ Typically this flag would be set if the page is new or has been
+ rewritten completely.
+ <function>GenericXLogRegisterBuffer</function> can be repeated if the
+ WAL-logged action needs to modify multiple pages.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Apply modifications to the page images obtained in the previous step.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ <function>GenericXLogFinish(state)</function> &mdash; apply the changes to
+ the buffers and emit the generic WAL record.
+ </para>
+ </listitem>
+ </orderedlist>
+ </para>
+
+ <para>
+ WAL record construction can be canceled between any of the above steps by
+ calling <function>GenericXLogAbort(state)</function>. This will discard all
+ changes to the page image copies.
+ </para>
+
+ <para>
+ Please note the following points when using the generic WAL record
+ facility:
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ No direct modifications of buffers are allowed! All modifications must
+ be done in copies acquired from <function>GenericXLogRegisterBuffer()</function>.
+ In other words, code that makes generic WAL records should never call
+ <function>BufferGetPage()</function> for itself. However, it remains the
+ caller's responsibility to pin/unpin and lock/unlock the buffers at
+ appropriate times. Exclusive lock must be held on each target buffer
+ from before <function>GenericXLogRegisterBuffer()</function> until after
+ <function>GenericXLogFinish()</function>.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Registrations of buffers (step 2) and modifications of page images
+ (step 3) can be mixed freely, i.e., both steps may be repeated in any
+ sequence. Keep in mind that buffers should be registered in the same
+ order in which locks are to be obtained on them during replay.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ The maximum number of buffers that can be registered for a generic WAL
+ record is <literal>MAX_GENERIC_XLOG_PAGES</literal>. An error will be thrown
+ if this limit is exceeded.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Generic WAL assumes that the pages to be modified have standard
+ layout, and in particular that there is no useful data between
+ <structfield>pd_lower</structfield> and <structfield>pd_upper</structfield>.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Since you are modifying copies of buffer
+ pages, <function>GenericXLogStart()</function> does not start a critical
+ section. Thus, you can safely do memory allocation, error throwing,
+ etc. between <function>GenericXLogStart()</function> and
+ <function>GenericXLogFinish()</function>. The only actual critical section is
+ present inside <function>GenericXLogFinish()</function>. There is no need to
+ worry about calling <function>GenericXLogAbort()</function> during an error
+ exit, either.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ <function>GenericXLogFinish()</function> takes care of marking buffers dirty
+ and setting their LSNs. You do not need to do this explicitly.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ For unlogged relations, everything works the same except that no
+ actual WAL record is emitted. Thus, you typically do not need to do
+ any explicit checks for unlogged relations.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ The generic WAL redo function will acquire exclusive locks to buffers
+ in the same order as they were registered. After redoing all changes,
+ the locks will be released in the same order.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ If <literal>GENERIC_XLOG_FULL_IMAGE</literal> is not specified for a
+ registered buffer, the generic WAL record contains a delta between
+ the old and the new page images. This delta is based on byte-by-byte
+ comparison. This is not very compact for the case of moving data
+ within a page, and might be improved in the future.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+</chapter>