posts - 58,  comments - 75,  trackbacks - 0
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 阅读(1673) | 评论 (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 阅读(1962) | 评论 (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 阅读(2980) | 评论 (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 阅读(3010) | 评论 (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 阅读(5843) | 评论 (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 阅读(836) | 评论 (0)编辑 收藏
文件是一种资源。
流对象要依附与某个资源。

所以在C++标准库中,流都是不可拷贝的和赋值的。
一个类有了流对象成员,那么它也就不可拷贝和赋值了。
如果进行了拷贝和赋值会出现运行时错误。

这也表现了一种设计范型。
资源只能在资源的使用者中保存其应用。并在资源的使用者环境中创建。
不同使用者之间只传递资源的描述,而不直接传递资源。

例如。
一个类要使用文件。
只传递给这个类文件的描述,如文件名,偏移量等等。
而不传个他一个文件。

这个类再根据这些描述来开启文件。对其操作。
posted @ 2007-05-24 16:42 walkspeed 阅读(493) | 评论 (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 阅读(3422) | 评论 (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 阅读(3035) | 评论 (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 阅读(872) | 评论 (0)编辑 收藏
仅列出标题
共6页: 1 2 3 4 5 6 

<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

常用链接

留言簿(4)

随笔分类(64)

随笔档案(58)

文章分类(3)

文章档案(3)

相册

收藏夹(9)

C++零碎

好友

搜索

  •  

积分与排名

  • 积分 - 159657
  • 排名 - 163

最新评论

阅读排行榜

评论排行榜