# Asynchronous Replication

> As mentioned in the HA Applications page, in `asynchronous` or lazy replication, updates are propagated to replica nodes asynchronously and after the transaction commits on the master node. These updates are applied to replica nodes as separate transactions which can improve transaction responsiveness, however replica `read-only` transactions run the risk of operating with stale data. Because replica databases are available to the replica applications for read-only access, replica applications may read ‘stale’ data if transactions were committed at the master but not yet propagated to the replica.

> Asynchronous replication is enabled in C/C++ applications by setting the `mode_flags` element to `MCO_HAMODE_ASYNCH` in the master:

>         mco_HA_master_params_t MasterParams;
>         mco_HA_master_params_init( &MasterParams );
>         MasterParams.mode_flags = MCO_MASTER_MODE | MCO_HAMODE_ASYNCH;
>         …
>         mco_HA_set_master_params( db, &MasterParams );

> In C# and Java applications:

>         MasterConnection.Parameters MParams = new MasterConnection.Parameters(
>         MasterConnection.MCO_HAMODE_ASYNCH);
>         con.SetReplicationMode( MParams );

> The master application must also create a memory device to accommodate the asynchronous buffer in either shared or conventional memory. The size of the buffer is defined in bytes (not in a number of transactions) and is processed in a separate task within the eXtremeDB High Availability runtime.

> The following code snippet demonstrates how the async buffer can be initialized in C/C++ applications:

>         /****************************************************
>         * Asynchronous commit thread
>         * It sends transaction data to replicas using the async_databuf
>         ****************************************************/
>         void AsyncCommit( sample_task_t * descriptor )
>         {
>             /* wait for async commit event and output the portion of data to the stream */
>             while (mco_HA_async_send_data_to_replicas(descriptor->db_connection) ==
>                 MCO_S_OK)
>             sample_sleep(1);
>         }

>         /****************************************************
>         /* Snippet from the master main that initializes async replication */
>         /****************************************************
>         mco_HA_master_params_init( &MasterParams );
>         MasterParams.mode_flags = MCO_MASTER_MODE | MCO_HAMODE_ASYNCH;

>         /* assign the device as an asynchronous buffer */
>         MasterParams.async_databuf.assignment = MCO_MEMORY_ASSIGN_HA_ASYNC_BUF;

>         /* set the device size */
>         MasterParams.async_databuf.size       = ASYNC_DATABUF_SIZE;
>         if ( runtime_info.mco_shm_supported )
>         {
>             /* set the device as a shared named memory device */
>             MasterParams.async_databuf.type       = MCO_MEMORY_NAMED;

>             /* set memory name */
>             sprintf( MasterParams.async_databuf.dev.named.name, "%s-ha", db_name);
>             MasterParams.async_databuf.dev.named.flags = 0;  /* zero flags */

>             /* set mapping address or zero it out */
>             MasterParams.async_databuf.dev.named.hint  = 0;
>         }
>         else
>         {
>             /* set a conventional memory device */
>             MasterParams.async_databuf.type         = MCO_MEMORY_CONV;
>             MasterParams.async_databuf.dev.conv.ptr = (void*)malloc(ASYNC_DATABUF_SIZE);
>         }

>         mco_HA_set_master_params(db, &MasterParams); /*  set MASTER mode */

>         /* start the ListenToReplicas thread*/
>         sample_start_connected_task(&listen_task, ListenToReplicas, db_name, &ha );

>         /* start the AsyncCommit thread*/
>         sample_start_connected_task(&async_commit_task, AsyncCommit, db_name, 0 );

> A similar C# implementation would look like the following:

>         // Asynchronous commit thread that sends transaction data to replicas,
>         // using async databuf
>         public void Replicate()
>          {
>             MasterConnection con = new MasterConnection(db);
>             while (con.AsyncSendDataToReplicas())
>              {
>                 Thread.Sleep(REPLICATION_PERIOD);
>             }
>             con.Disconnect();
>         }

>         Master()
>         {
>             //****************************************************
>             // Snippet from the master main that initializes async replication
>             //****************************************************
>             // set HA mode

>             MasterConnection.Parameters MParams = new
>             MasterConnection.Parameters(
>             MasterConnection.MCO_HAMODE_ASYNCH );
>             MasterParams.AsyncBuf = new
>             Database.PrivateMemoryDevice( Database.Device.Kind.AsyncBuffer,
>             ASYNC_BUF_SIZE );
>             con.SetReplicationMode( MParams );
>             MParams.listening = true;

>             // start listen and async. commit threads
>             Thread listenThread = new Thread(new ThreadStart(Listen));
>             Thread replicateThread = new Thread(new ThreadStart(Replicate));
>             listenThread.Start();
>             replicateThread.Start();

> As with synchronous replication, no additional replication logic is required in either master or replica applications; all replication operations are managed internally by the eXtremeDB High Availability runtime.

> ## Replication Event Notifications

> Whether using `synchronous` or `asynchronous` replication, replica application instances can be configured to receive notification of various synchronization and replication events. The possible notification events are defined as follows:

> MCO_REPL_NOTIFY_CONNECTED
> Replica successfully connected.
> MCO_REPL_NOTIFY_CONNECT_FAILED
> Replica connection failed.
> MCO_REPL_NOTIFY_DB_EQUAL
> The database is the same, no need to load the database.
> MCO_REPL_NOTIFY_DB_LOAD_BEGIN
> Begin loading the database.
> MCO_REPL_NOTIFY_DB_LOAD_FAILED
> Error loading the database; param1 on the notification callback is the MCO_RET return code.
> MCO_REPL_NOTIFY_DB_LOAD_OK
> Database successfully loaded; param1 on the notification callback is the MCO_E_HA_REPLICA_STOP_REASON code.
> MCO_REPL_NOTIFY_DB_CREATION_FAILED
> Database creation failed" notification; param1 on the notification callback is the MCO_RET return code.
> MCO_REPL_NOTIFY_COMMIT_FAILED
> Error during a transaction commit; param1 on the notification callback is the MCO_RET return code.
> MCO_REPL_NOTIFY_REPLICA_STOPPED
> Replication stopped.
> MCO_REPL_NOTIFY_HOTSYNC
> Hotsynch process beginning.
> MCO_REPL_NOTIFY_EOHOTSYNC
> Hotsynch process completed.
> MCO_REPL_NOTIFY_STATEFUL_SYNC
> Stateful synch process beginning.
> MCO_REPL_NOTIFY_STATEFUL_SYNC_END
> Stateful synch process completed.
> MCO_REPL_NOTIFY_MASTER_DB_EXTENDED
> The master has extended the database memory.

> Replication event notifications in C/C++ replica applications are enabled by setting the `MCO_HAMODE_REPLICA_NOTIFICATION` bit in the `mode_flags` element and the function address of the event handler in the `notifying_callback` element in the `mco_HA_replica_params_t` structure passed to `mco_HA_attach_master()`. In C# and Java applications the mode flag and callback are specified in the `ReplicaConnection.Parameters` sent to method `ReplicaConnection.AttachMaster()`.