# Synchronous Replication

> Synchronous replication using the time-cognizant, two-phase commit protocol is the default mode. So it is sufficient for C/C++ master applications to call:

>         mco_HA_master_params_t MasterParams;
>         mco_HA_master_params_init( &MasterParams );
>         mco_HA_set_master_params( db, &MasterParams );

> In C# and Java applications:

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

> The eXtremeDB High Availability runtime does the initial synchronization in C/C++ master applications during the `mco_HA_attach_replica()` call and all other replication happens during the call to `mco_trans_commit()`; in C# and Java applications during the `MasterConnection.AttachReplica()` and `MasterConnection.CommitTransaction()` method.

> On the replica side the eXtremeDB High Availability runtime manages initial replication for C/C++ applications within `mco_HA_attach_master()`. When `mco_HA_attach_master()` is called, control is passed to the eXtremeDB High Availability runtime which manages the initial synchronization of the replica database and then waits for and processes transaction data sent from the master during the master call to `mco_trans_commit()`. In C# and Java replica applications initial synchronization and subsequent transaction replication is managed by the eXtremeDB High Availability runtime during the `ReplicaConnection.AttachMaster()` method.

> ## Implementation

> Most C/C++ applications using eXtremeDB High Availability will employ just the following functions from the protocol layer API:

>         MCO_RET mco_HA_start();
>         void mco_HA_master_params_init();
>         MCO_RET mco_HA_set_master_params();
>         MCO_RET mco_HA_attach_replica();
>         void mco_HA_replica_params_init();
>         MCO_RET mco_HA_attach_master();
>         MCO_RET mco_HA_stop();

> Equivalently, most C# and Java applications using eXtremeDB High Availability will employ just the following API methods:

>         Database db = new Database();
>         db.Open();
>         MasterConnection con = new MasterConnection(db);
>         con.SetReplicationMode();
>         con.AttachReplica();
>         con.StopReplication();
>         ReplicaConnection con = new ReplicaConnection(db);
>         con.AttachMaster();
>         con.Disconnect();
>         db.Close();

> Using the HA “interface” API on the master side:

> To initiate replication on the master side the application must:

> - Initialize the HA runtime in C/C++ applications by calling `mco_HA_start()`; in C# and Java applications by instantiating a Database object with High Availability Support enabled, eg:
> - `Database db = new Database( new ExtremedbWrapper(),Database.Mode.HighAvailabilitySupport);`
> - In C/C++ applications, call `mco_HA_master_params_init()` to initialize the `mco_HA_master_params_t` structure (`include/ha/mcoha.h`); in C# and Java applications instantiate a `MasterConnection.Parameters` object.
> - Define the master mode and master flags in C/C++ applications by filling in the `mco_HA_master_params_t` structure. (Note that the `MCO_MASTER_MODE` flag value must be set.); in C# and Java applications by setting the properties of the `MasterConnection.Parameters` object.
> - Set up master replication mode flags in C/C++ applications by calling `mco_HA_set_master_params()`; in C# and Java applications by calling the `MasterConnection.SetReplicationMode()` method.
> - Create a `listener` task.
> - In the listener thread, for C/C++ applications call `mco_HA_attach_replica()`; in C# and Java applications by call the `MasterConnection.AttachReplica()` method.
> - To initiate asynchronous replication a couple of more steps are required (discussed later).

> The following code fragment illustrates a simple C/C++ master implementation.

>         void* ListenToReplicas ( void *p )
>         {
>             while ((! stop_flag ) {
>                 ret = mco_HA_attach_replica(...);

>                 if ( MCO_S_OK != ret )
>                 // something went wrong, examine the return code
>                 ...
>                 else
>                 // replica is connected successfully
>             }

>         }

>         int main(int argc, char* argv[])
>         {
>             mco_HA_master_params_t MasterParams;
>             …
>             /* initialize HA subsystem */
>             mco_HA_start();
>             /* create the database */
>             rc = mco_db_open_dev( dbName, dbname_get_dictionary(),°
>             dev, n_dev, &db_params);
>             …

>             /* connect to the database, obtain a database handle */
>             rc = mco_db_connect( dbName, &db );
>             …
>             /* set MASTER mode */
>             mco_HA_master_params_init( &MasterParams );
>             mco_HA_set_master_params( db, &MasterParams );
>             /* create a ‘listener’ thread */
>             rc = pthread_create (&ConnThread, NULL,
>             (void*)ListenToReplicas, &ha);

>             /* Continue with the regular database processing */
>             while (master_has_some_work_to_do) {
>             rc = mco_trans_start( db, MCO_READ_WRITE,
>             MCO_TRANS_FOREGROUND, &t );
>             ...
>             rc = mco_trans_commit(t);
>         }

>         /* Detach and close connections to replicas */
>         mco_HA_stop(db);
>         }

> Note that `mco_HA_attach_replica()` is called in the context of a separate “listener” task. Upon receiving a connection request, this function performs the following actions to “activate” the replica:

> - Wait for the replica connection
> - Accept the connection, create a channel
> - Transmit initial synchronization data to the replica
> - Register the replica with the HA runtime

> The `mco_HA_attach_replica()` function is described in detail in the API Reference section, but briefly its prototype is:

>         mco_HA_attach_replica( mco_db_h db, char* masterport,
>                     timer_unit timeout);

> The timeout argument represents the “accept connection” timeout.

> Note that If the master database is a shared-memory database and several processes access it, only one process (called the `primary` master) handles connections to replicas. So only the primary master process can call network-related functions such as `mco_HA_keep_alive()`, `mco_HA_attach_replica()`,etc.

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

>         public void Listen() {
>         MasterConnection con = new MasterConnection(db);

>             while (listening) {
>             if (con.AttachReplica(PORT, ATTACH_TIMEOUT)) {
>                 // Replica connected…
>                 }
>             }
>         con.Disconnect();
>         }

>         Master()
>         {
>             Database.Parameters parameters = new Database.Parameters();
>             db = new Database(new ExtremedbWrapper(),
>             Database.Mode.HighAvailabilitySupport);
>             db.Open( dbName, parameters, DATABASE_SIZE);
>             MasterConnection con = new MasterConnection(db);

>             // set HA mode
>             MasterConnection.Parameters MParams = newMasterConnection.Parameters(
>             MasterConnection.MCO_HAMODE_HOTSYNCH );
>             con.SetReplicationMode( MParams );
>             MParams.listening = true;

>             // start listen thread
>             Thread listenThread = new Thread(new ThreadStart(Listen));
>             listenThread.Start();

>             // continue with the regular database processing
>             while (master_has_some_work_to_do) {
>             con.StartTransaction(Database.Transaction.ReadWrite);
>             ...
>             con.CommitTransaction();
>         }

>         // stop thread
>         listening = false;
>         listenThread.Join();

>         con.Disconnect();
>         db.Close();
>         }

> Using the HA “interface” API on the replica side:

> To initiate replication on the replica-side the application must:

> - Initialize the HA runtime in C/C++ applications by calling `mco_HA_start()`; in C# and Java applications by instantiating a Database object with High Availability Support enabled, eg:
> - `Database db = new Database( new ExtremedbWrapper(),Database.Mode.HighAvailabilitySupport);`
> - Create and connect to the database.
> - Initialize the replica mode flags in C/C++ applications by calling `mco_HA_replica_params_init()`; in C# and Java applications by setting the properties of the `ReplicaConnection.Parameters` object.
> - Begin replication in C/C++ applications by calling `mco_HA_attach_master()`; in C# and Java applications by method `ReplicaConnection.AttachMaster()`.

> The following code fragment illustrates a simple C/C++ replica implementation.

>         int main(int argc, char* argv[])
>         {
>             int stopReason = 0;
>             mco_HA_replica_params_t ReplicaParams;
>             ...

>             /* initialize HA subsystem */
>             mco_HA_start();

>             /* create the database */
>             rc = mco_db_open_dev( dbName, dbname_get_dictionary(),°
>                         dev, n_dev, &db_params);
>             …
>             /* connect to the database, obtain a database handle */
>             rc = mco_db_connect( dbName, &db );
>             …
>             /* set replica params */
>             mco_HA_replica_params_init( &ReplicaParams );
>             rc = mco_HA_attach_master( &db, mastername,
>                             &ReplicaParams,
>                             &stopReason,
>                             TM_CONNECTION_TIMEOUT);
>             return stopReason;
>         }

> Note that `mco_HA_attach_master()` is a blocking call. Essentially all control is turned over at this point to the eXtremeDB High Availability runtime which manages the initial synchronization and then commits transactions sent from the master. The function is described in detail in the API Reference section, but briefly its prototype is:

>         MCO_RET mco_HA_attach_master( mco_db_h db,
>         const char* conn_string,
>         const mco_HA_replica_params_t* params,
>         MCO_E_HA_REPLICA_STOP_REASON* stop_reason,
>         timer_unit timeout);

> The `stop_reason` indicates why the runtime has returned control to the application (`include/ha/mcoha.h`). When control is returned to the replica application, it should examine the `stop_reason` and make a decision on the course of further action. It could, for example, become the master application itself, or simply terminate. The timeout represents the `connection` timeout (the period of time the replica waits while attempting to make a connection to the master). The `params` structure contains a set of replica control flags (`include/ha/mcoha.h`). For example `MCO_HAMODE_REPLICA_NOTIFICATION`, etc.

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

>         public Slave()
>         {
>             Database.Parameters parameters = new Database.Parameters();
>             parameters.MemPageSize = PAGE_SIZE;
>             db = new Database(new ExtremedbWrapper(),
>             Database.Mode.HighAvailabilitySupport);
>             db.Open( dbName, parameters, DATABASE_SIZE );

>             // start working thread
>             running = true;
>             Thread inspectThread = new Thread(new ThreadStart(Run));
>             inspectThread.Start();

>             ReplicaConnection con = new ReplicaConnection(db);
>             ReplicaConnection.Parameters RParams = new ReplicaConnection.Parameters();

>             if (!con.AttachMaster("localhost:" + PORT, replParams, CONNECT_TIMEOUT)) {
>                 Console.WriteLine("Failed to connect to master");
>             }

>             //stop working thread
>             running = false;
>             inspectThread.Join();

>             Console.WriteLine("Replica is terminated");
>             con.Disconnect();
>             db.Close();
>         }