Berkeley DB在Queue模式下的使用
Queue模式讀數據的一個簡單的示例
在Queue模式下讀數據,記錄(Dbt)要調用set_ulen函數和set_flags函數
#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 );
//直接用數據庫的讀函數
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 閱讀(1687) |
評論 (2) |
編輯 收藏
Berkeley DB在Queue模式下的使用
Queue模式下僅能存儲定長的記錄,既value的長度為定長。Queue的key是一個邏輯增長的數,一般就是int。
不需要開發者去改變這個類型。
Queue模式下只能存儲定長的記錄。所以一定要調用DB的set_re_length函數來設定數據庫中記錄的長度。
如果沒有設定,默認的為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 ) );
//直接用數據庫的寫函數
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模式下不能用游標進行數據的插入。只能進行數據的修改。
posted @
2007-05-29 18:03 walkspeed 閱讀(1983) |
評論 (7) |
編輯 收藏
Berkeley DB對并發的支持
要讓Berkeley DB數據支持并發,就要創建Berkeley DB的環境(environment)
環境類是 DbEnv。要支持并發,在初始化DbEnv時要用DB_INIT_CDB、DB_INIT_MPOOL
兩個標致。
如下
DbEnv env;
env.open( "evn", DB_INIT_CDB|DB_INIT_MPOOL, 0 );
然后在創建數據庫時,將環境傳給數據庫。如下
Db bdb( &env, 0 );
這樣就可以支持并發了。
Berkeley DB并發的簡單原則
Berkeley DB的并發遵循的是允許同時多個讀操作,當只有一個寫操作。
1 每個游標有一鎖,非游標的讀寫用一鎖
2 寫操作等待所有的讀鎖解鎖。
3 讀操作不需要等待寫鎖解鎖。
posted @
2007-05-26 16:17 walkspeed 閱讀(3003) |
評論 (2) |
編輯 收藏
Berkeley DB的訪問方法有四種BTree、Hash、Queue、Recno
他們在DB創建時選擇,而且只能在創建時選擇。一點選定某一個訪問方法,
在使用中不能改變。
BTree 數據被存儲在一個排序的平衡樹結構中。key和value都可以是簡單數
據(如整型,字符串),也可以是復雜數據(如結構)。當有多個數據的key
相同時,可以有復本。
Hash 數據存儲在一個擴展的線性hash表中。其他的特性象BTree。
Queue 數據存儲在一個隊列中,記錄是定長的。key為一個邏輯數,不由用戶
選擇類型。在尾部插入記錄,在頭部刪除記錄和取出記錄非常的快。提供了
記錄水平縮,提高在并發下的訪問。
Recno 數據可以是定常或是變長的記錄。其他特性象Queue。key也是一個邏輯數。
數據庫訪問方法的選擇。
根據key可否用戶定義分為BTree、Hash一組,Queue、Renco一組。
BTree與Hash之間的選擇
如果數據量不,能被放到內存中。這種情況下選擇BTree。即在小數據量的情況下
選用BTree,原因是在利用key來定為記錄時,成功的幾率大些。Hash有退步算法。
但是在大數據量的情況下,由于數據并不能都在數據庫中,要訪問磁盤,并且BTree
要維護的內部信息大于Hash,訪問磁盤的幾率大于Hash,會造成訪問的瓶頸。所以
在大數據量下選擇Hash。
Queue與Recno之間的選擇
用在多并發下最好用Queue。但是如果記錄是變長的,就只能選Recno了。在其它的情
況下,兩者沒有明顯的差別。
Berkeley DB支持從非常小的數據庫到256T的數據容量的數據庫。單個key或recode
最大可以為4G的數據。
Berkeley DB的數據庫被存儲為二進制的格式,有利于平臺的移植。
Berkeley DB支持并發的訪問,但是不能用在NSF(網絡文件系統)下。因為無法定位和
獲得數據庫的環境(在環境中設置對并發的控制)。
Berkeley DB的環境(Environments)提供了以下的功能
1 多數據庫文件(Multi-database files)。將多個數據存儲在一個物理文件中。
2 提供多線程或多進程的支持(Multi-thread and multi-process support)。
3 事務處理
4 高可用性(重復性)支持。即一個主數據庫,和多個提供只讀能力的復制數據庫
5 日志子系統。
posted @
2007-05-26 11:26 walkspeed 閱讀(3029) |
評論 (0) |
編輯 收藏
C++標準庫中用來計算時間差的函數
頭文件 < 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 閱讀(5858) |
評論 (0) |
編輯 收藏
C++標準庫中string類使用的注意。
在string類之間進行復制沒有什么問題。
但是要拷貝到內存中時就要注意。一定要在string取出的長度上加1。
如下
char buf[256];
std::string str = "1234567890";
memcpy( buf, str.c_str(), str.length()+1 );
這樣才能拷貝到字符串的結束符‘0’。要不就拷貝不到。
string的length函數只計算有效字符的長度。如同C中的strlen函數。
posted @
2007-05-25 14:47 walkspeed 閱讀(848) |
評論 (0) |
編輯 收藏
文件是一種資源。
流對象要依附與某個資源。
所以在C++標準庫中,流都是不可拷貝的和賦值的。
一個類有了流對象成員,那么它也就不可拷貝和賦值了。
如果進行了拷貝和賦值會出現運行時錯誤。
這也表現了一種設計范型。
資源只能在資源的使用者中保存其應用。并在資源的使用者環境中創建。
不同使用者之間只傳遞資源的描述,而不直接傳遞資源。
例如。
一個類要使用文件。
只傳遞給這個類文件的描述,如文件名,偏移量等等。
而不傳個他一個文件。
這個類再根據這些描述來開啟文件。對其操作。
posted @
2007-05-24 16:42 walkspeed 閱讀(503) |
評論 (0) |
編輯 收藏
tm結構中每個字段的解釋
tm結構中的每個段是一個int類型
tm_sec 秒鐘【0,59】
tm_min 分鐘【0,59】
tm_hour 小時【0,23】。是從午夜開始計時。UTC下是是以格林威治為標準0,local下是以本地時區為標準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 閱讀(3536) |
評論 (2) |
編輯 收藏
將tm結構的值轉換為一個time_t類型的值
在32位系統中time_t是一個long。
頭文件 <time.h>
time_t mktime(
struct tm *timeptr
);
__time32_t _mktime32(
struct tm *timeptr
);
__time64_t _mktime64(
struct tm *timeptr
);
獲得系統時間。
頭文件 <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
);
將時間轉換成一個字符串
是個安全的版本,用來替代上面的函數
頭文件 <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>
同上面函數的功能,是安全版本
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>
同上面函數的功能,是安全版本
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函數
頭文件 <time.h>
clock_t clock( void );
posted @
2007-05-22 10:00 walkspeed 閱讀(3046) |
評論 (0) |
編輯 收藏
輸入流的讀取多個字符的操作多用read。
read的定義形式如下
basic_istream& read( char_type *_Str, streamsize _Count );
char_type* 是流字符類型的指針,這個指針是用來存儲要讀取的字符
的位置。
streamsize 是存儲空間大小的類型,多位long。
重點在返回值的類型,是一個輸入流類型的應用。不是實際的讀取數據的長度。
要獲得實際的讀取長度要調用 gcount函數。定義如下
streamsize gcount( ) const;
要獲得當前讀取的位置要調用tellg函數。定義如下
pos_type tellg( );
想要知道以一共讀取了多少數據就可以用這個函數。
tellg會跳過格式符。即返回的位置是跳過控制符的。
這就是說幾個gcount的和不一定等于tellg的值。所以
用來確定讀取位置時一定要用tellg函數。而不能用
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;
}
讀取過程中可能會出現問題,流是不保證讀取過程的完整性。即要讀多少數據,
在對到這么多的數據后才返回。
這要求編程人員去判斷流的當前狀態。再進行下面的處理。
good函數知道當前狀態是好的。即上一個操作成功。可以進行下一個操作。
fail函數表示上一個操作失敗。但流還沒有完全破壞,可以進行一些處理。
bad函數表示流被破壞啦,別想了。不要在處理這個流拉。
eof函數表示已到流的尾部。不用再往下讀拉。不會讀出數據的。
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" );
//這是成立的。說明狀態并沒有應為文件的關閉而改變。只要這個對象
//的還活著,他的上一個狀態將保持。而起會對下面的操作產生影響。
//除非你清除或修改了狀態。
if( ifile.eof() )
{
ifile.close();
return -1;
}
ifile.close();
return 0;
}
posted @
2007-05-20 12:06 walkspeed 閱讀(885) |
評論 (0) |
編輯 收藏