# Opening Persistent Databases with the C API

> As explained for In-Memory Databases, before performing data storage and retrieval operations, we must open and connect to the database. To open the database C applications call function `mco_db_open_dev()` with a number of parameters including the database dictionary, a database parameters structure and an array of memory devices. This is demonstrated in SDK sample `samples/native/coresample 02_open_disk_file`.

> ## Defining Storage Devices

> Whereas for an in-memory database, there can be a single device to describe the conventional (aka local or in-process) or shared memory for the database, for persistent databases, or hybrid databases (which contain both `transient` and `persistent` classes), a minimum of four devices must be defined. For example:

>         const char * db_name = "C:\\data\\myDb";
>         #define  N_DEVICES            4
>         #define  DATABASE_SIZE        (600 * 1024 * 10)
>         #define  CACHE_SIZE           (300 * 1024 * 10 )

>         mco_device_t       dev[N_DEVICES];

>         /* Configure first memory device as a plain conventional memory region */
>         dev[0].type       = MCO_MEMORY_CONV;
>         dev[0].assignment = MCO_MEMORY_ASSIGN_DATABASE;
>         dev[0].size       = DATABASE_SIZE;
>         dev[0].dev.conv.ptr = (void*)malloc( DATABASE_SIZE );

>         /* Configure conventional memory region for cache */
>         dev[1].type       = MCO_MEMORY_CONV;
>         dev[1].assignment = MCO_MEMORY_ASSIGN_CACHE;
>         dev[1].size       = CACHE_SIZE;
>         dev[1].dev.conv.ptr = (void*)malloc( CACHE_SIZE );

>         /* Configure FILE memory device for main database storage */
>         dev[2].type = MCO_MEMORY_FILE;
>         dev[2].assignment = MCO_MEMORY_ASSIGN_PERSISTENT;
>         sprintf(dev[2].dev.file.name, FILE_PREFIX "%s.dbs", db_name);
>         dev[2].dev.file.flags = MCO_FILE_OPEN_DEFAULT;

>         /* Configure FILE memory device for transaction log */
>         dev[3].type       = MCO_MEMORY_FILE;
>         dev[3].assignment = MCO_MEMORY_ASSIGN_LOG;
>         sprintf(dev[3].dev.file.name, FILE_PREFIX "%s.log", db_name);
>         dev[3].dev.file.flags = MCO_FILE_OPEN_DEFAULT;

> ## Database Parameters

> The database open parameters are defined in structure `db_params_t` Typically the parameters are initialized by calling mco_db_params_init() to set default values, then the following four application-specific parameters are assigned:

>         #define  MEMORY_PAGE_SIZE     128
>         #define  PSTORAGE_PAGE_SIZE   4096

>         mco_db_params_t    db_params;

>         /* Initialize and customize the database parameters */
>         mco_db_params_init ( &db_params );                  /* Initialize the params with default values */
>         db_params.mem_page_size      = MEMORY_PAGE_SIZE;    /* Set page size for in-memory part */
>         db_params.disk_page_size     = PSTORAGE_PAGE_SIZE;  /* Set page size for persistent storage */
>         db_params.db_max_connections = 1;                   /* Set total number of connections to the database */
>         db_params.db_log_type        = UNDO_LOG;            /* Set log type */

> ## Database Operations

> Once the persistent database devices and parameters are specified, the database open call `mco_db_open_dev()`, the connect call `mco_db_connect()` and all other APIs to perform database operations are identical to those for in-memory databases. Please refer to SDK sample `samples/native/coresample 02_open_disk_file` for further implementation details.