Fast Transfer

Fast Transfer is a way to stream changes between servers or accounts. It uses a special serialisation format to avoid having to do a lot of separate operations on tables, properties and streams through a folder hierarchy.

The protocol is described in MS-OXCFXICS. That document also deals with Incremental Change Synchronization.

The remote operations

There are two "kinds" of remote operation for Fast Transfer. libmapi provides API wrappers for each ROP.

The first kind sets up a transfer context, which is basically either a "source" or a "sink" for a fast transfer stream:
- RopFastTransferSourceCopyTo - general "source" for a hierarchy transfer, implemented by FXCopyTo()
- RopFastTransferSourceCopyFolder - source for a folder (and usually subfolders and messages), implemented by FXCopyFolder()
- RopFastTransferSourceCopyMessages - source for a list of messages (and usually any attachments and embedded messages), implemented by FXCopyMessages()
- RopFastTransferSourceCopyProperties - source for a list of properties, implemented by FXCopyProps()
- RopFastTransferDestinationConfigure - sets up a "sink" for fast transfer stream (you have to specify the source stream type)
- RopTellVersion (not usually required, but implemented by TellVersion().

The second kind actually does the transfer of the stream, using RopFastTransferSourceGetBuffer to copy from the source, and RopFastTransferDestinationPutBuffer to write to the sink.
RopFastTransferSourceGetBuffer is implemented by FXGetBuffer() and RopFastTransferDestinationPutBuffer is implemented by FXPutBuffer().

The parser

Openchange (libmapi) provides a parser for the fast transfer stream format. The format is a bit complex to parse (mainly because any of the variable length properties can be split at any point in the stream in order to fit into the available buffer space), so we provide a callback based API so it is not necessary to re-implement the parser. You simply write your handler functions, and configure the parser using function pointers to the handler functions.

The basic usage of the parser is to:
  1. set up the source context (using FXCopyTo(), FXCopyFolder(), FXCopyMessages() or FXCopyProps()).
  2. create a struct fx_parser_context using fxparser_init()
  3. set the callback routines (using fxparser_set_marker_callback(), fxparser_set_delprop_callback(), fxparser_set_namedprop_callback() and fxparser_set_property_callback())
  4. provide the stream (in chunks as provided by FXGetBuffer()) to fxparser_parse(), repeating until the TransferStatus from FXGetBuffer() is something other than TransferStatus_Partial
  5. free the parser context using talloc_free()
  6. release the source context (using mapi_object_release())

See the code in testprogs/check_fasttransfer.c for a live example, and check the libmapi.h header for the function pointer signatures.

Also available in: HTML TXT