# Using the Flash Simulator

> Tying up the Simulator with the database runtime example:

>         static void create_database(const char *db_name, mco_device_t *devs)
>         {
>             mco_db_params_t    db_params;
>             mco_flashsim_params_t fsp = {0};

>             /* --- Configure flash simulator parameters --- */
>             fsp.page_size       = P_RAMFLASH_PAGE_SIZE;        /* Page size in bytes (must be power of two) */
>             fsp.pages_per_block = P_RAMFLASH_PAGES_PER_BLOCK;  /* Number of pages per erase block */
>             fsp.n_blocks        = P_RAMFLASH_NUM_BLOCKS;       /* Total number of erase blocks */
>             fsp.image_filename  = g_flash_image_file_name;     /* Optional file to persist flash content across runs */

>             /* --- Device 0: main database memory (RAM) --- */
>             devs[0].assignment = MCO_MEMORY_ASSIGN_DATABASE;
>             devs[0].size       = P_DB_SIZE;
>             devs[0].type       = MCO_MEMORY_CONV;
>             devs[0].dev.conv.ptr = (char*)malloc(devs[0].size);
>             devs[0].dev.conv.flags = 0;

>             /* --- Device 1: database cache (RAM) --- */
>             devs[1].assignment = MCO_MEMORY_ASSIGN_CACHE;
>             devs[1].size       = P_DB_CACHE_SZ;
>             devs[1].type       = MCO_MEMORY_CONV;
>             devs[1].dev.conv.ptr = (char*)malloc(devs[1].size);
>             devs[1].dev.conv.flags = 0;

>             /* --- Device 2: persistent storage device (bound to flash simulator via media_context) --- */
>             devs[2].assignment = MCO_MEMORY_ASSIGN_PERSISTENT;
>             devs[2].type       = MCO_MEMORY_FILE;              /* FILE type indicates external media context will be used */
>             devs[2].dev.file.flags = MCO_FILE_OPEN_WITH_MEDIA_CTX; /* Use media_context instead of a filename */
>             devs[2].dev.file.name[0] = '\0';                   /* Filename is ignored — media context provides I/O backend */

>             /* --- Device 3: memory for flash simulator internal state --- */
>             devs[3].assignment = MCO_MEMORY_ASSIGN_PERSISTENT;
>             devs[3].size       = mco_flashsim_memory_size(&fsp); /* Calculate required memory size based on geometry */
>             devs[3].type       = MCO_MEMORY_CONV;
>             devs[3].dev.conv.ptr = (char*)malloc(devs[3].size);
>             devs[3].dev.conv.flags = 0;

>             /* --- Initialize the flash simulator instance --- */
>             CHECK(mco_flashsim_open(&devs[3], &fsp, &g_flash_handle)); /* Open simulator using allocated memory */

>             /* --- Bind simulator to the persistent device via media context --- */
>             /* mco_flashsim_media_context() returns a pointer to the simulator's internal mco_device_t,
>             which eXtremeDB uses as the I/O backend for flash operations. */
>             CHECK(mco_flashsim_media_context(g_flash_handle,
>                                             &devs[2].dev.file.media_context,
>                                             &devs[2].dev.file.media_context_size));

>             /* --- Configure database parameters --- */
>             mco_db_params_init(&db_params);
>             db_params.mode_mask                 = P_DB_MODE_MASK;
>             db_params.mem_page_size             = P_DB_MEM_PAGE_SZ;
>             db_params.disk_page_size            = P_DB_DISK_PAGE_SZ;
>             db_params.disk_max_database_size    = P_DB_DISK_MAX_SIZE;
>             db_params.db_max_connections        = 16;
>             db_params.meta_cache_lines          = P_DB_META_CACHE_LINES;
>             db_params.meta_cache_ways           = P_DB_META_CACHE_WAYS;
>             db_params.flash_gc_ratio            = P_DB_FLASH_GC_RATIO;

>             /* --- Open database with RAM, cache, and simulated flash devices --- */
>             CHECK(mco_db_open_dev(db_name, perf_get_dictionary(), devs, 3, &db_params));
>         }

>         ...

>         int perf(const char *image_name)
>         {
>             mco_device_t devices[4];
>             mco_db_h db;

>             g_flash_image_file_name = image_name;

>             mco_error_set_handler(&errhandler);
>             CHECK(mco_runtime_start());

>             create_database("perf_db", devices);               /* Create and open DB with flash simulator */
>             CHECK(mco_db_connect("perf_db", &db));

>             do_perf(db, 1000);                                 /* Run test workload */

>             /* --- Print flash simulator statistics and block health map --- */
>             /* Shows operation counts, data volume, timing, and visual block status:
>             '.' = healthy, '!' = error, 'X' = bad block */
>             mco_flashsim_print_stat(g_flash_handle, 128);      /* 128 blocks per line in the map */

>             /* --- Save simulator state to image file (if filename was provided) --- */
>             /* Enables exact state restoration on next run for debugging or regression testing */
>             if (g_flash_image_file_name) {
>                 CHECK(mco_flashsim_save_image(g_flash_handle, NULL)); /* Uses filename from fsp.image_filename */
>             }

>             CHECK(mco_db_disconnect(db));
>             destroy_database("perf_db", devices);
>             mco_runtime_stop();
>             return 0;
>         }