Incremental online backup can be performed while normal database activity proceeds uninterrupted. While the library level backup is the recommended method of implementation, the eXtremeDB runtime exports low level APIs to allow applications to provide a custom backup implementation.
For alternative data export options see page Data Export and Import in C
Library Level Backup
The library level is a convenient way to integrate a database backup process into C applications. This approach assumes that the backup is done to a file system. The backup and restore functions are provided in the
mcobackup
library. Please see the Incremental Backup Implementation page for a detailed description of how the backup process is performed. Also, please see the SDK sample 18-backup_online for implementation details.In order to implement a full or incremental backup, the application must first define filenames for the backup files and labels for backup "tags" then set the appropriate parameters in the
mco_db_params_t
structure passed tomco_db_open_dev()
. For example:char * filename = "MyDb.bak"; char * label_full = "Full"; char * label_inc1 = "Inc1"; char * label_inc2 = "Inc2"; db_params.backup_map_size = 4 * DATABASE_SEGMENT_SIZE / DISK_PAGE_SIZE / 16; db_params.backup_max_passes = 10; db_params.backup_min_pages = 10; sprintf(db_params.backup_map_filename, "%s","Backup_map"); db_params.mode_mask = MCO_DB_INCREMENTAL_BACKUP; rc = mco_db_open_dev(db_name, MyDb_get_dictionary(), &dev, 1, &db_params );The backup map is used to keep track of database pages processed by the backup algorithm. For persistent databases the backup map is written to a file when the
mco_db_close()
API is called. If nobackup_map_filename
is specified, the default name of<database_name>.bm
is used.The backup is an iterative process controlled by the two conditions
backup_max_passes
andbackup_min_pages.
backup_map_size The size of the backup counters array in bytes. It must be power of two. This parameter is ignored and calculated automatically if the parameter disk_max_database_size
is defined (non-zero)backup_min_pages The minimum number of modified pages required to perform an incremental backup. When the number of remaining pages is less than
backup_min_pages
the backup process locks the database exclusively and finalizes the backup. If the number of modified pages is small, it takes a very short time to write them out and complete the backup. (Note that a value of zero disables the backup.)backup_max_passes Irrespective of
backup_min_pages
, this parameter represents the maximum number of loops until an incremental backup is performed.A single backup file can contain several independent backups, possibly of different types (full or incremental) or with different tags or timestamps. Each backup is "framed" within a header and a footer (this frame is called a backup record).
To create a backup file, applications call
mco_backup_create()
specifying afile_name
, alabel
and the backuptype
MCO_BACKUP_TYPE_SNAPSHOT
. This creates the initial backup record. Then successive incremental backup records can be added by callingmco_backup_create()
with backup typeMCO_BACKUP_TYPE_INCREMENTAL
. Or the backup typeMCO_BACKUP_TYPE_AUTO
can be specified to cause automatic selection of a snapshot or incremental record depending on the content of the backup file; if there is no snapshot in the file yet, the backup process will create one; otherwise a partial (incremental) backup record is created.Restoring or Verifying a Backup
Once created, the backup file can be used to restore the database from a specific backup record by calling the
mco_backup_restore()
API with the appropriate label. To view the records in a backup file call themco_backup_list()
API which displays thename
,type
,label
and other properties of the backup records. It may sometimes be useful to check backup files for consistency without performing the restore. Themco_backup_verify()
function is provided for this purpose.The following C application code snippets demonstrate how these APIs might be used. First, to backup a database:
{ mco_db_h con; MCO_RET rc; char * filename = “backup.bak”; char * label = “a label”; /* connect to a database */ rc = mco_db_connect( db_name, &con ); /* backup the database */ rc = mco_backup_create( con, filename, label, MCO_BACKUP_TYPE_AUTO, 1, 0, 0); }Then to restore a database from the backup file:
{ mco_db_h con; MCO_RET rc; char * filename = “backup.bak”; char * label = “a label”; /* connect to a database */ rc = mco_db_connect( db_name, &con ); /* restore the database */ rc = mco_backup_restore( con, filename, label, 0, 0); }Library Level API Reference:
See page Incremental Backup C API for detailed descriptions and examples of the library level APIs.
Low level C API backup functions
The eXtremeDB backup services can be overridden via custom callback function implementations. Also, services can be turned on/off through the internal runtime configuration file
target/mcolib/mcocfg.h
defineMCO_CFG_BACKUP
.By default, the backup services are enabled and the following backup-related APIs are exported:
typedef MCO_RET (*mco_backup_info_proc_t)( uint4 phase, const mco_backup_info_t * info, void * param ); typedef MCO_RET (*mco_backup_chunk_proc_t)( uint4 chunk_id, const char * mem, uint4 mem_sz, void * param ); typedef MCO_RET (*mco_restore_chunk_proc_t)( uint4* chunk_id, char ** mem, uint4 * mem_sz, void * param );The
mco_backup_info_proc_t()
andmco_backup_chunk_proc_t()
callbacks are called by internal eXtremeDB runtime functionmco_backup()
. The first is intended to store informational headers that frame a backup record. The second stores a chunk of data. Themco_restore_chunk_proc_t()
callback is called by internal eXtremeDB runtime functionmco_restore()
and is intended to restore a chunk of data from the backup storage. Applications cannot call these callback APIs directly.This core-level incremental backup/restore API does not limit the application to use a file system or any other specific type of storage. It is up to the application to decide how to store its backups. Internally the runtime functions
mco_backup()
andmco_restore()
assure the integrity of the data chunks. Optionally the application may encrypt or compress the data in the process.The restore procedure requires a database with the same database properties (such as size, memory page size etc.) and overwrites its content with the data pages read from the backup record. As with the library-level backup, it is necessary to have at least one snapshot (full backup record), and any possible number of incremental records, to restore the content of a database.
The following code snippet demonstrates one possible simple implementation of these callback APIs:
/* backup callbacks */ MCO_RET mco_backup_info(uint4 phase, const mco_backup_info_t* info, void* param) { mco_backup_ctx_t *ctx = (mco_backup_ctx_t *)param; mco_backup_info_t hdr = *info; switch (phase) { case MCO_BACKUP_PHASE_1: … /* write backup header */ if (fwrite(&hdr, sizeof(hdr), 1, ctx->f) != 1) { return MCO_E_DISK_WRITE; } ... break; case MCO_BACKUP_PHASE_2: ... /* write backup footer */ if (fwrite(&hdr, sizeof(hdr), 1, ctx->f) != 1) { return MCO_E_DISK_WRITE; } ... break; default: return MCO_E_ILLEGAL_PARAM; } return MCO_S_OK; } MCO_RET mco_backup_chunk(uint4 chunk_id, const char* chunk, uint4 chunk_size, void* param ) { mco_backup_ctx_t *ctx = (mco_backup_ctx_t *)param; ... /* write the chunk */ if (fwrite( chunk, chunk_size, 1, ctx->f) != 1) { return MCO_E_DISK_WRITE; } ... return MCO_S_OK; } MCO_RET mco_backup_create(mco_db_h con, char const* file_name, char const* label, mco_backup_type type, char* err_buf, unsigned int * err_buf_sz) { MCO_RET rc; mco_backup_ctx_t ctx; ... /* open a backup file */ ctx.f = fopen(file_name, "rb+”); ... /* run backup procedure passing-in two callbacks */ rc = mco_backup(con, label, type, mco_backup_info, mco_backup_chunk, &ctx); ... /* close backup file */ fclose(ctx.f); ... return rc; } MCO_RET mco_restore_chunk(uint4* chunk_id, char** pchunk, uint4* pchunk_size, void * param) { mco_backup_ctx_t *ctx = (mco_backup_ctx_t *) param; ... /* read chunk into a buffer and return read size and the content */ ... if ( ((*pchunk_size)=fread( ((*pchunk)=buf), size, 1, ctx->f)) != 1) { return MCO_E_DISK_READ; } ... return MCO_S_OK; } MCO_RET mco_backup_restore(mco_db_h con, char const* file_name, char const* label, char const* cipher, char* err_buf, unsigned int * err_buf_sz) { MCO_RET rc; mco_backup_ctx_t ctx; mco_backup_info_t info; ... /* open a backup file */ ctx.f = fopen(file_name, "rb+”); ... /* read backup header and footer*/ fread( &info, sizeof(info), ctx.f ); ... /* apply the backup from the file passing-in chunk read callback and the backup info (header & footer) */ rc = mco_restore(con, &info, mco_restore_chunk, &ctx); ... /* close backup file */ fclose(ctx.f); ... return rc; }