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; }