📄 main.c
字号:
/***************************************************************
* *
* Copyright (c) 2001-2007 McObject LLC. All Right Reserved. *
* *
***************************************************************/
/*
* This sample demonstrate the use of eXtremeDB for the Routing Table Management software.
* The program measures the performance for routing table inserts and lookups. The program
* randomly generates IP addresses, each masked with three masks - 255.255.0.0, 255.255.255.0
* or 255.255.255.255. We then insert these routes into the routing table, creating a
* hash-based index based on the {mask/ip address} pair. The database engine filters out
* duplicate pairs of {mask/ip address} as the new routes are installed into the routing table.
* After the table is populated, the program searches for a route for a random packet using
* patricia index prefix match function.
*
* A somewhat detailed discussion of the routing table implementaion using eXtremeDB
* could be found in the whitepaper "The Role of In-Memory Database Systems in Routing
* Table Management in IP Routers" - http://mcobject.com/whitepapers.htm
*/
#include <platform.h>
#include <stdio.h>
#include <stdlib.h>
#include "rtdb.h"
static const char* dbname = "Route2";
static const int SEGSZ = 1024 * 1024 * 32UL;
#ifndef MCO_PLATFORM_X64
static const int PAGESIZE = 96;
#else
static const int PAGESIZE = 192;
#endif
const int MAP_ADDRESS = 0x20000000;
#define NROUTES 200000
#define NSEARCHES 500000
static const char* prtip(uint4 n);
const uint4 _mask[4] =
{
0xff000000, 0xffff0000, 0xffffff00, 0xffffffff
};
#define get_mask(nbits) _mask[(nbits/8)-1]
static uint1 calcNbits(uint4 mask)
{
static int n8[16] =
{
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
};
int rc = 0, i;
for (i = 0; i < 8; i++)
{
int halfbt = (mask >> (i << 2)) &15;
rc += n8[halfbt];
}
return (uint1)rc;
}
static void _SH_(void)
{
char text[] =
{
"\nThis sample demonstrate the use of eXtremeDB for the Routing Table\n"
"Management software.The program measures the performance for routing\n"
"randomly generates IP addresses, each masked with three masks - 255.255.0.0,\n"
"255.255.255.0 or 255.255.255.255. We then insert these routes into the\n"
"routing table.After the table is populated, the program searches for a route\n"
"for a random packet using patricia index prefix match function.\n"
};
char text1[] =
{
"Copyright (c) 2001-2007 McObject LLC. All Right Reserved.\n\n"
};
printf("%s\neXtremeDB runtime version %d.%d, build %d\n%s\n\nPress Enter to start", text, MCO_COMP_VER_MAJOR,
MCO_COMP_VER_MINOR, MCO_COMP_BUILD_NUM, text1);
getchar();
}
unsigned char* make_mask(uint4 val, uint2 bitnum)
{
static unsigned char _mask_[4];
int i;
val = val >> (32-bitnum);
memset(_mask_, 0, sizeof(_mask_));
for (i = 0; i < bitnum; i++, val = val >> 1)
{
_mask_[i >> 3] |= (val &1) << (i &7);
}
return _mask_;
}
uint4 make_uint(char* _mask_, uint2 bitnum)
{
uint4 val = 0;
int i;
for (i = 0; i < bitnum; i++)
{
val |= ((_mask_[i >> 3] >> (i &7)) &1) << i;
}
val = val << (32-bitnum);
return val;
}
/* Produces database memory report
*/
void showMem(mco_db_h db)
{
mco_puint freepg, totalpg;
mco_db_free_pages(db, &freepg);
mco_db_total_pages(db, &totalpg);
printf("\n\tMemory Report:\n\ttotal pages=%d (%dK)\n\tfree pages=%d (%dK)\n\tused %dK\n", totalpg, totalpg*
PAGESIZE / 1024, freepg, freepg* PAGESIZE / 1024, (totalpg - freepg)* PAGESIZE / 1024);
}
/* fatal error handler */
static void errhandler(int n)
{
printf("\neXtremeDB fatal error: %d", n);
getchar();
exit( - 1);
}
static MCO_RET addRoute(mco_db_h db, uint4 dest, uint4 mask, uint4 gatew, uint4 interf, uint2 weight)
{
MCO_RET rc;
mco_trans_h t;
Route rt;
uint1 nbit = ((calcNbits(mask) + 7) / 8)* 8;
rc = mco_trans_start(db, MCO_READ_WRITE, MCO_TRANS_FOREGROUND, &t);
if (rc)
{
return rc;
}
// add route:
rc = Route_new(t, &rt);
if (rc)
{
goto End;
}
// dest=dest>>(32-nbit);
Route_dest_alloc(&rt, nbit);
Route_dest_put_range(&rt, 0, nbit, (uint1*)make_mask(dest, nbit));
Route_gateway_put(&rt, gatew);
Route_interf_put(&rt, interf);
Route_metric_put(&rt, weight);
End: rc = mco_trans_commit(t);
return rc;
}
static uint4 genIP(void)
{
uint4 rc = 0x2A3B0000;
int rn = rand() | (rand() << 16);
rc |= rn &0xFFFFFF;
if (rn &0x01000000)
{
rc |= 0x0E000000; // ^= (rn & 0x0F000000);
}
return rc;
}
static uint4 genMask(uint4 ip)
{
int rn = rand() &15;
if (rn < 12)
{
return 0xFFFFFFFF;
}
if (rn < 15)
{
return 0xFFFFFF00;
}
return 0xFFFF0000;
}
static const char* prtip(uint4 n)
{
static char rc[100];
sprintf(rc, "%03d.%03d.%03d.%03d ", (n >> 24) &0xFF, (n >> 16) &0xFF, (n >> 8) &0xFF, n &0xFF);
return rc;
}
/* This is used to dump the content of the routing table into the file
* In oredr to use this, change the schema so, that the tree index is
* declared, and remove the #define DUMP_TABLE on the top of this file
*/
//#define DUMP_TABLE
static void dumpRoutingTable(mco_db_h db, const char* fnm)
{
#ifdef DUMP_TABLE
FILE* f = fopen(fnm, "w");
mco_cursor_t csr;
Route rt;
uint4 dest, gateway, interf;
uint2 blen;
mco_trans_h t;
MCO_RET rc;
unsigned char buf[4];
if (!f)
{
return ;
}
mco_trans_start(db, MCO_READ_WRITE, MCO_TRANS_FOREGROUND, &t);
Route_byDest_index_cursor(t, &csr);
for (rc = mco_cursor_first(t, &csr); rc == MCO_S_OK; rc = mco_cursor_next(t, &csr))
{
Route_from_cursor(t, &csr, &rt);
dest = 0;
Route_dest_size(&rt, &blen);
Route_dest_get_range(&rt, 0, blen, buf);
dest = make_uint(buf, blen);
Route_interf_get(&rt, &interf);
Route_gateway_get(&rt, &gateway);
fprintf(f, "%s", prtip(dest));
fprintf(f, "%s", prtip(get_mask(blen)));
fprintf(f, "%s", prtip(gateway));
fprintf(f, "%s", prtip(interf));
fprintf(f, "\n");
}
mco_trans_commit(t);
fclose(f);
#endif
}
/*
* searchRoute()
*/
static int searchRoute(mco_db_h db, uint4 ip, uint4* res_gatew, uint4* res_interf)
{
MCO_RET rc;
mco_cursor_t csr;
mco_trans_h t;
Route rt;
uint4 dest;
int ok = 0;
uint2 blen;
unsigned char buf[4];
rc = mco_trans_start(db, MCO_READ_ONLY, MCO_TRANS_FOREGROUND, &t);
if (rc)
{
return rc;
}
rc = Route_byDest_index_cursor(t, &csr);
if (rc)
{
return rc;
}
rc = Route_byDest_prefix_match(t, &csr, (uint1*)make_mask(ip, 32), 32);
if (rc == MCO_S_OK)
{
rc = Route_from_cursor(t, &csr, &rt);
if (rc)
{
return rc;
}
dest = 0;
rc = Route_dest_size(&rt, &blen);
if (rc)
{
return rc;
}
rc = Route_dest_get_range(&rt, 0, blen, (uint1*)buf);
if (rc)
{
return rc;
}
dest = make_uint(buf, blen);
if (dest == (ip &get_mask(blen)))
{
ok = 1;
}
}
else
{
printf("ip %s\n", prtip(ip));
}
rc = mco_trans_commit(t);
return ok;
}
static void dodo(mco_db_h db)
{
int j;
MCO_RET rc;
uint4 gway = genIP();
uint4 interf = genIP();
int nok = 0;
int nskipped = 0;
uint4 ip;
uint4 mask;
uint1 cycle = 0;
time_t t1, t2, t3, t4;
uint4 wasfound = 0;
printf("\nPopulating Routing Table with %d randomly generated routes\n", NROUTES);
Sleep(50);
time(&t1);
for (j = 0; j < NROUTES; j++)
{
cycle = 0;
ip = genIP();
mask = genMask(ip);
ip = ip &mask;
rc = addRoute(db, ip, mask, gway, interf, 1);
if (rc)
{
if (rc == MCO_S_DUPLICATE)
{
nskipped++;
}
else
{
printf("\nRoute add error: %d", rc);
break;
}
}
if (j % 5000 == 0)
{
printf(".");
}
}
time(&t2);
printf("\nAdded %d routes, %d duplicate routes rejected -- %d sec\n\n", j - nskipped, nskipped, t2 - t1);
Sleep(50);
showMem(db);
dumpRoutingTable(db, "rt.txt");
printf("\nLooking for a random IP %d times\n", NSEARCHES);
Sleep(50);
time(&t3);
for (j = 0; j < NSEARCHES; j++)
{
uint4 ip = genIP();
uint4 res_gatew, res_interf;
int ok = searchRoute(db, ip, &res_gatew, &res_interf);
if (ok)
{
nok++;
}
if (j % 5000 == 0)
{
printf(".");
}
}
time(&t4);
printf("\nSearched %d destinations -- %d sec -- %d succeeded\n\n", j, t4 - t3, nok);
}
int main(void)
{
MCO_RET rc;
mco_db_h db = 0;
char* start_mem;
mco_runtime_info_t info;
_SH_();
mco_get_runtime_info(&info);
if (info.mco_shm_supported)
{
start_mem = (char*)MAP_ADDRESS;
}
else
{
start_mem = (char*)malloc(SEGSZ);
if (!start_mem)
{
printf("Couldn't allocated memory\n");
exit(1);
}
};
/* set fatal error handler */
mco_error_set_handler(&errhandler);
rc = mco_runtime_start();
/* Create a database, using first memory segment */
rc = mco_db_open(dbname, rtdb_get_dictionary(), start_mem, SEGSZ, (uint2)PAGESIZE);
if (rc)
{
printf("\nerror creating database");
if (!info.mco_shm_supported)
{
free(start_mem);
}
exit(1);
}
/* connect to the database, obtain a database handle */
mco_db_connect(dbname, &db);
showMem(db);
dodo(db);
/* disconnect from the database, db is no longer valid */
mco_db_disconnect(db);
/* destroys the memory manager */
mco_db_close(dbname);
mco_runtime_stop();
if (!info.mco_shm_supported)
{
free(start_mem);
}
printf("press Enter to finish \n");
getchar();
PROG_EXIT(0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -