# Database Memory Device Specification in C

> The application determines the size and location of the memory devices, the type of memory and how the eXtremeDB runtime will use the device by defining a mco_device_t structure. This structure is necessarily quite complex in order to accommodate a variety of storage device characteristics. However, for an in-memory database using conventional memory this definition is very simple: it is simply a matter of specifying a single device, its type, assignment, size and, after allocating heap memory, its address. For example:

>         int main(int argc, char* argv[])
>         {
>             ...
>             mco_device_t       dev;
>             ...
>             dev.type       = MCO_MEMORY_CONV;                /* Set the device as a conventional memory device */
>             dev.assignment = MCO_MEMORY_ASSIGN_DATABASE;     /* Assign the device as main database memory */
>             dev.size       = DATABASE_SEGMENT_SIZE;          /* Set the device size */
>             dev.dev.conv.ptr = (void*)malloc( DATABASE_SEGMENT_SIZE ); /* Allocate memory and set device pointer */
>             ...
>         }

> For a shared memory device, the definition needs to specify the name that will be used by the OS to share this memory segment, possible shared memory flags and a possible "hint" address. (please refer to `mco_device_t` for details). For example the following code snippet defines a shared memory device for a typical Windows application:

>         int main(int argc, char* argv[])
>         {
>             ...
>             mco_device_t       dev;
>             ...
>             dev.assignment = MCO_MEMORY_ASSIGN_DATABASE;     /* Assign the device as main database memory */
>             dev.size       = DATABASE_SEGMENT_SIZE;          /* Set the device size */
>             dev.type       = MCO_MEMORY_NAMED;               /* Set the device as a shared named memory device */
>             sprintf( dev.dev.named.name, "%s-db", db_name ); /* Set memory name */
>             dev.dev.named.flags = 0;                         /* Zero flags */
>             dev.dev.named.hint  = 0;                         /* Set mapping address or null it */
>             ...
>         }

> ## Persistent Databases

> Typically a persistent database application will define an array of at least four memory devices to manage the following distinct memory regions:

> MCO_MEMORY_ASSIGN_DATABASE | For metadata and database objects, indexes and other database structures
> MCO_MEMORY_ASSIGN_CACHE | For the disk manager cache (page pool)
> MCO_MEMORY_ASSIGN_PERSISTENT | A persistent storage device (can be file, multi-file or RAID). Note that if a persistent device is defined and the application does not explicitly assign `disk_page_size` the runtime will assign it the default value of 4096 bytes. (If multiple applications or tasks attempt to assign different disk page sizes for the same database the runtime returns an error code.)
> MCO_MEMORY_ASSIGN_LOG | A persistent storage device that contains the database log file

> For a typical persistent database application the memory devices could be defined as follows:

>         #define  N_DEVICES             4
>         #define DATABASE_SIZE 600 * 1024
>         #define CACHE_SIZE 300 * 1024
>         const char * db_name = "disk_db";

>         int main(int argc, char* argv[])
>         {
>             ...
>             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;

>             ...
>         }

> Please refer to the definition of the mco_device_t structure for further details regarding runtime options that can be set for persistent storage devices.