📄 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.
* The algorithm is a combination of a linear search and a tree search, masking the address with
* each of the three possible masks and then using the index to locate the route. Therefore each
* address is searched up to three times to find the best match. If more than one route exists,
* the one with the longest matching prefix is chosen.
*
* 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 = "Route1";
static const int SEGSZ = 1024 * 1024 * 16UL;
#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 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.The algorithm is a combination of a linear search and\n"
"a tree search, masking the address with each of the three possible masks and\n"
"then using the index to locate the route.\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();
}
/* 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 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 MCO_RET addRoute(mco_db_h db, uint4 dest, uint4 mask, uint4 gatew, uint4 interf, uint2 weight)
{
MCO_RET rc;
mco_trans_h t;
Mask hmask;
Route rt;
uint1 nbit = calcNbits(mask);
// mco_cursor_t csr;
rc = mco_trans_start(db, MCO_READ_WRITE, MCO_TRANS_FOREGROUND, &t);
if (rc)
{
return rc;
}
// add mask if need:
rc = Mask_all_find(t, nbit, mask, &hmask);
if (rc == MCO_S_NOTFOUND)
{
rc = Mask_new(t, &hmask);
if (rc)
{
goto End;
}
Mask_mask_put(&hmask, mask);
Mask_nbits_put(&hmask, nbit);
}
else
{
if (rc)
{
goto End;
}
}
// add route:
rc = Route_new(t, &rt);
if (rc)
{
goto End;
}
Route_dest_put(&rt, dest);
Route_mask_put(&rt, mask);
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) &255, (n >> 16) &255, (n >> 8) &255, (n) &255);
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 mask, dest, gateway, interf;
mco_trans_h t;
MCO_RET rc;
if (!f)
{
return ;
}
mco_trans_start(db, MCO_READ_WRITE, MCO_TRANS_FOREGROUND, &t);
Route_byMaskDest_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);
Route_dest_get(&rt, &dest);
Route_mask_get(&rt, &mask);
Route_interf_get(&rt, &interf);
Route_gateway_get(&rt, &gateway);
fprintf(f, "%s", prtip(dest));
fprintf(f, "%s", prtip(mask));
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;
Mask hmask;
uint4 mask;
mco_trans_h t;
int ok = 0;
rc = mco_trans_start(db, MCO_READ_ONLY, MCO_TRANS_FOREGROUND, &t);
if (rc)
{
return rc;
}
// scan all possible masks
rc = Mask_all_index_cursor(t, &csr);
if (rc)
{
goto End;
}
for (rc = mco_cursor_last(t, &csr); rc == MCO_S_OK; rc = mco_cursor_prev(t, &csr))
{
Route rt;
Mask_from_cursor(t, &csr, &hmask);
Mask_mask_get(&hmask, &mask);
rc = Route_byMaskDest_find(t, mask, mask &ip, &rt);
if (rc == MCO_S_OK)
{
ok = 1;
break;
}
}
End: 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;
time_t t1, t2, t3, t4;
printf("\nPopulating Routing Table with %d randomly generated routes\n", NROUTES);
Sleep(50);
time(&t1);
for (j = 0; j < NROUTES; j++)
{
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 + -