Berkeley DB在Queue模式下的使用
Queue模式讀數(shù)據(jù)的一個簡單的示例
在Queue模式下讀數(shù)據(jù),記錄(Dbt)要調用set_ulen函數(shù)和set_flags函數(shù)
#include < time.h >
#include < iostream >
#include < bdb/db_cxx.h >
struct ValueType
{
int _int;
char _char;
char _array[256];
};
void readDB( void )
{
Db bdb( 0, 0 );
bdb.set_re_len( sizeof( ValueType ) ); //用Queue模式一定要調用,而且一定要在open前調用
bdb.set_re_pad( 0x00 ); //為了字符串的填充為0。
bdb.open( 0, "SaveRecodeDB.db", 0, DB_QUEUE, DB_CREATE, 0 );
size_t k;
ValueType v;
Dbt key( &k, sizeof( size_t ) );
key.set_ulen( sizeof( size_t ) );
Dbt value( &v, sizeof( ValueType ) );
value.set_ulen( sizeof( ValueType ) );
value.set_flags( DB_DBT_USERMEM );
//直接用數(shù)據(jù)庫的讀函數(shù)
for( int i=0; i<1000000; ++i )
{
bdb.get( 0, &key, &value, DB_CONSUME );
}
bdb.close( 0 );
}
int main( int argc, char* argv[] )
{
clock_t et1 = clock();
readDB();
clock_t et2 = clock();
std::cout << "work is fine, " << "have times : " << et2 - et1 << std::endl;
return 0;
}
posted @
2007-05-30 13:58 walkspeed 閱讀(1707) |
評論 (2) |
編輯 收藏
Berkeley DB在Queue模式下的使用
Queue模式下僅能存儲定長的記錄,既value的長度為定長。Queue的key是一個邏輯增長的數(shù),一般就是int。
不需要開發(fā)者去改變這個類型。
Queue模式下只能存儲定長的記錄。所以一定要調用DB的set_re_length函數(shù)來設定數(shù)據(jù)庫中記錄的長度。
如果沒有設定,默認的為0。這樣當存儲記錄時一定會報異常。程序出錯。
在讀取記錄時,當記錄的長度小于設定的長度時,會填充字符達到設定長度。
默認的字符為0x02(ASCII中的)。可以設定自己的填充字符。調用DB的set_re_pad。
一個簡單的示例
#include < time.h >
#include < iostream >
#include < bdb/db_cxx.h >
struct ValueType
{
int _int;
char _char;
char _array[256];
};
void writeDB( void )
{
Db bdb( 0, 0 );
bdb.set_re_len( sizeof( ValueType ) ); //用Queue模式一定要調用,而且一定要在open前調用
bdb.set_re_pad( 0x00 ); //為了字符串的填充為0。
bdb.open( 0, "SaveRecodeDB.db", 0, DB_QUEUE, DB_CREATE, 0 );
size_t k;
ValueType v;
Dbt key( &k, sizeof( size_t ) );
Dbt value( &v, sizeof( ValueType ) );
//直接用數(shù)據(jù)庫的寫函數(shù)
for( int i=0; i<1000000; ++i )
{
bdb.put( 0, &key, &value, DB_APPEND );
}
bdb.close( 0 );
}
int main( int argc, char* argv[] )
{
clock_t et1 = clock();
writeDB();
clock_t et2 = clock();
std::cout << "work is fine, " << "have times : " << et2 - et1 << std::endl;
return 0;
}
在Queue模式下不能用游標進行數(shù)據(jù)的插入。只能進行數(shù)據(jù)的修改。
posted @
2007-05-29 18:03 walkspeed 閱讀(2007) |
評論 (7) |
編輯 收藏
Berkeley DB對并發(fā)的支持
要讓Berkeley DB數(shù)據(jù)支持并發(fā),就要創(chuàng)建Berkeley DB的環(huán)境(environment)
環(huán)境類是 DbEnv。要支持并發(fā),在初始化DbEnv時要用DB_INIT_CDB、DB_INIT_MPOOL
兩個標致。
如下
DbEnv env;
env.open( "evn", DB_INIT_CDB|DB_INIT_MPOOL, 0 );
然后在創(chuàng)建數(shù)據(jù)庫時,將環(huán)境傳給數(shù)據(jù)庫。如下
Db bdb( &env, 0 );
這樣就可以支持并發(fā)了。
Berkeley DB并發(fā)的簡單原則
Berkeley DB的并發(fā)遵循的是允許同時多個讀操作,當只有一個寫操作。
1 每個游標有一鎖,非游標的讀寫用一鎖
2 寫操作等待所有的讀鎖解鎖。
3 讀操作不需要等待寫鎖解鎖。
posted @
2007-05-26 16:17 walkspeed 閱讀(3022) |
評論 (2) |
編輯 收藏
Berkeley DB的訪問方法有四種BTree、Hash、Queue、Recno
他們在DB創(chuàng)建時選擇,而且只能在創(chuàng)建時選擇。一點選定某一個訪問方法,
在使用中不能改變。
BTree 數(shù)據(jù)被存儲在一個排序的平衡樹結構中。key和value都可以是簡單數(shù)
據(jù)(如整型,字符串),也可以是復雜數(shù)據(jù)(如結構)。當有多個數(shù)據(jù)的key
相同時,可以有復本。
Hash 數(shù)據(jù)存儲在一個擴展的線性hash表中。其他的特性象BTree。
Queue 數(shù)據(jù)存儲在一個隊列中,記錄是定長的。key為一個邏輯數(shù),不由用戶
選擇類型。在尾部插入記錄,在頭部刪除記錄和取出記錄非常的快。提供了
記錄水平縮,提高在并發(fā)下的訪問。
Recno 數(shù)據(jù)可以是定常或是變長的記錄。其他特性象Queue。key也是一個邏輯數(shù)。
數(shù)據(jù)庫訪問方法的選擇。
根據(jù)key可否用戶定義分為BTree、Hash一組,Queue、Renco一組。
BTree與Hash之間的選擇
如果數(shù)據(jù)量不,能被放到內存中。這種情況下選擇BTree。即在小數(shù)據(jù)量的情況下
選用BTree,原因是在利用key來定為記錄時,成功的幾率大些。Hash有退步算法。
但是在大數(shù)據(jù)量的情況下,由于數(shù)據(jù)并不能都在數(shù)據(jù)庫中,要訪問磁盤,并且BTree
要維護的內部信息大于Hash,訪問磁盤的幾率大于Hash,會造成訪問的瓶頸。所以
在大數(shù)據(jù)量下選擇Hash。
Queue與Recno之間的選擇
用在多并發(fā)下最好用Queue。但是如果記錄是變長的,就只能選Recno了。在其它的情
況下,兩者沒有明顯的差別。
Berkeley DB支持從非常小的數(shù)據(jù)庫到256T的數(shù)據(jù)容量的數(shù)據(jù)庫。單個key或recode
最大可以為4G的數(shù)據(jù)。
Berkeley DB的數(shù)據(jù)庫被存儲為二進制的格式,有利于平臺的移植。
Berkeley DB支持并發(fā)的訪問,但是不能用在NSF(網絡文件系統(tǒng))下。因為無法定位和
獲得數(shù)據(jù)庫的環(huán)境(在環(huán)境中設置對并發(fā)的控制)。
Berkeley DB的環(huán)境(Environments)提供了以下的功能
1 多數(shù)據(jù)庫文件(Multi-database files)。將多個數(shù)據(jù)存儲在一個物理文件中。
2 提供多線程或多進程的支持(Multi-thread and multi-process support)。
3 事務處理
4 高可用性(重復性)支持。即一個主數(shù)據(jù)庫,和多個提供只讀能力的復制數(shù)據(jù)庫
5 日志子系統(tǒng)。
posted @
2007-05-26 11:26 walkspeed 閱讀(3048) |
評論 (0) |
編輯 收藏
C++標準庫中用來計算時間差的函數(shù)
頭文件 < time.h >
double difftime(
time_t timer1,
time_t timer0
);
double _difftime32(
__time32_t timer1,
__time32_t timer0
);
double _difftime64(
__time64_t timer1,
__time64_t timer0
);
C++標準庫用來格式化輸出時間字符串
頭文件 < time.h >
size_t strftime(
char *strDest,
size_t maxsize,
const char *format,
const struct tm *timeptr
);
size_t _strftime_l(
char *strDest,
size_t maxsize,
const char *format,
const struct tm *timeptr,
_locale_t locale
);
size_t wcsftime(
wchar_t *strDest,
size_t maxsize,
const wchar_t *format,
const struct tm *timeptr
);
size_t _wcsftime_l(
wchar_t *strDest,
size_t maxsize,
const wchar_t *format,
const struct tm *timeptr,
_locale_t locale
);
The formatting codes for strftime are listed below:
%a
Abbreviated weekday name
%A
Full weekday name
%b
Abbreviated month name
%B
Full month name
%c
Date and time representation appropriate for locale
%d
Day of month as decimal number (01 – 31)
%H
Hour in 24-hour format (00 – 23)
%I
Hour in 12-hour format (01 – 12)
%j
Day of year as decimal number (001 – 366)
%m
Month as decimal number (01 – 12)
%M
Minute as decimal number (00 – 59)
%p
Current locale's A.M./P.M. indicator for 12-hour clock
%S
Second as decimal number (00 – 59)
%U
Week of year as decimal number, with Sunday as first day of week (00 – 53)
%w
Weekday as decimal number (0 – 6; Sunday is 0)
%W
Week of year as decimal number, with Monday as first day of week (00 – 53)
%x
Date representation for current locale
%X
Time representation for current locale
%y
Year without century, as decimal number (00 – 99)
%Y
Year with century, as decimal number
%z, %Z
Either the time-zone name or time zone abbreviation, depending on registry settings; no characters if time zone is unknown
%%
Percent sign
posted @
2007-05-25 15:30 walkspeed 閱讀(5874) |
評論 (0) |
編輯 收藏
C++標準庫中string類使用的注意。
在string類之間進行復制沒有什么問題。
但是要拷貝到內存中時就要注意。一定要在string取出的長度上加1。
如下
char buf[256];
std::string str = "1234567890";
memcpy( buf, str.c_str(), str.length()+1 );
這樣才能拷貝到字符串的結束符‘0’。要不就拷貝不到。
string的length函數(shù)只計算有效字符的長度。如同C中的strlen函數(shù)。
posted @
2007-05-25 14:47 walkspeed 閱讀(860) |
評論 (0) |
編輯 收藏
文件是一種資源。
流對象要依附與某個資源。
所以在C++標準庫中,流都是不可拷貝的和賦值的。
一個類有了流對象成員,那么它也就不可拷貝和賦值了。
如果進行了拷貝和賦值會出現(xiàn)運行時錯誤。
這也表現(xiàn)了一種設計范型。
資源只能在資源的使用者中保存其應用。并在資源的使用者環(huán)境中創(chuàng)建。
不同使用者之間只傳遞資源的描述,而不直接傳遞資源。
例如。
一個類要使用文件。
只傳遞給這個類文件的描述,如文件名,偏移量等等。
而不傳個他一個文件。
這個類再根據(jù)這些描述來開啟文件。對其操作。
posted @
2007-05-24 16:42 walkspeed 閱讀(517) |
評論 (0) |
編輯 收藏
tm結構中每個字段的解釋
tm結構中的每個段是一個int類型
tm_sec 秒鐘【0,59】
tm_min 分鐘【0,59】
tm_hour 小時【0,23】。是從午夜開始計時。UTC下是是以格林威治為標準0,local下是以本地時區(qū)為標準0.
gmtime返回的是UTC,localtime返回的是本地。
tm_mon 月份【0,11】。注意是0到11.而不是常用的1到12.
tm_year 年份。是從1900年開始計算。即記錄的是本年與1900年的差值。
tm_wday 表示在一個星期中的第幾天【0,6】
tm_yday 表示一年中的第幾天【0,365】,1月1日為0
tm_isdst 不清楚,文檔中只是說在gmtime下為0
posted @
2007-05-23 12:02 walkspeed 閱讀(3588) |
評論 (2) |
編輯 收藏
將tm結構的值轉換為一個time_t類型的值
在32位系統(tǒng)中time_t是一個long。
頭文件 <time.h>
time_t mktime(
struct tm *timeptr
);
__time32_t _mktime32(
struct tm *timeptr
);
__time64_t _mktime64(
struct tm *timeptr
);
獲得系統(tǒng)時間。
頭文件 <time.h>
In Visual C++ 2005, time is a wrapper for _time64 and time_t is, by default, equivalent to __time64_t.
If you need to force the compiler to interpret time_t as the old 32-bit time_t, you can define _USE_32BIT_TIME_T.
This is not recommended because your application may fail after January 18, 2038; the use of this macro is not allowed on 64-bit platforms.
time_t time(
time_t *timer
);
__time32_t _time32(
__time32_t *timer
);
__time64_t _time64(
__time64_t *timer
);
將時間轉換成一個字符串
頭文件 <time.h>
char *ctime(
const time_t *timer
);
char *_ctime32(
const __time32_t *timer )
;
char *_ctime64(
const __time64_t *timer )
;
wchar_t *_wctime(
const time_t *timer
);
wchar_t *_wctime32(
const __time32_t *timer
);
wchar_t *_wctime64(
const __time64_t *timer
);
將時間轉換成一個字符串
是個安全的版本,用來替代上面的函數(shù)
頭文件 <time.h>
errno_t ctime_s(
char* buffer,
size_t sizeInBytes,
const time_t *time
);
errno_t _ctime32_s(
char* buffer,
size_t sizeInBytes,
const __time32_t *time
);
errno_t _ctime64_s(
char* buffer,
size_t sizeInBytes,
const __time64_t *time )
;
errno_t _wctime_s(
wchar_t* buffer,
size_t sizeInWords,
const time_t *time
);
errno_t _wctime32_s(
wchar_t* buffer,
size_t sizeInWords,
const __time32_t *time
);
errno_t _wctime64_s(
wchar_t* buffer,
size_t sizeInWords,
const __time64_t *time
);
template <size_t size>
errno_t _ctime32_s(
char (&buffer)[size],
const __time32_t *time
); // C++ only
template <size_t size>
errno_t _ctime64_s(
char (&buffer)[size],
const __time64_t *time
); // C++ only
template <size_t size>
errno_t _wctime32_s(
wchar_t (&buffer)[size],
const __time32_t *time
); // C++ only
template <size_t size>
errno_t _wctime64_s(
wchar_t (&buffer)[size],
const __time64_t *time
); // C++ only
將時間值轉換成一個結構
頭文件 <time.h>
struct tm *gmtime(
const time_t *timer
);
struct tm *_gmtime32(
const time32_t *timer
);
struct tm *_gmtime64(
const __time64_t *timer
);
將時間值轉換成一個結構
頭文件 <time.h>
同上面函數(shù)的功能,是安全版本
errno_t _gmtime_s(
struct tm* _tm,
const __time_t* time
);
errno_t _gmtime32_s(
struct tm* _tm,
const __time32_t* time
);
errno_t _gmtime64_s(
struct tm* _tm,
const __time64_t* time
);
將時間轉換成本地時間。
頭文件 <time.h>
struct tm *localtime(
const time_t *timer
);
struct tm *_localtime32(
const __time32_t *timer
);
struct tm *_localtime64(
const __time64_t *timer
);
將時間轉換成本地時間。
頭文件 <time.h>
同上面函數(shù)的功能,是安全版本
errno_t _localtime_s(
struct tm* _tm,
const time_t *time
);
errno_t _localtime32_s(
struct tm* _tm,
const time32_t *time
);
errno_t _localtime64_s(
struct tm* _tm,
const _time64_t *time
);
clock函數(shù)
頭文件 <time.h>
clock_t clock( void );
posted @
2007-05-22 10:00 walkspeed 閱讀(3059) |
評論 (0) |
編輯 收藏
輸入流的讀取多個字符的操作多用read。
read的定義形式如下
basic_istream& read( char_type *_Str, streamsize _Count );
char_type* 是流字符類型的指針,這個指針是用來存儲要讀取的字符
的位置。
streamsize 是存儲空間大小的類型,多位long。
重點在返回值的類型,是一個輸入流類型的應用。不是實際的讀取數(shù)據(jù)的長度。
要獲得實際的讀取長度要調用 gcount函數(shù)。定義如下
streamsize gcount( ) const;
要獲得當前讀取的位置要調用tellg函數(shù)。定義如下
pos_type tellg( );
想要知道以一共讀取了多少數(shù)據(jù)就可以用這個函數(shù)。
tellg會跳過格式符。即返回的位置是跳過控制符的。
這就是說幾個gcount的和不一定等于tellg的值。所以
用來確定讀取位置時一定要用tellg函數(shù)。而不能用
gcount的和,在偏移,這會產生不對的位置。
看下面的例子
int main( int argc, char* argv[] )
{
std::ifstream ifile;
char buf[10];
ifile.open( "example.txt" ); //examplet.txt文件中每行有一個回車符
ifile.read( buf, 10 );
size_t size = ifile.tellg(); //size為11
size = ifile.gcount(); //size為10
ifile.read( buf, 10 );
size = ifile.tellg(); //size為22
size = ifile.gcount(); //size為10
if( ifile.eof() )
{
return -1;
}
ifile.close();
return 0;
}
讀取過程中可能會出現(xiàn)問題,流是不保證讀取過程的完整性。即要讀多少數(shù)據(jù),
在對到這么多的數(shù)據(jù)后才返回。
這要求編程人員去判斷流的當前狀態(tài)。再進行下面的處理。
good函數(shù)知道當前狀態(tài)是好的。即上一個操作成功。可以進行下一個操作。
fail函數(shù)表示上一個操作失敗。但流還沒有完全破壞,可以進行一些處理。
bad函數(shù)表示流被破壞啦,別想了。不要在處理這個流拉。
eof函數(shù)表示已到流的尾部。不用再往下讀拉。不會讀出數(shù)據(jù)的。
int main( int argc, char* argv[] )
{
std::ifstream ifile;
char buf[10];
ifile.open( "example.txt" ); //examplet.txt文件中每行有一個回車符
ifile.seekg( 0, ios::end );
ifile.close();
ifile.open( "example.txt" );
//這是成立的。說明狀態(tài)并沒有應為文件的關閉而改變。只要這個對象
//的還活著,他的上一個狀態(tài)將保持。而起會對下面的操作產生影響。
//除非你清除或修改了狀態(tài)。
if( ifile.eof() )
{
ifile.close();
return -1;
}
ifile.close();
return 0;
}
posted @
2007-05-20 12:06 walkspeed 閱讀(898) |
評論 (0) |
編輯 收藏