<!doctype book PUBLIC "-//Davenport//DTD DocBook V3.0//EN" [
]>

<book id="pilot-link-sync-abs-conduit">
  <bookinfo>
    <title>Pilot Link Sync Abs Conduits</title>
    <date>2000 October</date>
    <releaseinfo>First draft.  Based on gnome-pilot documentation</releaseinfo>
    <authorgroup>
      <author>
	<firstname>JP</firstname>
	<surname>Rosevear</surname>
      </author>
    </authorgroup>
    <address><email>jpr@helixcode.com</email></address>
  </bookinfo>

  <preface>
    <title>Pilot Link Sync AbsConduits</title>
    <para>This document describes the conduit interface for the pilot-link sync abs conduit.</para>
  </preface>

  <chapter>
   <title>Introduction to the Sync Abs Conduit</title>

   <sect1>
     <title>What is the sync abs conduit?</title>
 
     <para>The sync abs conduit is designed to free the implementor
     from having to code the descision logic of the synchronization
     of a palm pilot database.  This is accomplished by having the 
     implementor define a series action based callbacks that are called
     when appropriate by the sync abs code in pilot-link.</para>
   </sect1>
  </chapter>

  <chapter>
    <title>Sync Abs conduit implementation</title>

    <sect1>
      <title>PilotRecords and DesktopRecords</title>
      <para>There are two data structures that represent records during
      the synchronization process, the <type>PilotRecord</type> and
      <type>DesktopRecord</type>.  The <type>PilotRecord</type>, as the
      name implies, represents records on the pilot device, while the
      <type>DesktopRecord</type> represents records stored in or by a
      desktop application.</para>

      <para>A <type>PilotRecord</type> contains the pilot record id,
      the record category id, dlp status flags (modified, dirty, etc),
      the raw byte data of the actual record and the length of said
      raw data.  If the record is of one the standard types, for example
      a datebook entry, the pilot-link unpack methods can be called to 
      interpret the data.  If the record is not one of the standard types,
      the conduit will need to interpret the data itself.</para>

      <para>A <type>DesktopRecord</type> contains the pilot record id
      (if known), the record category id and the dlp status flags 
      (modified, dirty, etc).  To ease implementation and speed operation, 
      a <type>DesktopRecord</type> can be extended by declaring a DesktopRecord to be the
      first member of another struct and returning a pointer to that other
      struct when asked to return references to a <type>DesktopRecord</type>.
      This is possible because all <type>DesktopRecords</type> are created and
      destroyed exclusively via the callbacks and thus the implementor can
      add arbitrary data to such a record.</para>
    </sect1>

    <sect1>
      <title>SyncHandler and its callbacks</title>

      <para>A <type>SyncHandler</type> structure contains several standard
        data fields as well as a series of fifteen function pointers which 
        are the callbacks which need to be implemented.</para>
      
      <para>The standard data fields include the socket descripter (sd) for
        this particular conduit.  Please note that a socket to the pilot is not
        opened by the sync abs conduit.  The name field should contain the name of
        the database to be synchronized and data field is for the implementor to store
        any useful and is not used by the sync abs conduit itself.</para>

      <sect2 id="callbacks">
	<title>Callbacks</title>

	<para>This a a walkthrough of sync abs conduit's
	  fourteen callbacks. Their purpose, importance, usage by the various
	  types of synchronization processes (Fast/Slow sync, copy to/from
	  remote) and how they should behave.</para>

	<para>These use normal UNIX api return values, meaning 0 on
	  success, negative values on failure. There is one exception, the
          compare method which returns 0 if two records are the same and 1 if
          they are not. However, in this case an error is still represented 
          by a negative return value.</para>

	  <orderedlist> 
	    <listitem>
	      <funcsynopsis>
		<funcprototype>
		  <funcdef>int <function>(*PreSync)</function></funcdef>
		  <paramdef>SyncHandler *<parameter>sh</parameter></paramdef>
		  <paramdef>int <parameter>dbhandle</parameter></paramdef>
		  <paramdef>int *<parameter>slow</parameter></paramdef>
		</funcprototype>
	      </funcsynopsis>
	      <variablelist>
		<varlistentry>
		<term>Description</term>
		  <listitem>
		    <para>This function is called before the
		    synchronization process begins. In the
		    implementation, the conduit should handle
		    necesseary initialisation, eg. getting the
		    <type>AppInfo</type> for the database that the
		    conduit is synchronizing.</para>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Parameters</term>
		  <listitem>
		    <variablelist>
		      <varlistentry
			<term><parameter>sh</parameter></term>
			<listitem>
			  <para>pointer to the <type>SyncHandler</type>
                          controlling this synchronization</para>
			</listitem>
		      </varlistentry>
		      <varlistentry>
			<term><parameter>dbhandle</parameter></term>
			<listitem>
			<para>the dbhandle, as opened by the pilot-link library.</para>
			</listitem>
		      </varlistentry>
		      <varlistentry>
			<term><parameter>slow</parameter></term>
			<listitem>
			  <para>An <type>int</type>* pointing that should
                          be set to 1 for a slow sync and 0 for a 
                          fast sync.</para>
			</listitem>
		      </varlistentry>
		    </variablelist>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Returns</term>
		  <listitem>
		    <para>0 on success, a negative value for
		    failure. And on success, sets *<parameter>slow</parameter>
                    to the appropriate value.</para>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Needed by</term>
		  <listitem>
		    <para>All</para>
		  </listitem>
		</varlistentry>
	      </variablelist>
	    </listitem>

	    <listitem>
	      <funcsynopsis>
		<funcprototype>
		  <funcdef>int <function>(*PostSync)</function></funcdef>
		  <paramdef>SyncHandler *<parameter>sh</parameter></paramdef>
		  <paramdef>int <parameter>dbhandle</parameter></paramdef>
		</funcprototype>
	      </funcsynopsis>
	      <variablelist>
		<varlistentry>
		<term>Description</term>
		  <listitem>
		    <para>This function is called just
		    after the synchronization process ends. In the
		    implementation, the conduit should handle
		    necessary cleanup, eg. doing actual record
                    deletion if it is not done immediately or logging the
                    operation.</para>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Parameters</term>
		  <listitem>
		    <variablelist>
		      <varlistentry
			<term><parameter>sh</parameter></term>
			<listitem>
			  <para>pointer to the <type>SyncHandler</type>
                          controlling this synchronization</para>
			</listitem>
		      </varlistentry>
		      <varlistentry>
			<term><parameter>dbhandle</parameter></term>
			<listitem>
			<para>the dbhandle, as opened by the pilot-link library.</para>
			</listitem>
		      </varlistentry>
		    </variablelist>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Needed by</term>
		  <listitem>
		    <para>All</para>
		  </listitem>
		</varlistentry>
	      </variablelist>
	    </listitem>

	    <listitem>
	      <funcsynopsis>
		<funcprototype>
		  <funcdef>int <function>(*SetPilotID)</function></funcdef>
		  <paramdef>SyncHandler *<parameter>sh</parameter></paramdef>
		  <paramdef>DesktopRecord *<parameter>dr</parameter></paramdef>
		  <paramdef>guint32 <parameter>ID</parameter></paramdef>
		</funcprototype>
	      </funcsynopsis>
	      <variablelist>
		<varlistentry>
		  <term>Description</term>
		  <listitem>
		    <para>Associates a desktop record with a pilot
		    record. This is usually called during synchronization,
		    when a new record is added to the pilot, which assigns an id
		    to the record. This id is then passed on to the
		    conduit via this call.</para> <para>This id is
		    also used when iterating over records, where a
		    modification to a local record requires a lookup
		    in the pilot. This lookup is done using this Id,
		    so it is important to save it in the local
		    database.</para>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Parameters</term>
		  <listitem>
		    <variablelist>
		      <varlistentry
			<term><parameter>sh</parameter></term>
			<listitem>
			  <para>pointer to the <type>SyncHandler</type>
                          controlling this synchronization</para>
			</listitem>
		      </varlistentry>
		      <varlistentry>
			<term><parameter>local</parameter></term>
			<listitem>
			  <para>A <type>DesktopRecord</type>* pointing to
			the record to which the id was
			assigned. </para>
			</listitem>
		      </varlistentry>
		      <varlistentry>
			<term><parameter>ID</parameter></term>
			<listitem>
			  <para>A <type>guint32</type> integer
			containg the id.</para>
			</listitem>
		      </varlistentry>
		    </variablelist>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Returns</term>
		  <listitem>
		    <para>0 on success, negative value on error</para>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Needed by</term>
		  <listitem>
		    <para>Fast sync, Slow sync, Merge to pilot, Copy to pilot</para>
		  </listitem>
		</varlistentry>
	      </variablelist>
	    </listitem>

	    <listitem>
	      <funcsynopsis>
		<funcprototype>
		  <funcdef>int <function>(*SetStatusCleared)</function></funcdef>
		  <paramdef>SyncHandler *<parameter>sh</parameter></paramdef>
		  <paramdef>DesktopRecord *<parameter>dr</parameter></paramdef>
		</funcprototype>
	      </funcsynopsis>
	      <variablelist>
		<varlistentry>
		  <term>Description</term>
		  <listitem>
		    <para>Indicates that the status of the record (usually that
                    it has been changed in some way) should be cleared - usually
                    this is done when the record has been synchronized while iterating
                    over the pilot records.</para>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Parameters</term>
		  <listitem>
		    <variablelist>
		      <varlistentry
			<term><parameter>sh</parameter></term>
			<listitem>
			  <para>pointer to the <type>SyncHandler</type>
                          controlling this synchronization</para>
			</listitem>
		      </varlistentry>
		      <varlistentry>
			<term><parameter>local</parameter></term>
			<listitem>
			  <para>A <type>DesktopRecord</type>* pointing to
			  the record whose status should be cleared.</para>
			</listitem>
		      </varlistentry>
		    </variablelist>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Returns</term>
		  <listitem>
		    <para>0 on success, negative value on error</para>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Needed by</term>
		  <listitem>
		    <para>Fast sync, Slow sync, Merge to pilot, Copy to pilot</para>
		  </listitem>
		</varlistentry>
	      </variablelist>
	    </listitem>

	    <listitem>
	      <funcsynopsis>
		<funcprototype>
		  <funcdef>int <function>(*ForEach)</function></funcdef>
		  <paramdef>GnomePilotConduitSyncAbs* <parameter>conduit</parameter></paramdef>
		  <paramdef>DesktopRecord** <parameter>dr</parameter></paramdef>
		</funcprototype>
	      </funcsynopsis>
	      <variablelist>
		<varlistentry>
		  <term>Description</term>
		  <listitem>
		    <para>Returns a succesion of records, all records in the 
                    desktop database.</para>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Parameters</term>
		  <listitem>
		    <variablelist>
		      <varlistentry>
			<term><parameter>sh</parameter></term>
			<listitem>
			  <para>pointer to the <type>SyncHandler</type>
                          controlling this synchronization</para>
			</listitem>
		      </varlistentry>
		      <varlistentry>
			<term><parameter>dr</parameter></term>
			<listitem>
			  <para>the iterations "pointer". At first call,
			*<parameter>dr</parameter> is NULL. The
			method should then set
			<parameter>dr</parameter> to point at the
			first desktop record (if any). Upon subsequent
                        calls, point <parameter>dr</parameter> to the next
			desktop record, when you reach the end, set
			<parameter>dr</parameter> to NULL.</para>
			</listitem>
		      </varlistentry>
		    </variablelist>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Returns</term>
		  <listitem>
		    <para>0 on success and *<parameter>dr</parameter> 
                    is set to non NULL or NULL on completion.
                    Returns negative value on error.</para>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Needed by</term>
		  <listitem>
		    <para>FastSync, SlowSync, Copy To Remote</para>
		  </listitem>
		</varlistentry>
	      </variablelist>
	    </listitem>

	    <listitem>
	      <funcsynopsis>
		<funcprototype>
		  <funcdef>int <function>(*ForEachModified)</function></funcdef>
		  <paramdef>SyncHandler *<parameter>sh</parameter></paramdef>
		  <paramdef>DesktopRecord** <parameter>dr</parameter></paramdef>
		</funcprototype>
	      </funcsynopsis>
	      <variablelist>
		<varlistentry>
		  <term>Description</term>
		  <listitem>
		    <para>Iterates over records that have been modified, which
                    in this context refers to a record that has been changed,
                    deleted or marked as modified.</para>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Parameters</term>
		  <listitem>
		    <variablelist>
		      <varlistentry>
			<term><parameter>sh</parameter></term>
			<listitem>
			  <para>pointer to the <type>SyncHandler</type>
                          controlling this synchronization</para>
			</listitem>
		      </varlistentry>
		      <varlistentry>
			<term><parameter>dr</parameter></term>
			<listitem>
			  <para>the iterations "pointer". At first call,
			*<parameter>dr</parameter> is NULL. The
			method should then set
			<parameter>dr</parameter> to point at the
			first desktop record (if any). Upon subsequent
                        calls, point <parameter>dr</parameter> to the next
			desktop record, when you reach the end, set
			<parameter>dr</parameter> to NULL.</para>
			</listitem>
		      </varlistentry>
		    </variablelist>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Returns</term>
		  <listitem>
		    <para>1 on success and
		    *<parameter>local</parameter> is set to non NULL,
		    0 on completion and *<parameter>local</parameter>
		    is set to NULL, negative value on error.</para>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Needed by</term>
		  <listitem>
		    <para>FastSync, SlowSync, Copy To Remote, Copy From Remote</para>
		  </listitem>
		</varlistentry>
	      </variablelist>
	    </listitem>

	    <listitem>
	      <funcsynopsis>
		<funcprototype>
		  <funcdef>int <function>(*Compare)</function></funcdef>
		  <paramdef>SyncHandler *<parameter>sh</parameter></paramdef>
		  <paramdef>PilotRecord* <parameter>pr</parameter></paramdef>
		  <paramdef>DesktopRecord* <parameter>dr</parameter></paramdef>
		</funcprototype>
	      </funcsynopsis>
	      <variablelist>
		<varlistentry>
		  <term>Description</term>
		  <listitem>
		    <para>Compare a desktop record with a pilot record. 
                    If both the desktop and pilot records have been modfied,
                    this is called determine if the changes are identical. The
                    meaning of "identical" is determined by the conduit
                    implementor</para>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Parameters</term>
		  <listitem>
		    <variablelist>
		      <varlistentry>
			<term><parameter>sh</parameter></term>
			<listitem>
			  <para>pointer to the <type>SyncHandler</type>
                          controlling this synchronization</para>
			</listitem>
		      </varlistentry>
		      <varlistentry>
			<term><parameter>pr</parameter></term>
			<listitem>
			  <para>Pointer to the pilot record</para>
			</listitem>
		      </varlistentry>
		      <varlistentry>
			<term><parameter>dr</parameter></term>
			<listitem>
			  <para>Pointer to the desktop record</para>
			</listitem>
		      </varlistentry>
		    </variablelist>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Returns</term>
		  <listitem>
		    <para>0 if identical in whatever way the conduit
		  decides, positive if different, negative if failure.</para>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Needed by</term>
		  <listitem>
		    <para>FastSync, SlowSync.</para>
		  </listitem>
		</varlistentry>
	      </variablelist>
	    </listitem>

	    <listitem>
	      <funcsynopsis>
		<funcprototype>
		  <funcdef>int <function>(*AddRecord)</function></funcdef>
		  <paramdef>SyncHandler *<parameter>sh</parameter></paramdef>
		  <paramdef>PilotRecord* <parameter>pr</parameter></paramdef>
		</funcprototype>
	      </funcsynopsis>
	      <variablelist>
		<varlistentry>
		  <term>Description</term>
		  <listitem>
		    <para>Store the information in a pilot record in on 
                    the desktop.</para>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Parameters</term>
		  <listitem>
		    <variablelist>
		      <varlistentry>
			<term><parameter>sh</parameter></term>
			<listitem>
			  <para>pointer to the <type>SyncHandler</type>
                          controlling this synchronization</para>
			</listitem>
		      </varlistentry>
		      <varlistentry>
			<term><parameter>pr</parameter></term>
			<listitem>
			  <para> pointer to a pilot record whose information
                          is to be stored. The method should copy all the
			  information needed, and either immediately
			  store the record, or queue it for
			  storage.</para>
			</listitem>
		      </varlistentry>
		    </variablelist>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Returns</term>
		  <listitem>
		    <para>0 on success, negative value on error</para>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Needed by</term>
		  <listitem>
		    <para>FastSync, SlowSync, Copy From Remote</para>
		  </listitem>
		</varlistentry>
	      </variablelist>
	    </listitem>

	    <listitem>
	      <funcsynopsis>
		<funcprototype>
		  <funcdef>int <function>(*ReplaceRecord)</function></funcdef>
		  <paramdef>SyncHandler *<parameter>sh</parameter></paramdef>
		  <paramdef>DesktopRecord* <parameter>dr</parameter></paramdef>
		  <paramdef>PilotRecord* <parameter>pr</parameter></paramdef>
		</funcprototype>
	      </funcsynopsis>
	      <variablelist>
		<varlistentry>
		  <term>Description</term>
		  <listitem>
		    <para>Replace the desktop record information with the
                    information in the pilot record</para>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Parameters</term>
		  <listitem>
		    <variablelist>
		      <varlistentry>
			<term><parameter>sh</parameter></term>
			<listitem>
			  <para>pointer to the <type>SyncHandler</type>
                          controlling this synchronization</para>
			</listitem>
		      </varlistentry>
		      <varlistentry>
			<term><parameter>dr</parameter></term>
			<listitem>
			  <para> pointer to a desktop record whose information
                          is to be replaced.</para>
			</listitem>
		      </varlistentry>
		      <varlistentry>
			<term><parameter>pr</parameter></term>
			<listitem>
			  <para> pointer to a pilot record whose information
                          is to be used to replace the desktop record's
                          information. The method should copy all the
			  information needed, and either immediately
			  replace the record, or queue it for
			  replacement.</para>
			</listitem>
		      </varlistentry>
		    </variablelist>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Returns</term>
		  <listitem>
		    <para>0 on success, negative value on error</para>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Needed by</term>
		  <listitem>
		    <para>FastSync, SlowSync, Copy To Remote, Copy From Remote</para>
		  </listitem>
		</varlistentry>
	      </variablelist>
	    </listitem>

	    <listitem>
	      <funcsynopsis>
		<funcprototype>
		  <funcdef>int <function>(*DeleteRecord)</function></funcdef>
		  <paramdef>SyncHandler *<parameter>sh</parameter></paramdef>
		  <paramdef>DesktopRecord* <parameter>dr</parameter></paramdef>
		</funcprototype>
	      </funcsynopsis>
	      <variablelist>
		<varlistentry>
		  <term>Description</term>
		  <listitem>
		    <para>This method takes the
		    <parameter>dr</parameter> record, and removes it
		    from the desktop.</para>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Parameters</term>
		  <listitem>
		    <variablelist>
		      <varlistentry
>			<term><parameter>sh</parameter></term>
			<listitem>
			  <para>pointer to the <type>SyncHandler</type>
                          controlling this synchronization</para>
			</listitem>
		      </varlistentry>
		      <varlistentry>
			<term><parameter>dr</parameter></term>
			<listitem>
			  <para> pointer to a pilot record that should be
                          deleted. </para>
			</listitem>
		      </varlistentry>
		    </variablelist>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Returns</term>
		  <listitem>
		    <para>0 on success, a negative value for failure.</para>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Needed by</term>
		  <listitem>
		    <para>FastSync and SlowSync.</para>
		  </listitem>
		</varlistentry>
	      </variablelist>
	    </listitem>

	    <listitem>
	      <funcsynopsis>
		<funcprototype>
		  <funcdef>int <function>(*ArchiveRecord)</function></funcdef>
		  <paramdef>SyncHandler *<parameter>sh</parameter></paramdef>
		  <paramdef>DesktopRecord *<parameter>dr</parameter></paramdef>
		  <paramdef>int <parameter>archive</parameter></paramdef>
		</funcprototype>
	      </funcsynopsis>
	      <variablelist>
		<varlistentry>
		  <term>Description</term>
		  <listitem>
		    <para>Sets whether or not a record is archived.</para>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Parameters</term>
		  <listitem>
		    <variablelist>
		      <varlistentry>
			<term><parameter>sh</parameter></term>
			<listitem>
			  <para>pointer to the <type>SyncHandler</type>
                          controlling this synchronization</para>
			</listitem>
		      </varlistentry>
		      <varlistentry>
			<term><parameter>dr</parameter></term>
			<listitem>
			  <para>The a pointer to the desktop record 
                          whose "archiveness" is to be set.</para>
			</listitem>
		      </varlistentry>
		      <varlistentry>
			<term><parameter>archive</parameter></term>
			<listitem>
			  <para>0 if the record should be marked as archived,
                          1 otherwise.</para>
			</listitem>
		      </varlistentry>
		    </variablelist>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Returns</term>
		  <listitem>
		    <para>0 on success, negative value on error</para>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Needed by</term>
		  <listitem>
		    <para>FastSync, SlowSync, Copy To Remote, Copy From Remote</para>
		  </listitem>
		</varlistentry>
	      </variablelist>
	    </listitem>

	    <listitem>
	      <funcsynopsis>
		<funcprototype>
		  <funcdef>int <function>(*MatchRecord)</function></funcdef>
		  <paramdef>SyncHandler *<parameter>sh</parameter></paramdef>
		  <paramdef>PilotRecord* <parameter>pr</parameter></paramdef>
		  <paramdef>DesktopRecord** <parameter>dr</parameter></paramdef>
		</funcprototype>
	      </funcsynopsis>
	      <variablelist>
		<varlistentry>
		  <term>Description</term>
		  <listitem>
		    <para>This method takes the
		    <parameter>pr</parameter> record, and locates
		    the desktop record which is supposed to be the same
		    as the pilot record. The contents of the desktop record
                    belong to the conduit and is not tampered with by the 
                    calling method, so you may freely return a pointer to a
		    local static variable.</para> 
		  <para>The memory allocated by 
                   <function>MatchRecord</function> is
		    freed by the caller by a call to
		    <function>FreeMatch</function>.</para>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Parameters</term>
		  <listitem>
		    <variablelist>
		      <varlistentry>
			<term><parameter>sh</parameter></term>
			<listitem>
			  <para>pointer to the <type>SyncHandler</type>
                          controlling this synchronization</para>
			</listitem>
		      </varlistentry>
		      <varlistentry>
			<term><parameter>pr</parameter></term>
			<listitem>
			  <para> pointer to the pilot record to be
                          matched with a desktop record.</para>
			</listitem>
		      </varlistentry>
		      <varlistentry>
			<term><parameter>dr</parameter></term>
			<listitem>
			<para><parameter>dr</parameter> is a pointer to a
		        pointer for storing the record. If no desktop record
		        matching the remote is found, set
		        *<parameter>dr</parameter> to NULL.</para>
			<para>Only one desktop record should match a remote
		        record.</para>
			</listitem>
		      </varlistentry>
		    </variablelist>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Returns</term>
		  <listitem>
		    <para>0 on success, a negative value for
		  failure. And on success, sets
		  *<parameter>local</parameter> to the appropriate
		  record.</para>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Needed by</term>
		  <listitem>
		    <para>FastSync and SlowSync.</para>
		  </listitem>
		</varlistentry>
	      </variablelist>
	    </listitem>

	    <listitem>
	      <funcsynopsis>
		<funcprototype>
		  <funcdef>int <function>(*FreeMatch)</function></funcdef>
		  <paramdef>SyncHandler *<parameter>sh</parameter></paramdef>
		  <paramdef>DesktopRecord** <parameter>dr</parameter></paramdef>
		</funcprototype>
	      </funcsynopsis>
	      <variablelist>
		<varlistentry>
		  <term>Description</term>
		  <listitem>
		    <para>This method is responsible for freeing memory
		    allocated by a <function>MatchRecord</function> call.
                    </para>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Parameters</term>
		  <listitem>
		    <variablelist>
		      <varlistentry>
			<term><parameter>sh</parameter></term>
			<listitem>
			  <para>pointer to the <type>SyncHandler</type>
                          controlling this synchronization</para>
			</listitem>
		      </varlistentry>
		      <varlistentry>
			<term><parameter>dr</parameter></term>
			<listitem>
			  <para> pointer to a record pointer. This
			  record'ss resources should be freed, and
			  *<parameter>dr</parameter> set to
			  NULL.</para>
			</listitem>
		      </varlistentry>
		    </variablelist>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Returns</term>
		  <listitem>
		    <para>0 on success, negative value on error</para>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Needed by</term>
		  <listitem>
		    <para>FastSync, SlowSync, Copy To Remote, Copy From Remote</para>
		  </listitem>
		</varlistentry>
	      </variablelist>
	    </listitem>

	    <listitem>
	      <funcsynopsis>
		<funcprototype>
		  <funcdef>gint  <function>(*Prepare)</function></funcdef>
		  <paramdef>SyncHandler *<parameter>sh</parameter></paramdef>
		  <paramdef>DesktopRecord* <parameter>dr</parameter></paramdef>
		  <paramdef>PilotRecord* <parameter>pr</parameter></paramdef>
		</funcprototype>
	      </funcsynopsis>
	      <variablelist>
		<varlistentry>
		  <term>Description</term>
		  <listitem>
		    <para>From a given desktop record, fill in the given
		    <type>PilotRecord</type> record so it can be stored 
		    on the pilot.</para>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Parameters</term>
		  <listitem>
		    <variablelist>
		      <varlistentry>
			<term><parameter>sh</parameter></term>
			<listitem>
			  <para>pointer to the <type>SyncHandler</type>
                          controlling this synchronization</para>
			</listitem>
		      </varlistentry>
		      <varlistentry>
			<term><parameter>dr</parameter></term>
			<listitem>
			  <para>A non-null 
                          <type>DesktopRecord</type>*,
			  pointing to a desktop record created by a call
                          to <function>ForEach</function> or
                          <function>ForEachModified</function></para>
			</listitem>
		      </varlistentry>
		      <varlistentry>
			<term><parameter>pr</parameter></term>
			<listitem>
			  <para>A pointer to a 
                          <type>PilotRecord</type>,
			  which this method should fill out the pilot record
                          version of the desktop record.</para>
			</listitem>
		      </varlistentry>
		    </variablelist>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Returns</term>
		  <listitem>
		    <para>0 on success, negative value on error.</para>
		  </listitem>
		</varlistentry>
		<varlistentry>
		  <term>Needed by</term>
		  <listitem>
		    <para>FastSync, SlowSync, Copy To Remote</para>
		  </listitem>
		</varlistentry>
	      </variablelist>
	    </listitem>

	</orderedlist>
      </sect2>
    </sect1>

    <sect1>
      <title>API Functions</title>
      <para>Hi</para>
    </sect1>
  </chapter>
</book>
