📄 main.c
字号:
/***************************************************************
* *
* Copyright (c) 2001-2007 McObject LLC. All Right Reserved. *
* *
***************************************************************/
#include "platform.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "nvram_db.h"
#define REGISTRY_SIZE (3000)
#define DB_SIZE ( 1 * 1024 * 1024) // ( 32 * 1024)
DEFINE_PROCESS_MASKS(set);
static char mem__[DB_SIZE + REGISTRY_SIZE + 32];
#define NVRAM_BEGIN ((long)(& mem__[0]))
#define NVRAM_END (NVRAM_BEGIN + sizeof(mem__))
#define STRINGS_DIM 10
#define STRINGS_STEP 100
#define MAX_VECT_LEN 10
#define LOG_PERIOD 10000
#define REGISTRY_ADDRESS ((char*) NVRAM_BEGIN )
#define DB_ADDRESS ((char*) ( NVRAM_BEGIN + REGISTRY_SIZE ) )
#define CHECKSUM_ADDR ((char*) ( NVRAM_BEGIN + REGISTRY_SIZE + DB_SIZE) )
#ifndef MCO_PLATFORM_X64
#define PAGESIZE 96
#else
#define PAGESIZE 192
#endif
THREAD_ID thWorkThread;
THREAD_ID thStartStop;
THREAD_ID thCheckRes;
mco_db_h db = 0;
mco_db_h* pdb;
int startflag = 0;
int stopflag = 0;
int CheckTime = 1000;
int idx = 0;
int short_loop = - 1;
int long_loop = - 1;
int count = 0;
int test_Mode = 0;
static char* strings[STRINGS_DIM];
typedef struct CheckSum_t
{
int checksum_before_commit;
int checksum_after_commit;
} CheckSums;
static const char* dbName = "nvram_db";
void usage(void)
{
Printf("Usage: \n\trecovery\t[-t][timeout_value] | \n");
Printf("\t\t\t[-h]\n");
Printf("\t\t\t[-e]\n");
}
void _SH_(void)
{
Printf("\n\t This test demonstrates database recovery after the hardware reset.\n"
"\tThe working thread creates a database in the local memory buffer\n"
"\tand updates it in an infinite loop.\n"
"\t When the Enter key is pressed, the working thread is first cancelled\n"
"\tand then restarted. After the thread is restarted, it connects to\n"
"\tthe database and performs the recovery if necessary.\n\n"
"\t The sample uses mco_db_check_resources() function, that is called\n"
"\tfrom the \"watchdog\" thread in order to detect hanging on the resource\n""\tand repair it.\n\n");
Printf("\tCopyright (c) 2001-2007 McObject LLC. All Right Reserved.\n");
Printf("\n\teXtremeDB runtime version %d.%d, build %d\n\n", MCO_COMP_VER_MAJOR, MCO_COMP_VER_MINOR,
MCO_COMP_BUILD_NUM);
usage();
if (test_Mode == 0)
{
Printf("\n\tPress Enter to start");
getchar();
}
}
void help(void)
{
Printf("Usage: \trecovery [OPTIONS]\n");
Printf("Options:\n\n");
Printf("-t[N] Resource timeout value. N is timeout value in milliseconds,\n"" default is 1000 ms\n");
Printf("-e Exit from the program\n");
Printf("-h help\n");
}
short rand2(short lowlimit, short uplimit)
{
int n = rand();
return (short)((n % (uplimit - lowlimit + 1)) + lowlimit);
}
void make_strings(void)
{
int i, j, strsz;
for (j = 0; j < STRINGS_DIM; j++)
{
strsz = STRINGS_STEP *(j + 1);
strings[j] = (char*)malloc(strsz + 1);
for (i = 0; i < strsz; i++)
{
strings[j][i] = (char)rand2('a', 'z');
}
strings[j][strsz] = 0;
}
}
char* get_random_string()
{
return strings[rand2(0, STRINGS_DIM - 1)];
}
static int starting_create_new_db(mco_db_h* pdb)
{
if (mco_db_connect(dbName, pdb) != MCO_S_OK)
{
*pdb = 0;
return 1;
}
else
{
mco_db_disconnect(*pdb);
*pdb = 0;
return 0;
}
}
static void errhandler(int n)
{
printf("\neXtremeDB runtime fatal error: %d", n);
for (;;)
;
}
static const char* sKind(int k)
{
switch (k)
{
case MCO_REPORT_DB_TOTAL:
return "Database Instance ";
case MCO_REPORT_TREE_TOTAL:
return "All Tree Indexes ";
case MCO_REPORT_HASH_TOTAL:
return "All Hash Indexes ";
case MCO_REPORT_LIST_TOTAL:
return "All Lists ";
case MCO_REPORT_TREE:
return "Tree Index ";
case MCO_REPORT_HASH:
return "Hash Index ";
case MCO_REPORT_LIST:
return "List ";
case MCO_REPORT_OID:
return "OID Index ";
}
return "??? ";
}
static void detailed_mem_report(mco_db_h db)
{
int i;
#define maxItems 10
mco_report_item_t v[maxItems];
int nitm;
mco_db_report(db, MCO_REPORT_DB_ALL, v, maxItems, &nitm);
#undef maxItems
printf("\n********** Memory report ****************************");
for (i = 0; i < nitm; i++)
{
mco_report_item_h itm = v + i;
const char* itm_name = itm->name ? itm->name: "";
const char* kindstr = sKind(itm->flag);
printf("\n%s [%2d] %3d pages (%3d Kb) %5d items h=%2d --%s", kindstr, (int)(itm->id), (int)(itm->used_pages),
(int)(itm->used_pages* PAGESIZE / 1024), (int)(itm->objects_num), (int)(itm->tree_height), itm_name);
}
printf("\n*****************************************************\n");
}
static void classStat0(mco_trans_h t, mco_db_h db)
{
mco_class_stat_t stat;
detailed_mem_report(db);
mco_class_stat_get(t, Rec_code, &stat);
printf("\nstat: obj=%d corep=%d blobp=%d corespace=%d\n", stat.objects_num, stat.core_pages, stat.blob_pages,
stat.core_space);
}
static int nRecords(mco_db_h db)
{
int ret = 0;
mco_trans_h t;
mco_class_stat_t stat;
mco_trans_start(db, MCO_READ_WRITE, MCO_TRANS_FOREGROUND, &t);
mco_class_stat_get(t, Rec_code, &stat);
ret = (int)stat.objects_num;
mco_trans_commit(t);
return ret;
}
static void classStat(mco_db_h db)
{
mco_trans_h t;
mco_trans_start(db, MCO_READ_WRITE, MCO_TRANS_FOREGROUND, &t);
classStat0(t, db);
mco_trans_commit(t);
}
int check_task(uint4 task_id, void* user_data)
{
return 0; // all tasks being checked already dead
}
static int str_checksum(const char* s, uint2 len)
{
int sum = 11;
uint2 j;
for (j = 0; j < len; j++)
{
sum += (17* s[j]) % 9003;
}
return sum;
}
static int record_checksum(int key, const char* str, uint2 str_len)
{
return str_checksum(str, str_len);
}
static int record_checksum_byhandle(Rec* rec)
{
uint4 key;
uint2 len;
MCO_RET rc = 0;
int chksum;
uint2 vl;
int i;
mco_time tim;
uint4 u4;
Svalue sv;
char str[STRINGS_STEP* STRINGS_DIM + 10] =
{
0
};
for (;;)
{
if ((rc |= Rec_key_get(rec, &key)))
{
break;
}
if ((rc |= Rec_str_get(rec, str, sizeof(str), &len)))
{
break;
}
chksum = str_checksum(str, len);
if ((rc |= Rec_valuev_size(rec, &vl)))
{
break;
}
for (i = 0; i < vl; i++)
{
if ((rc |= Rec_valuev_at(rec, (uint2)i, &sv)))
{
break;
}
if ((rc |= Svalue_tm_get(&sv, &tim)))
{
break;
}
chksum += (17* tim) % 9003;
if ((rc |= Svalue_u4_get(&sv, &u4)))
{
break;
}
chksum += (17* u4) % 9003;
if ((rc |= Svalue_bytes_get(&sv, str, sizeof(str))))
{
break;
}
chksum += str_checksum(str, (uint2)strlen(str));
}
break;
}
if (rc)
{
return 0;
}
return chksum;
}
static int calculate_checksum(mco_db_h db)
{
MCO_RET rc;
mco_trans_h t;
mco_cursor_t csr;
Rec rec;
int sum = 0;
rc = mco_trans_start(db, MCO_READ_ONLY, MCO_TRANS_FOREGROUND, &t);
if (MCO_S_OK != rc)
{
printf("\nError starting trn\n");
goto Err;
}
Rec_tkey_index_cursor(t, &csr);
rc = mco_cursor_first(t, &csr);
while (rc == MCO_S_OK)
{
rc = Rec_from_cursor(t, &csr, &rec);
if (rc)
{
goto Err;
}
sum ^= record_checksum_byhandle(&rec);
rc = mco_cursor_next(t, &csr);
}
mco_trans_commit(t);
return sum;
Err: mco_trans_rollback(t);
return - 1;
}
// returns 0 if OK
static int connect_to_db(mco_db_h* pdb, int create_it)
{
MCO_RET rc;
if (create_it)
{
printf("\nCreating database instance\n");
// first, clean registry in NVRAM:
printf("\nCleaning registry:\n");
memset(REGISTRY_ADDRESS, REGISTRY_SIZE, 0);
printf("\nstart runtime\n");
mco_runtime_start(); // after cleaning nvram, not before!
printf("\nopen databasee\n");
rc = mco_db_open(dbName, nvram_db_get_dictionary(), DB_ADDRESS, DB_SIZE, (uint2)PAGESIZE);
if (rc)
{
printf("\nerror %d creating database", rc);
goto ErrExit;
}
// Initialize Checksum:
{
CheckSums* chk = (CheckSums*)CHECKSUM_ADDR;
chk->checksum_after_commit = 0;
chk->checksum_before_commit = 0;
printf("\nChecksums initialized (%d, %d)\n", chk->checksum_after_commit, chk->checksum_before_commit);
}
}
else
{
mco_runtime_start();
}
/* connect to the database, obtain a database handle */
rc = mco_db_connect(dbName, pdb);
if (rc)
{
printf("\nerror %d connecting database", rc);
goto ErrExit;
}
/* verify that current checksum equals to one of
the 2 possible stored in NVRAM @ CheckSums
*/
{
CheckSums* chk = (CheckSums*)CHECKSUM_ADDR;
int curr_sum = calculate_checksum(db);
if (curr_sum != chk->checksum_after_commit && curr_sum != chk->checksum_before_commit)
{
printf("\nFailed recovery !!!\n""\nChecksum is %d, expected %d or %d\n",
curr_sum, chk->checksum_after_commit, chk->checksum_before_commit);
goto ErrExit;
}
chk->checksum_after_commit = curr_sum;
}
return 0;
ErrExit: return - 1;
}
static int get_random_val(void)
{
/*
static int num = 3;
num = (num *19 + 25) % 3037;
return num;
*/
return rand();
}
static MCO_RET insertTrn(mco_db_h db)
{
MCO_RET rc;
mco_trans_h t;
Rec rec;
uint4 key;
char buf[100];
CheckSums* chk = (CheckSums*)CHECKSUM_ADDR;
int recsum;
uint2 buflen;
uint2 vl = 0, i;
Svalue sv;
char* str;
uint2 len;
// Insert 1 record
key = get_random_val() + idx;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -