最便捷的序列化方式

Spring与Redis集成-配置连接工厂、序列化方式、RedisTemplate Spring框架通过Spring Data Redis项目提供了对Redis的全面支持。Spring Data Redis简化了Redis的使用,使得开发者能够使用熟悉的Spring编程模型与Redis进行交互。连接管理:通过连接工厂管理Redis连接。数据访问:通过RedisTemplate和StringRedisTemplate提供高层次的数据访问接口。缓存支持:通过Spring Cache抽象集成Redis作为缓存提供者。消息发布/订阅:支持Redis的发布/订阅模式。 阅读详情
 

最便捷、最强大、速度最快的C++序列化框架。

 

特别注意:vc6太古老,不符合C++规范,无法使用该框架

 

1.         高性能,速度非常快,比你能找到的同类产品至少快一个数量级

2.         在网络通讯,数据库存储中非常好用。

3.         预先支持所有基本类型,所有stl容器类型(除stack/queue之外)

4.         支持变长int32/uint32/int64/uint64

5.         支持stl::pair,boost::tuple

6.         可选的版本控制,而非强制

a)         对于小对象,通常不需要版本控制

b)         boost::serialization的版本号是强制的,当初我设计这个序列化框架就是因为boost不能省略版本号

7.         非侵入式设计,不污染名字空间

8.         声明式语法,简单,可靠

9.         …….

 

该框架的易用性

还是用代码说明问题最简洁,看这个例子:

 

struct MyData1

{

    int  a, b, c;

    var_int32_t d;  // d.t is int32 value

    var_uint64_t e; // d.t is uint64 value

    std::string f;

    std::map<std::string, int> g;

    std::set<int> h;

 

    // 声明序列化,无版本控制,最简洁的声明,后面几个稍微复杂点

    DATA_IO_LOAD_SAVE(MyData1, &a&b&c&d&e&f&g&h)

};

 

struct MyData2

{

    int  a, b, c;

    var_int32_t d;

    var_uint64_t e;

    std::string f;

    std::map<std::string, int> g;

    std::set<int> h;

 

    // 声明序列化,有版本控制

    DATA_IO_LOAD_SAVE_V(MyData2,

        1, // 当前版本

        &a&b&c&d&e&f&g&h

        )

};

 

struct MyData3

{

    int  a, b, c;

    boost::int32_t d;

    boost::uint64_t e;

    std::string f;

    std::map<std::string, int> g;

    std::set<int> h;

    std::multiset<int> i;

 

    unsigned version;

 

    // 声明序列化,有版本控制

    DATA_IO_LOAD_SAVE_V(MyData3,

        2, // 当前版本

        &a

        &b

        &c

        &as_var_int(d) // d 声明为int32_t, 但是作为var_int32_t 来存储

        &as_var_int(e) // e 声明为uint64_t, 但是作为var_uint64_t 来存储

        &f

        &g

        &h

        &vmg.since(2, i) // 版本2 新增了成员i

        &vmg.get_version(version) // 如果需要,将版本值存入version 成员

        )

};

 

int main(int argc, char* argv[])

{

    PortableDataOutput<AutoGrownMemIO> output;

    PortableDataInput<MemIO> input;

 

    output.resize(1024); // 可选,如果没有这一行最多就是多拷贝几次内存,相当于使用vector.reserve

 

    MyData1 d1;

    // set d1 values

    // ...

 

    MyData2 d2;

    // set d2 values

    // ...

 

    MyData3 d3;

    // set d3 values

    // ...

 

    output << d1 << d2 << d3; // 存储

 

    input.set(output.begin(), output.current());

 

    input >> d1 >> d2 >> d3; // 载入

 

//----------------------------------

 

// operator& 与operator<< 等效

    output & d1 & d2 & d3; // 存储

 

    input.set(output.begin(), output.current());

 

// operator& 与operator>> 等效

    input & d1 & d2 & d3; // 载入

}

 

模仿这段代码,可以完成大部分的现实需求,如果有更多的需求,可以使用该框架的高级功能。例如,系统中已经定义了一些数据结构,但又不能修改现有代码,怎样给它们增加序列化能力呢?请看如下代码:

 

// in system header, can not change

struct SysData1

{

    int a;

    unsigned b;

    string c;

};

 

// add these 2 function in your header

template<class DataIO>

void DataIO_saveObject(DataIO& dio, const SysData1& x)

{

    dio & x.a & x.b & x.c;

}

template<class DataIO>

void DataIO_loadObject(DataIO& dio, SysData1& x)

{

    dio & x.a & x.b & x.c;

}

 

如果现存的对象需要版本控制,参考如下代码:

 

struct SysData2

{

    int a;

    unsigned b;

    string c;

};

 

// add these 2 function in your header

template<class DataIO>

void DataIO_saveObject(DataIO& dio, const SysData2& x)

{

    const unsigned curr_version = 2;

    dio & serialize_version_t(curr_version);

    dio & x.a & x.b;

    dio & x.c;

}

template<class DataIO>

void DataIO_loadObject(DataIO& dio, SysData2& x)

{

    const unsigned curr_version = 2;

    serialize_version_t loaded_version;

    in >> loaded_version;

    if (loaded_version.t > curr_version)

    {

        throw BadVersionException(loaded_version.t, curr_version, className);

    }

    dio & x.a & x.b;

    if (loaded_version.t >= 2)

        dio & x.c;

}

 

 

 

DataIO_loadObject/DataIO_saveObject只要在调用点可见,就可以对SysData进行序列化。

因为DataIO 序列化框架使用DataIO_loadObject/DataIO_saveObject来载入和存储对象,这样做的好处有以下几点:

l  非侵入,对象类型和加载/存储函数可以分离定义

n   否则无法为不可更改代码的对象增加序列化能力

l  这两个函数可以定义在任何名字空间

n   根据C++的名字查找规则,只要在调用环境和每个参数所在的名字空间中有相应的匹配函数,就会使用该函数。我们需要有效地利用这一点。

l  DataIO_loadObject/DataIO_saveObject这两个函数名较长,并且罕见

n   因此不会与系统中的其他标识符发生冲突。(对比boost::serialization中的serialize函数,它就比较容易和其他名字发生冲突,serialize太常见了)。

 

性能

在上面的代码中可以看到几个陌生的名字:MemIO, AutoGrownMemIO,PortableDataOutput,PortableDataInput…

代码中没有提到MinMemIO,因为MinMemIO没有越界检查,只有在非常简单,完全可控的情况下,才能使用它。因为没有越界检查,它的性能非常好,在大多数情况下相当于手工的memcpy序列化。

使用MemIO稍微慢一点,但是有越界检查,读取时越界会抛出EndOfFileException异常,写入越界时会抛出OutOfSpaceException异常。

使用AutoGrownMemIO,在save时,碰到边界会自动增加内存(相当于vector.push_back自动增加内存),也可以使用resize预先分配内存(相当于vector.reserve/resize)。

这个几个MemIO类都非常简单,速度快是很自然的。

在PortableDataOutput,PortableDataInput中,如果机器字节序是LittleEndian,需要交换字节序,这一点,在新版的vc中和gcc中,会直接映射到一条指令:bswap。所以也不会有性能问题。

对于var_int的存储,无符号数,每个字节包含7个有效位,余下一位表示是否需要读取下一个字节。因此0~127仅需要一个字节,0~2^14-1需要两个字节,等等。对于有符号数,最低有效位存储符号,其余位存储绝对值。所有stl容器和string的尺寸就是用var_uint32_t存储的。

该框架中,同时实现了StreamBuffer,可以为任意Stream增加一层缓冲,往缓冲里面序列化数据的效率和MemIO系列是一样的,不同之处在于当缓冲耗尽或填满时会调用真实Stream的读写方法。这比起通常很多实现中将BufferedStream作为一个抽象,在读取哪怕一个字节时也需要一个虚函数调用,速度要快得多。

扩展应用

使用该序列化框架,我实现了一个不需要IDL的RPC。

使用该序列化框架,对Berkeley DB进行包装,可以让它象标准容器一样使用,免除了复杂的编码。后面我会继续介绍。

=================================================================

=================================================================

 

使用前面介绍的序列化框架,可以非常简单地将Bekeley DB作为存储层,实现一个易于使用的,强类型的,持久化的map。

 

这个设计的的基本原则就是:模板作为一个薄的、类型安全的包装层,实现层的代码可以多个模板实例来公用,这样不但加快了编译时间,也减小了生成的代码尺寸。

这个实现相当于std::map<Key,Data>,但接口上也不完全相同,主要是基于易实现和性能考虑。

下一篇介绍std::map<Key1,std::map<Key2,Data> >的BerkeleyDB实现。

 

 多的不说,贴上代码。

 

file: dbmap.h

 

 

 

  1. /* vim: set tabstop=4 : */
  2. #ifndef __febird_bdb_dbmap_h__
  3. #define __febird_bdb_dbmap_h__
  4. #if defined(_MSC_VER) && (_MSC_VER >= 1020)
  5. # pragma once
  6. #endif
  7. #include <db_cxx.h>
  8. #include "native_compare.h"
  9. #include "../io/DataIO.h"
  10. #include "../io/MemStream.h"
  11. #include "../refcount.h"
  12. namespace febird {
  13. class FEBIRD_DLL_EXPORT dbmap_iterator_impl_base : public RefCounter
  14. {
  15. public:
  16.     class dbmap_base* m_owner;
  17.     DBC*  m_curp;
  18.     int   m_ret;
  19. public:
  20.     dbmap_iterator_impl_base(class dbmap_base* owner);
  21.     void init(DB* dbp, DB_TXN* txn, const char* func);
  22.     virtual ~dbmap_iterator_impl_base();
  23.     virtual void load_key(void* data, size_t size) = 0;
  24.     virtual void load_val(void* data, size_t size) = 0;
  25.     virtual void save_key(PortableDataOutput<AutoGrownMemIO>& oKey) = 0;
  26.     void advance(u_int32_t direction_flag, const char* func);
  27.     void update(const void* d, const char* func);
  28.     void remove(const char* func);
  29. };
  30. class FEBIRD_DLL_EXPORT dbmap_base
  31. {
  32.     DECLARE_NONE_COPYABLE_CLASS(dbmap_base)
  33. public:
  34.     DB*    m_db;
  35.     size_t m_bulkSize;
  36.     bt_compare_fcn_type m_bt_comp;
  37.     dbmap_base(DB_ENV* env, const char* dbname
  38.         , DB_TXN* txn
  39.         , bt_compare_fcn_type bt_comp
  40.         , const char* func
  41.         );
  42.     virtual ~dbmap_base();
  43.     virtual void save_key(PortableDataOutput<AutoGrownMemIO>& dio, const void* key) const = 0;
  44.     virtual void save_val(PortableDataOutput<AutoGrownMemIO>& dio, const void* data) const = 0;
  45.     virtual dbmap_iterator_impl_base* make_iter() = 0;
  46.     dbmap_iterator_impl_base* begin_impl(DB_TXN* txn, const char* func);
  47.     dbmap_iterator_impl_base* end_impl(DB_TXN* txn, const char* func);
  48.     dbmap_iterator_impl_base* find_impl(const void* k, DB_TXN* txn, u_int32_t flags, const char* func);
  49.     bool insert_impl(const void* k, const void* d, u_int32_t flags, DB_TXN* txn, const char* func);
  50.     bool remove_impl(const void* k, DB_TXN* txn, const char* func);
  51.     void clear_impl(DB_TXN* txn, const char* func);
  52. };
  53. template<class Key, class Val, class Value, class Impl>
  54. class dbmap_iterator :
  55.     public std::iterator<std::bidirectional_iterator_tag, Value, ptrdiff_t, const Value*, const Value&>
  56. {
  57.     boost::intrusive_ptr<Impl> m_impl;
  58.     void copy_on_write()
  59.     {
  60.         if (m_impl->getRefCount() > 1)
  61.         {
  62.             Impl* p = new Impl(m_impl->m_owner);
  63.             m_impl->m_ret = m_impl->m_curp->dup(m_impl->m_curp, &p->m_curp, DB_POSITION);
  64.             FEBIRD_RT_assert(0 == m_impl->m_ret, std::runtime_error);
  65.             m_impl.reset(p);
  66.         }
  67.     }
  68. private:
  69. #ifdef _MSC_VER
  70. //# pragma warning(disable: 4661) // declaration but not definition
  71. //! MSVC will warning C4661 "declaration but not definition"
  72. void operator++(int) { assert(0); }
  73. void operator--(int) { assert(0); }
  74. #else
  75. //! disable, because clone iterator will cause very much time and resource
  76. void operator++(int);// { assert(0); }
  77. void operator--(int);// { assert(0); }
  78. #endif
  79. public:
  80.     dbmap_iterator() {}
  81.     explicit dbmap_iterator(dbmap_iterator_impl_base* impl)
  82.         : m_impl(static_cast<Impl*>(impl))
  83.     {
  84.         assert(impl);
  85.         assert(dynamic_cast<Impl*>(impl));
  86.     }
  87. //  bool exist() const { return DB_NOTFOUND != m_impl->m_ret && DB_KEYEMPTY != m_impl->m_ret; }
  88.     bool exist() const { return 0 == m_impl->m_ret; }
  89.     void update(const Val& val) { m_impl->update(&val, BOOST_CURRENT_FUNCTION); }
  90.     void remove() { m_impl->remove(BOOST_CURRENT_FUNCTION); }
  91.     dbmap_iterator& operator++()
  92.     {
  93.         assert(0 == m_impl->m_ret);
  94.         copy_on_write();
  95.         m_impl->advance(DB_NEXT, BOOST_CURRENT_FUNCTION);
  96.         return *this;
  97.     }
  98.     dbmap_iterator& operator--()
  99.     {
  100.         assert(0 == m_impl->m_ret);
  101.         copy_on_write();
  102.         m_impl->advance(DB_PREV, BOOST_CURRENT_FUNCTION);
  103.         return *this;
  104.     }
  105.     const Value& operator*() const
  106.     {
  107.         assert(0 == m_impl->m_ret);
  108.         return m_impl->m_val;
  109.     }
  110.     const Value* operator->() const
  111.     {
  112.         assert(0 == m_impl->m_ret);
  113.         return &m_impl->m_val;
  114.     }
  115.     Value& get_mutable() const
  116.     {
  117.         assert(0 == m_impl->m_ret);
  118.         return m_impl->m_val;
  119.     }
  120. };
  121. template<class Key, class Val>
  122. class dbmap : protected dbmap_base
  123. {
  124.     DECLARE_NONE_COPYABLE_CLASS(dbmap)
  125. public:
  126.     typedef Key     key_type;
  127.     typedef std::pair<Key, Val> value_type;
  128. protected:
  129.     class dbmap_iterator_impl : public dbmap_iterator_impl_base
  130.     {
  131.     public:
  132.         value_type m_val;
  133.         dbmap_iterator_impl(dbmap_base* owner)
  134.             : dbmap_iterator_impl_base(owner)
  135.         {}
  136.         virtual void load_key(void* data, size_t size)
  137.         {
  138.             PortableDataInput<MemIO> iKey;
  139.             iKey.set(data, size);
  140.             iKey >> m_val.first;
  141.             FEBIRD_RT_assert(iKey.eof(), std::logic_error);
  142.         }
  143.         virtual void load_val(void* data, size_t size)
  144.         {
  145.             PortableDataInput<MinMemIO> iVal;
  146.             iVal.set(data);
  147.             iVal >> m_val.second;
  148.             FEBIRD_RT_assert(iVal.diff(data) == size, std::logic_error);
  149.         }
  150.         virtual void save_key(PortableDataOutput<AutoGrownMemIO>& oKey1)
  151.         {
  152.             oKey1 << m_val.first;
  153.         }
  154.     };
  155.     //! overrides
  156.     void save_key(PortableDataOutput<AutoGrownMemIO>& dio, const void* key) const { dio << *(const Key*)key; }
  157.     void save_val(PortableDataOutput<AutoGrownMemIO>& dio, const void* val) const { dio << *(const Val*)val; }
  158.     dbmap_iterator_impl_base* make_iter() { return new dbmap_iterator_impl(this); }
  159. public:
  160.     typedef dbmap_iterator<Key, Val, value_type, dbmap_iterator_impl>
  161.             iterator, const_iterator;
  162.     dbmap(DB_ENV* env, const char* dbname
  163.         , DB_TXN* txn = NULL
  164.         , bt_compare_fcn_type bt_comp = bdb_auto_bt_compare((Key*)(0))
  165.         )
  166.         : dbmap_base(env, dbname, txn, bt_comp, BOOST_CURRENT_FUNCTION)
  167.     {
  168.     }
  169.     dbmap(DbEnv* env, const char* dbname
  170.         , DbTxn* txn = NULL
  171.         , bt_compare_fcn_type bt_comp = bdb_auto_bt_compare((Key*)(0))
  172.         )
  173.         : dbmap_base(env->get_DB_ENV(), dbname, txn ? txn->get_DB_TXN() : NULL, bt_comp, BOOST_CURRENT_FUNCTION)
  174.     {
  175.     }
  176.     iterator begin(DB_TXN* txn = NULL) { return iterator(begin_impl(txn, BOOST_CURRENT_FUNCTION)); }
  177.     iterator end  (DB_TXN* txn = NULL) { return iterator(end_impl  (txn, BOOST_CURRENT_FUNCTION)); }
  178.     iterator begin(DbTxn* txn) { return iterator(begin_impl(txn ? txn->get_DB_TXN() : NULL, BOOST_CURRENT_FUNCTION)); }
  179.     iterator end  (DbTxn* txn) { return iterator(end_impl  (txn ? txn->get_DB_TXN() : NULL, BOOST_CURRENT_FUNCTION)); }
  180.     value_type back()
  181.     {
  182.         iterator iter = this->end();
  183.         --iter;
  184.         if (iter.exist())
  185.             return *iter;
  186.         throw std::runtime_error(BOOST_CURRENT_FUNCTION);
  187.     }
  188.     value_type front()
  189.     {
  190.         iterator iter = this->begin();
  191.         if (iter.exist())
  192.             return *iter;
  193.         throw std::runtime_error(BOOST_CURRENT_FUNCTION);
  194.     }
  195.     iterator find(const Key& k, DB_TXN* txn = NULL)
  196.     {
  197.         return iterator(find_impl(&k, txn, DB_SET, BOOST_CURRENT_FUNCTION));
  198.     }
  199.     iterator find(const Key& k, DbTxn* txn)
  200.     {
  201.         return iterator(find_impl(&k, txn ? txn->get_DB_TXN() : NULL, DB_SET, BOOST_CURRENT_FUNCTION));
  202.     }
  203.     iterator lower_bound(const Key& k, DB_TXN* txn = NULL)
  204.     {
  205.         return iterator(find_impl(&k, txn, DB_SET_RANGE, BOOST_CURRENT_FUNCTION));
  206.     }
  207.     iterator lower_bound(const Key& k, DbTxn* txn)
  208.     {
  209.         return iterator(find_impl(&k, txn ? txn->get_DB_TXN() : NULL, DB_SET_RANGE, BOOST_CURRENT_FUNCTION));
  210.     }
  211.     bool insert(const std::pair<Key,Val>& kv, DB_TXN* txn = NULL)
  212.     {
  213.         return insert_impl(&kv.first, &kv.second, DB_NOOVERWRITE, txn, BOOST_CURRENT_FUNCTION);
  214.     }
  215.     bool insert(const std::pair<Key,Val>& kv, DbTxn* txn)
  216.     {
  217.         return insert_impl(&kv.first, &kv.second, DB_NOOVERWRITE, txn ? txn->get_DB_TXN() : NULL, BOOST_CURRENT_FUNCTION);
  218.     }
  219.     bool insert(const Key& k, const Val& d, DB_TXN* txn = NULL)
  220.     {
  221.         return insert_impl(&k, &d, DB_NOOVERWRITE, txn, BOOST_CURRENT_FUNCTION);
  222.     }
  223.     bool insert(const Key& k, const Val& d, DbTxn* txn)
  224.     {
  225.         return insert_impl(&k, &d, DB_NOOVERWRITE, txn ? txn->get_DB_TXN() : NULL, BOOST_CURRENT_FUNCTION);
  226.     }
  227.     void replace(const std::pair<Key,Val>& kv, DB_TXN* txn = NULL)
  228.     {
  229.         insert_impl(&kv.first, &kv.second, 0, txn, BOOST_CURRENT_FUNCTION);
  230.     }
  231.     void replace(const std::pair<Key,Val>& kv, DbTxn* txn)
  232.     {
  233.         insert_impl(&kv.first, &kv.second, 0, txn ? txn->get_DB_TXN() : NULL, BOOST_CURRENT_FUNCTION);
  234.     }
  235.     void replace(const Key& k, const Val& d, DB_TXN* txn = NULL)
  236.     {
  237.         insert_impl(&k, &d, 0, txn, BOOST_CURRENT_FUNCTION);
  238.     }
  239.     void replace(const Key& k, const Val& d, DbTxn* txn)
  240.     {
  241.         insert_impl(&k, &d, 0, txn ? txn->get_DB_TXN() : NULL, BOOST_CURRENT_FUNCTION);
  242.     }
  243.     bool remove(const Key& k, DB_TXN* txn = NULL)
  244.     {
  245.         return remove_impl(&k, txn, BOOST_CURRENT_FUNCTION);
  246.     }
  247.     bool remove(const Key& k, DbTxn* txn)
  248.     {
  249.         return remove_impl(&k, txn ? txn->get_DB_TXN() : NULL, BOOST_CURRENT_FUNCTION);
  250.     }
  251.     bool erase(iterator& iter)
  252.     {
  253.         return iter.remove();
  254.     }
  255.     void clear(DB_TXN* txn = NULL)
  256.     {
  257.         clear_impl(txn, BOOST_CURRENT_FUNCTION);
  258.     }
  259.     void clear(DbTxn* txn)
  260.     {
  261.         return clear_impl(txn ? txn->get_DB_TXN() : NULL, BOOST_CURRENT_FUNCTION);
  262.     }
  263.     DB* getDB() { return m_db; }
  264.     const DB* getDB() const { return m_db; }
  265. };
  266. } // namespace febird
  267. #endif // __febird_bdb_dbmap_h__

file: dbmap.cpp

 

  1. /* vim: set tabstop=4 : */
  2. #include "dbmap.h"
  3. #include <sstream>
  4. /**
  5.  @brief when iterate from end to begin
  6.  @code
  7.     for (dbmap<Key, Val>::iterator iter = dbm.end();;)
  8.     {
  9.         --iter;
  10.         if (!iter.exist()) break;
  11.         pair<Key,Val>& kv = *iter;
  12.     //  do some thing
  13.     }
  14.  @endcode
  15.  */
  16. namespace febird {
  17. dbmap_iterator_impl_base::dbmap_iterator_impl_base(class dbmap_base* owner)
  18.     : m_owner(owner)
  19.     , m_curp(0), m_ret(-1)
  20. {
  21. }
  22. void dbmap_iterator_impl_base::init(DB* dbp, DB_TXN* txn, const char* func)
  23. {
  24.     int ret = dbp->cursor(dbp, txn, &m_curp, 0);
  25.     if (0 != ret)
  26.     {
  27.         delete this;
  28.         std::ostringstream oss;
  29.         oss << db_strerror(ret) << "... at: " << func;
  30.         throw std::runtime_error(oss.str());
  31.     }
  32.     m_ret = 0;
  33. }
  34. dbmap_iterator_impl_base::~dbmap_iterator_impl_base()
  35. {
  36.     if (m_curp)
  37.         m_curp->close(m_curp);
  38. }
  39. void dbmap_iterator_impl_base::advance(u_int32_t direction_flag, const char* func)
  40. {
  41.     FEBIRD_RT_assert(0 == m_ret, std::logic_error);
  42.     DBT tk; memset(&tk, 0, sizeof(DBT));
  43.     DBT td; memset(&td, 0, sizeof(DBT));
  44.     m_ret = m_curp->get(m_curp, &tk, &td, direction_flag);
  45.     if (0 == m_ret)
  46.     {
  47.         load_key(tk.data, tk.size);
  48.         load_val(td.data, td.size);
  49.     }
  50.     else if (DB_NOTFOUND != m_ret)
  51.     {
  52.         std::ostringstream oss;
  53.         oss << db_strerror(m_ret) << "... at: " << func;
  54.         throw std::runtime_error(oss.str());
  55.     }
  56. }
  57. /**
  58.  @brief 
  59.  @return true successful updated
  60.         false (key, d.key2) did not exist, not updated
  61.  @throw other errors
  62.  */
  63. void dbmap_iterator_impl_base::update(const void* d, const char* func)
  64. {
  65.     FEBIRD_RT_assert(0 == m_ret, std::logic_error);
  66.     PortableDataOutput<AutoGrownMemIO> oKey1, oData;
  67.     this->save_key(oKey1);
  68.     m_owner->save_val(oData, d);
  69.     DBT tk; memset(&tk, 0, sizeof(DBT)); tk.data = oKey1.begin(); tk.size = oKey1.tell();
  70.     DBT td; memset(&td, 0, sizeof(DBT)); td.data = oData.begin(); td.size = oData.tell();
  71.     int ret = m_curp->put(m_curp, &tk, &td, DB_CURRENT);
  72.     if (0 != ret)
  73.     {
  74.         std::ostringstream oss;
  75.         oss << db_strerror(ret)
  76.             << "... at: " << func;
  77.         throw std::runtime_error(oss.str());
  78.     }
  79. }
  80. void dbmap_iterator_impl_base::remove(const char* func)
  81. {
  82.     FEBIRD_RT_assert(0 == m_ret, std::logic_error);
  83.     int ret = m_curp->del(m_curp, 0);
  84.     if (0 != ret)
  85.     {
  86.         std::ostringstream oss;
  87.         oss << db_strerror(ret)
  88.             << "... at: " << func;
  89.         throw std::runtime_error(oss.str());
  90.     }
  91. }
  92. //////////////////////////////////////////////////////////////////////////
  93. dbmap_base::dbmap_base(DB_ENV* env, const char* dbname
  94.     , DB_TXN* txn
  95.     , bt_compare_fcn_type bt_comp
  96.     , const char* func
  97.     )
  98.     : m_bt_comp(0)
  99. {
  100.     m_bulkSize = 512*1024;
  101.     m_db = 0;
  102.     int ret = db_create(&m_db, env, 0);
  103.     if (0 == ret)
  104.     {
  105.         if (bt_comp) {
  106.             m_bt_comp = bt_comp;
  107.             m_db->set_bt_compare(m_db, bt_comp);
  108.         }
  109.         m_db->app_private = (this);
  110.         int flags = env->open_flags & (DB_THREAD|DB_MULTIVERSION|DB_AUTO_COMMIT);
  111.         ret = m_db->open(m_db, txn, dbname, dbname, DB_BTREE, DB_CREATE|flags, 0);
  112.     }
  113.     if (0 != ret)
  114.     {
  115.         std::ostringstream oss;
  116.         oss << db_strerror(ret)
  117.             << "... at: " << func;
  118.         throw std::runtime_error(oss.str());
  119.     }
  120. }
  121. dbmap_base::~dbmap_base()
  122. {
  123.     if (m_db)
  124.         m_db->close(m_db, 0);
  125. }
  126. dbmap_iterator_impl_base* dbmap_base::begin_impl(DB_TXN* txn, const char* func)
  127. {
  128.     dbmap_iterator_impl_base* iter = make_iter();
  129.     iter->init(m_db, txn, func);
  130.     DBT tk; memset(&tk, 0, sizeof(DBT));
  131.     DBT td; memset(&td, 0, sizeof(DBT));
  132.     iter->m_ret = iter->m_curp->get(iter->m_curp, &tk, &td, DB_FIRST);
  133.     if (0 == iter->m_ret)
  134.     {
  135.         iter->load_key(tk.data, tk.size);
  136.         iter->load_val(td.data, td.size);
  137.     }
  138.     else if (DB_NOTFOUND != iter->m_ret)
  139.     {
  140.         std::ostringstream oss;
  141.         oss << db_strerror(iter->m_ret)
  142.             << "... at: " << func;
  143.         delete iter; iter = 0;
  144.         throw std::runtime_error(oss.str());
  145.     }
  146.     return iter;
  147. }
  148. dbmap_iterator_impl_base* dbmap_base::end_impl(DB_TXN* txn, const char* func)
  149. {
  150.     dbmap_iterator_impl_base* iter = make_iter();
  151.     iter->init(m_db, txn, func);
  152. //  iter->m_ret = DB_NOTFOUND;
  153.     return iter;
  154. }
  155. dbmap_iterator_impl_base* dbmap_base::find_impl(const void* k, DB_TXN* txn, u_int32_t flags, const char* func)
  156. {
  157.     PortableDataOutput<AutoGrownMemIO> oKey1;
  158.     save_key(oKey1, k);
  159.     DBT tk; memset(&tk, 0, sizeof(DBT)); tk.data = oKey1.begin(); tk.size = oKey1.tell();
  160.     DBT td; memset(&td, 0, sizeof(DBT));
  161.     dbmap_iterator_impl_base* iter = make_iter();
  162.     iter->init(m_db, txn, func);
  163.     iter->m_ret = iter->m_curp->get(iter->m_curp, &tk, &td, flags);
  164.     if (0 == iter->m_ret)
  165.     {
  166.         iter->load_key(tk.data, tk.size);
  167.         iter->load_val(td.data, td.size);
  168.     }
  169.     else if (DB_NOTFOUND != iter->m_ret && DB_KEYEMPTY != iter->m_ret)
  170.     {
  171.         std::ostringstream oss;
  172.         oss << db_strerror(iter->m_ret)
  173.             << "... at: " << func
  174.             << "/n"
  175.             << "flags=" << flags
  176.             ;
  177.         throw std::runtime_error(oss.str());
  178.     }
  179.     return iter;
  180. }
  181. /**
  182.  @brief insert a record
  183.  @return true success,  no same k-k2 in db, the record was inserted
  184.          false failed, has same k-k2 in db, the record was not inserted, not replaced existing yet
  185.  @throws exception, failed
  186.  */
  187. bool dbmap_base::insert_impl(const void* k, const void* d, u_int32_t flags, DB_TXN* txn, const char* func)
  188. {
  189.     PortableDataOutput<AutoGrownMemIO> oKey1, oData;
  190.     try {
  191.         save_key(oKey1, k);
  192.         save_val(oData, d);
  193.     }
  194.     catch (const IOException& exp)
  195.     {
  196.         std::ostringstream oss;
  197.         oss << exp.what() << "... at: " << func;
  198.         throw std::runtime_error(oss.str());
  199.     }
  200.     DBT tk; memset(&tk, 0, sizeof(DBT)); tk.data = oKey1.begin(); tk.size = oKey1.tell();
  201.     DBT td; memset(&td, 0, sizeof(DBT)); td.data = oData.begin(); td.size = oData.tell();
  202.     int ret = m_db->put(m_db, txn, &tk, &td, flags);
  203.     if (DB_KEYEXIST == ret)
  204.         return false;
  205.     if (0 == ret)
  206.         return true;
  207.     std::ostringstream oss;
  208.     oss << db_strerror(ret)
  209.         << "... at: " << func
  210.         << "/n"
  211.         ;
  212.     throw std::runtime_error(oss.str());
  213. }
  214. /**
  215.  @brief 
  216.  @return true (k) existed, remove success
  217.         false (k) not existed, nothing done
  218.  */
  219. bool dbmap_base::remove_impl(const void* k, DB_TXN* txn, const char* func)
  220. {
  221.     PortableDataOutput<AutoGrownMemIO> oKey1;
  222.     save_key(oKey1, k);
  223.     DBT tk; memset(&tk, 0, sizeof(DBT)); tk.data = oKey1.begin(); tk.size = oKey1.tell();
  224.     int ret = m_db->del(m_db, txn, &tk, 0);
  225.     if (DB_NOTFOUND == ret)
  226.         return false;
  227.     if (0 == ret)
  228.         return true;
  229.     std::ostringstream oss;
  230.     oss << db_strerror(ret)
  231.         << "... at: " << func
  232.         << "/n"
  233.         ;
  234.     throw std::runtime_error(oss.str());
  235. }
  236. void dbmap_base::clear_impl(DB_TXN* txn, const char* func)
  237. {
  238.     u_int32_t count;
  239.     int ret = m_db->truncate(m_db, txn, &count, 0);
  240.     if (0 != ret)
  241.     {
  242.         std::ostringstream oss;
  243.         oss << db_strerror(ret)
  244.             << "... at: " << func
  245.             << "/n"
  246.             ;
  247.         throw std::runtime_error(oss.str());
  248.     }
  249. }
  250. } // namespace febird
最常用的两种C++序列化方案的使用心得(protobuf和boost serialization) 导读 1. 什么是序列化? 2. 为什么要序列化?好处在哪里? 3. C++对象序列化的四种方法 4. 最常用的两种序列化方案使用心得 阅读详情

相关推荐

RedisTemplate之JSON序列化的配置方式

前言 在写这篇文章之前,我相信大家很多人包括我之前也使用过Jedis,特别是很多什么JedisUtils、RedisUtil等等所谓的工具类。刚开始不是太熟悉Reids觉得也挺方便,但是永久了之后发现完全没必要用这些自定义的Utils,更何况很对这种Utils序列化都是字符串,哪怕你设置的时候用Jackson或者是漏洞百出的Fastjson来转换成JSON字符串,而且每次在设置的时候都需要转换一下,是不是觉得很麻烦,有没有直接转换的呢?答案是有的,就是用Spring官方提供的RedisTemplate,然后

Yong Ledo的博客 3949

VB6各数据类型序列化和反序列化

Private Sub Command1_Click()序列化Dim var1 As ByteDim var2 As BooleanDim var3 As IntegerDim var4 As LongDim var5 As SingleDim var6 As DoubleDim var7 As Stringvar1 = CByte(Text1.Text)var2 = CBool(Tex

不愿放弃的专栏 2876

Coze智能体开发:JSON 序列化和反序列化

JSON 序列化和反序列化是常见的数据类型转换方式,例如将某个节点输出的 Object 对象保存在扣子数据库中,需要先将 Object 对象转换为 JSON 字符串,再通过数据库节点保存到 String 类型的字段中。

王国平的博客 2211

C++ 序列化:从设计到实现

使用C++ 实现了序列化和反序列化

weixin_36823685的博客 1636

C++序列化简析

CArchive类是VisualC++程序设计中最常用的文件处理的方法,CArchive类不仅可以实现简单数据结构的读写操作,还可以通过对CObiect类的派生实现对复杂数据结构的读写操作,因此,利用CArchive类,可以轻松实现任意数据结构的序列化。在使用基于OTT的数据库结构的程序进行性能测试时,由于读入的PNR数据是XML格式的文档,所以,读入XML文件到内存,将其转为DOM树,继而将DOM树中的数据转化为OTT数据库所需要的对象结构,需要耗费大量的时间。如果估计大了,又会造成空间的浪费。

程序猿老樊的博客 375

fastJSON:最小,最快的多态JSON序列化程序

fastJSON 最小,最快的多态JSON序列化器 请参阅此处的文章:[ ]( ) 另请参阅 安全警告 HP Enterprise Security Group引起了我的注意,使用$type扩展名可能会导致不安全,因此,应将其与常识和已知的json来源一起使用,而不要面向公众使用,以确保安全。 安全警告更新 我添加了JSONParameters.BadListTypeChecking ,默认为true以检查HP Enterprise Security Group发表的论文中已知的$type攻击向量,启用后将抛出异常并停止处理json。

Java最快的序列化库 zfoo protocol

Ⅰ. 简介 zfoo protocol是目前的Java二进制序列化和反序列化最快的框架,并且线程安全 协议目前原生支持Java Javascript C# Lua,协议理论上可以跨平台 使用Javassist字节码增强动态生成顺序执行的序列化和反序列化函数,顺序执行的函数可以轻易的被JIT编译以达到极致的性能 单线程环境,在没有任何JVM参数调优的情况下速度比Kryo快40%,比Protobuf快110%,参见性能测试 多线程环境,zfoo和Protobuf的性能不受任何影响,kryo因为线程不安全性能会

u011327159的博客 2025

VC序列化-存储文件方法

VC序列化-存储文件方法,可用于系统配置,或者系统状态的保存

序列化与反序列化

【代码】C/C++序列化与反序列化

cs的专栏 196

Windows如何使用Anaconda 3进行keras环境的配置

** Windows如何使用Anaconda 3进行keras环境的配置 搭建Keras环境* Anaconda3如何安装keras,主要包括下面三步: 1.安装mingw libpython 2.安装theano 3.安装keras 若你还没有按装anaconda,赶紧下载安装吧! 下载途径有两个 (1)Anaconda版本为Anaconda 4.4.0,对应的python版本为3.6,附上An...

Lance_liangliang的博客 1601

别再傻傻分不清!用R语言5分钟搞定RR、AR、OR的计算与解读(附代码)

本文通过R语言实战演示,详细讲解了RR(相对风险)、AR(绝对风险)和OR(比值比)的计算方法与科学解读。提供完整的代码示例和可视化技巧,帮助医学研究者快速掌握这些核心流行病学指标的应用与常见陷阱规避。

weixin_42526015的博客 265

探索 UniHttp:解锁 Xml 及 JavaBean 序列化的多种方式

本文将详细探讨在 UniHttp 环境下,实现 Xml 和 JavaBean 序列化的多种方式。我们将从基础的序列化原理入手,逐步深入到各种具体实现方法,包括但不限于使用原生的 Java 库、第三方序列化工具以及自定义序列化器等。

夜郎King的博客 8962

从仿真到实体:基于Isaac Gym的X20机械狗与Kinova Gen3 Lite机械臂全身协同控制实战

本文详细介绍了基于Isaac Gym仿真平台,实现云深处X20机械狗与Kinova Gen3 Lite机械臂全身协同控制的完整实战流程。内容涵盖环境搭建、模型适配、分阶段训练策略、域随机化技巧,以及最终将训练好的策略安全部署到实体机器人的关键步骤,为复杂机器人系统的仿真到实体迁移提供了宝贵经验。

yhn45678901的博客 489

最便捷、最强大、速度最快的C++序列化框架【二】

项目地址:http://code.google.com/p/febird 目前该框架(DataIO)仅支持二进制。想起序列化支持只需要一个宏DATA_IO_LOAD_SAVE/DATA_IO_LOAD_SAVE_V,对象成员基本上用“&”连接起来,这样,可以写一个简单的语法分析器,将成员序列化表达转化成字符串,然后进行语法分析,这样,就可以在不用改变客户代码的情况下,进行文本方式(如XML

whinah的专栏 1472

Trans论文复现:电池储能调峰和调频:超线性增益的联合优化程序代码!

本程序参考一区SCI期刊《Using Battery Storage for Peak Shaving and Frequency Regulation: Joint Optimization for Superlinear Gains》,程序。与之前将电池储能用于单一应用相比,研究结果表明,如果电池联合提供多种服务,它们可以获得比以前想象的更大的经济效益。欢迎感兴趣的小伙伴关注下方公众号获取完整版代码哦~,小编会继续推送更有质量的学习资料、文章程序代码~限于篇幅,仅列出部分算例的结果!

weixin_48747334的博客 567

避坑指南:LISFLOOD-FP模型数据单位、参数文件与results文件夹结果解析全攻略

本文详细解析了LISFLOOD-FP洪水模拟模型的关键应用环节,包括数据单位校验、参数文件优化及结果文件解读与可视化。特别针对常见的单位混淆问题,提供了从DEM到边界条件的全面校验方法,并深入剖析了.par参数文件的配置技巧,帮助用户避免模型崩溃和结果失真。

weixin_42533622的博客 237

Kotlin 便捷的实现 Parcelable 序列化

Android中的序列化在开发中,如果有需要用到序列化和反序列化的操作,就会用到 Serializable 或者 Parcelable,它们各有优缺点,会适用于不同的场景。SerializableSerializable 的优点是实现简单,你只需要实现一个 Serializable 接口,并不需要任何额外的代码,但是它的序列化和反序列化,实际上是使用反射做的,所以效率会略低,并且它会在序列化的过程中

发强 1万+

自动权重化图卷积网络(Auto-Weighted GCN)算法在反洗钱识别中的应用及代码实现

该算法通过自动学习节点之间的权重信息,能够更好地捕捉AML数据中的关系和结构,从而提高反洗钱识别的准确性和效果。传统的AML识别方法通常依赖于专家定义的规则和手动提取的特征,但这些方法在应对大规模和复杂的数据时存在一定的局限性。GCN通过在图上执行卷积操作来捕捉节点之间的关系和结构信息,从而实现对图数据的学习和表示。自动权重化图卷积网络是一种基于GCN的改进算法,能够自动学习节点之间的权重信息,从而更好地捕捉图中的关系。利用自动计算的权重值执行图卷积操作。根据节点之间的相似度,计算每个节点的权重。

syntax_api860的博客 376

最常用的C++序列化方案:protobuf

参考链接:最常用的两种C++序列化方案的使用心得(protobuf和boost serialization)[c++] Google Protobuf库 1. 什么是序列化? 程序员在编写应用程序的时候往往需要将程序的某些数据存储在内存中,然后将其写入某个文件或是将它传输到网络中的另一台计算机上以实现通讯。这个将 程序数据转化成能被存储并传输的格式的过程被称为“序列化”(Serializatio...

weixin_36976685的博客 938

yolov5直接调用zed相机实现三维测距(python)

zed代码比较简洁,但是一定要把环境配置好,后续自己会把他当做普通双目标定,去对比分析效果,并完善相关功能。

积极向上的mr.d的博客 1万+

北斗导航 | 卫星信号捕获跟踪原理解析

卫星信号的捕获与跟踪是导航接收机的"眼睛",其性能直接决定定位精度、动态适应性和抗干扰能力。随着北斗三号全球组网完成,新一代接收机正朝着。两大核心阶段,二者共同构成定位的基础。调制,频谱主瓣宽度达4.092MHz,较传统BPSK调制抗干扰能力提升3dB[38]。的目标持续演进,在自动驾驶、精密农业等领域展现出巨大应用潜力。二维空间中搜索峰值相关能量[4]。卫星导航接收机对信号的处理可分为。北斗三号B1C/B2a信号采用。北斗三号新增的B1C信号采用。

尘世冰封的专栏 775

java中原生的序列化与其他序列化框架

java基础之序列化

简单,快乐,拥抱变化 682

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

最常用的C++序列化方案综述

导读 1. 什么是序列化? 2. 为什么要序列化?好处在哪里? 3. C++对象序列化的四种方法 4. 最常用的两种序列化方案使用心得 正文 1. 什么是序列化? 程序员在编写应用程序的时候往往需要将程序的某些数据存储在内存中,然后将其写入某个文件或是将它传输到网络中的另一台计算机上以实现通讯。这个将程序数据转化成能被存储并传输的格式的过程被称为“序列化”(Serializa

追梦船的专栏 860

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

高性能序列化类库

目录 一:序列化 (1)作用 (2)问题 (3)优化方向 二:Spark中的序列化 (1)序列化情景 (2)Java序列化 (3)Kryo序列化 (4)优化Kryo类库的使用 (5)Kryo的使用场景 一:序列化 (1)作用 序列化之后到内存,磁盘,进行传输 (2)问题 序列化前后分别是什么样的形态进行存在? (流化动作) 序列化:把对象转换为字节序列的过程...

威少(微笑) 779

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

上一篇: 什么是序列化
下一篇: Berkeley DB的sql实现
inter999
博客等级 码龄19年 18粉丝 9原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值