[serialize] xml archives and versioning

The header of our xml archive looks like this: <?xml version="1.0" encoding="UTF-8" standalone="yes" ?> <!DOCTYPE boost_serialization> <boost_serialization signature="serialization::archive" version="3"> <CoatingScanConfig class_id="0" tracking_level="0"> The object written as CoatingScanConfig didn't have a class version specified (and therefore there isn't one in the header). When writting this class, the version parameter is passed in to the serialize() method is 0 for the class, but when reading it, the version number is subsequently passed in as 3 (which looks like the archive version). Should it not be 0 also? Is 0 a valid version number for a class? If I specify the class version as 1, then reading and writing both get '1' as the version, but if I don't specify a version, or I specify 0, then writing gets 0, but reading gets '3'. If 0 isn't valid, then could there be a static_assert catching this? And a quick usage question: If a class isn't versioned, is an inherent 'version 0' written to the archive so that a version number of 1 can be applied to the object later when it is modified, or do objects need to be given a version number from the start? Thanks Russell

Actually there are two version concepts in the serialization library. The first is the serialization library format version. This is the "3" in the boost_serialization tag. Its purpose is to permit future changes in the serialization library to be made in such a way that the future code can detect and properly read archives created with previous versions of the library. Hopefully this will rarely if ever change and almost never bee needed by users of the library. The second is the class version. This is designed to be used by library users to permit them to change class definitions and still guarentee that previously written archives are readable. "Russell Hind" <rh_gmane@mac.com> wrote in message news:cl5tad$ghm$1@sea.gmane.org...
The header of our xml archive looks like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> <!DOCTYPE boost_serialization> <boost_serialization signature="serialization::archive" version="3"> <CoatingScanConfig class_id="0" tracking_level="0">
The object written as CoatingScanConfig didn't have a class version specified (and therefore there isn't one in the header).
When writting this class, the version parameter is passed in to the serialize() method is 0 for the class, but when reading it, the version number is subsequently passed in as 3 (which looks like the archive version). Should it not be 0 also?
It certainly should - send me a code snippet. The package includes tests of
Is 0 a valid version number for a class?
yes
If I specify the class version as 1, then reading and writing both get '1' as the version, but if I don't specify a version, or I specify 0, then writing gets 0, but reading gets '3'.
I would think that is a bug. I would like to see more information
If 0 isn't valid, then could there be a static_assert catching this?
And a quick usage question: If a class isn't versioned, is an inherent 'version 0' written to the archive so that a version number of 1 can be applied to the object later when it is modified, or do objects need to be given a version number from the start?
serialization traits determine whether or not a class is versioned. Default is for non primititve types to be versioned and the default version number is 0. The usage of version number when not necessary could be a performance issue so there is the option of setting serialization traits for any type so that versioning isn't done. For example, this is not done for STL collections. Review the section of the documentation "serialization traits"
Thanks
Russell
_______________________________________________ Unsubscribe & other changes:

Robert Ramey wrote:
It certainly should - send me a code snippet. The package includes tests of
If I change this to use text_i/o archive then it works fine, but with XML, m_Version is set to zero when writing, but set to 3 when reading (this is with latest trunk from just before branch for release yesterday morning). Also, if I provide a version number for the class of anything but 0 then it works find (e.g. 1) but 0 or no version lead to the ambiguity (running under borland bcc32 5.6.4) #include <fstream> #include <iostream> #include <boost/archive/xml_iarchive.hpp> #include <boost/archive/xml_oarchive.hpp> class Test_c { public: Test_c(void) : m_Version(99999999) { } template <typename ArchiveT> void serialize(ArchiveT& ar, const unsigned int version) { m_Version = version; } unsigned int m_Version; }; int main(int argc, char** argv) { Test_c Test; { std::ofstream ofs("C:\\test.xml"); boost::archive::xml_oarchive toa(ofs); toa & BOOST_SERIALIZATION_NVP(Test); std::cout << "Test version = " << Test.m_Version << std::endl; } { std::ifstream ifs("C:\\test.xml"); boost::archive::xml_iarchive tia(ifs); tia & BOOST_SERIALIZATION_NVP(Test); std::cout << "Test version = " << Test.m_Version << std::endl; } return 0; }
serialization traits determine whether or not a class is versioned. Default is for non primititve types to be versioned and the default version number is 0. The usage of version number when not necessary could be a performance issue so there is the option of setting serialization traits for any type so that versioning isn't done. For example, this is not done for STL collections. Review the section of the documentation "serialization traits"
Thanks, I will do. Cheers Russell

Robert Ramey wrote:
It certainly should - send me a code snippet. The package includes
tests of
If I change this to use text_i/o archive then it works fine, but with XML, m_Version is set to zero when writing, but set to 3 when reading (this is with latest trunk from just before branch for release yesterday morning). Also, if I provide a version number for the class of anything but 0 then it works find (e.g. 1) but 0 or no version lead to the ambiguity (running under borland bcc32 5.6.4)
#include <fstream> #include <iostream> #include <boost/archive/xml_iarchive.hpp> #include <boost/archive/xml_oarchive.hpp>
class Test_c { public: Test_c(void) : m_Version(99999999) { }
template <typename ArchiveT> void serialize(ArchiveT& ar, const unsigned int version) { m_Version = version; }
unsigned int m_Version; };
int main(int argc, char** argv) { Test_c Test;
{ std::ofstream ofs("C:\\test.xml"); boost::archive::xml_oarchive toa(ofs); toa & BOOST_SERIALIZATION_NVP(Test); std::cout << "Test version = " << Test.m_Version << std::endl; }
{ std::ifstream ifs("C:\\test.xml"); boost::archive::xml_iarchive tia(ifs); tia & BOOST_SERIALIZATION_NVP(Test); std::cout << "Test version = " << Test.m_Version << std::endl; }
return 0; }
serialization traits determine whether or not a class is versioned.
Default
is for non primititve types to be versioned and the default version number is 0. The usage of version number when not necessary could be a
issue so there is the option of setting serialization traits for any type so that versioning isn't done. For example, this is not done for STL collections. Review the section of the documentation "serialization
There is a confusion here. Check the manual section titled "Class Versioning" There should be something like: BOOST_CLASS_VERSION(Test_c, 99) in your code. I don't remember what the maximum class version might be but it could be small like 255 for binary archives. Robert Ramey "Russell Hind" <rh_gmane@mac.com> wrote in message news:cl7tra$jqe$1@sea.gmane.org... performance traits"
Thanks, I will do.
Cheers
Russell
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Robert Ramey wrote:
There is a confusion here. Check the manual section titled "Class Versioning"
There should be something like:
BOOST_CLASS_VERSION(Test_c, 99)
in your code. I don't remember what the maximum class version might be but it could be small like 255 for binary archives.
I did ask about this in the previous e-mail. I thought non-primitive types were, by default, versioned, i.e. if no BOOST_CLASS_VERSION is specified, they have a version of 0. Is this not the case? Anyway, the code I posted still gives odd results if I set BOOST_CLASS_VERSION(Test_c, 0). Anything but 0 works, but zero gives the effects described previously, a 3 on the way back in, which is your archive version, not the class version. Again, specifying no version works for text archives (haven't checked binary) but not for XML. Thanks Russell

I rebuilt and reran the the tests "test_class_info_load" and "test_class_info_save" which are explicitly designed to test this functionality. I ran these test with XML archives. Do these tests pass for you? How is this situation different than yours? I updated the test sliightly so that the class version jumps from 2 to 4 - skipping over 3 so that a confusion between serialization library version and class version wouldn't be overlooked. Robert Ramey "Russell Hind" <rh_gmane@mac.com> wrote in message news:clacr8$u01$1@sea.gmane.org...
Robert Ramey wrote:
There is a confusion here. Check the manual section titled "Class Versioning"
There should be something like:
BOOST_CLASS_VERSION(Test_c, 99)
in your code. I don't remember what the maximum class version might be but it could be small like 255 for binary archives.
I did ask about this in the previous e-mail. I thought non-primitive types were, by default, versioned, i.e. if no BOOST_CLASS_VERSION is specified, they have a version of 0. Is this not the case?
Anyway, the code I posted still gives odd results if I set BOOST_CLASS_VERSION(Test_c, 0). Anything but 0 works, but zero gives the effects described previously, a 3 on the way back in, which is your archive version, not the class version.
Again, specifying no version works for text archives (haven't checked binary) but not for XML.
Thanks
Russell
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Robert Ramey wrote:
I rebuilt and reran the the tests "test_class_info_load" and "test_class_info_save" which are explicitly designed to test this functionality. I ran these test with XML archives. Do these tests pass for you? How is this situation different than yours? I updated the test sliightly so that the class version jumps from 2 to 4 - skipping over 3 so that a confusion between serialization library version and class version wouldn't be overlooked.
Do you test with version 0? That is the only version that causes a problem. I am looking in to how to run tests now so will let you know how I get on, but the problem is only if BOOST_CLASS_VERSION is 0 or not set (i.e. defaults to 0). 1 and above version work fine. Thanks Russell

Robert, test_class_info_load and test_class_info_save both passed for xml_archive but I have created a test (attached) which fails for version 0 xml archives. Can you try this please? It creates an object with version 0, writes it to an xml archive (currently hard-coded to drive c so I could check the output file easily), and then reads it back in. As mentioned before: when reading in the object, the version is passed in to serialize as 3, not 0 as it should be. For XML files: there is no version attribute for the object when the version is 0, so maybe this is the problem. Thanks Russell Robert Ramey wrote:
I rebuilt and reran the the tests "test_class_info_load" and "test_class_info_save" which are explicitly designed to test this functionality. I ran these test with XML archives. Do these tests pass for you? How is this situation different than yours? I updated the test sliightly so that the class version jumps from 2 to 4 - skipping over 3 so that a confusion between serialization library version and class version wouldn't be overlooked.
Robert Ramey
"Russell Hind" <rh_gmane@mac.com> wrote in message news:clacr8$u01$1@sea.gmane.org...
Robert Ramey wrote:
There is a confusion here. Check the manual section titled "Class Versioning"
There should be something like:
BOOST_CLASS_VERSION(Test_c, 99)
in your code. I don't remember what the maximum class version might be
but
it could be small like 255 for binary archives.
I did ask about this in the previous e-mail. I thought non-primitive types were, by default, versioned, i.e. if no BOOST_CLASS_VERSION is specified, they have a version of 0. Is this not the case?
Anyway, the code I posted still gives odd results if I set BOOST_CLASS_VERSION(Test_c, 0). Anything but 0 works, but zero gives the effects described previously, a 3 on the way back in, which is your archive version, not the class version.
Again, specifying no version works for text archives (haven't checked binary) but not for XML.
Thanks
Russell
_______________________________________________ Unsubscribe & other changes:
http://lists.boost.org/mailman/listinfo.cgi/boost
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 // test_class_info_load.cpp: test implementation level trait // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . // Use, modification and distribution is subject to the Boost Software // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // test implementation level "object_class_info" // should pass compilation and execution #include <cstdio> #include <string> #include <fstream> #include <boost/static_assert.hpp> #include <boost/serialization/level.hpp> #include <boost/serialization/tracking.hpp> #include <boost/serialization/version.hpp> #include <boost/serialization/nvp.hpp> #include <boost/archive/tmpdir.hpp> #include <boost/preprocessor/stringize.hpp> #include <boost/archive/xml_iarchive.hpp> #include <boost/archive/xml_oarchive.hpp> #include "test_tools.hpp" class A { public: template <typename ArchiveT> void serialize(ArchiveT& ar, const unsigned int version) { if (ArchiveT::is_loading::value) { BOOST_CHECK(version == 0); } } }; BOOST_CLASS_VERSION(A, 0) void in(const char *testfile, A& a) { { std::ofstream ofs(testfile); boost::archive::xml_oarchive xoa(ofs); xoa & BOOST_SERIALIZATION_NVP(a); } { std::ifstream ifs(testfile); boost::archive::xml_iarchive xia(ifs); xia & BOOST_SERIALIZATION_NVP(a); } } int test_main( int /* argc */, char* /* argv */[] ) { A a; std::string filename; filename += boost::archive::tmpdir(); filename += '/'; filename += BOOST_PP_STRINGIZE(testfile_); filename += BOOST_PP_STRINGIZE(BOOST_ARCHIVE_TEST); // in(filename.c_str(), a, b); in("c:\\test.xml", a); return boost::exit_success; } // EOF

OK, I have found an error and checked in a change that I believe will fix this. Thanks for finding this. Robert Ramey "Russell Hind" <rh_gmane@mac.com> wrote in message news:cld60j$fmc$1@sea.gmane.org...
Robert,
test_class_info_load and test_class_info_save both passed for xml_archive but I have created a test (attached) which fails for version 0 xml archives. Can you try this please?
It creates an object with version 0, writes it to an xml archive (currently hard-coded to drive c so I could check the output file easily), and then reads it back in.
As mentioned before: when reading in the object, the version is passed in to serialize as 3, not 0 as it should be.
For XML files: there is no version attribute for the object when the version is 0, so maybe this is the problem.
Thanks
Russell
Robert Ramey wrote:
I rebuilt and reran the the tests "test_class_info_load" and "test_class_info_save" which are explicitly designed to test this functionality. I ran these test with XML archives. Do these tests pass for you? How is this situation different than yours? I updated the test sliightly so that the class version jumps from 2 to 4 - skipping over 3 so that a confusion between serialization library version and class version wouldn't be overlooked.
Robert Ramey
"Russell Hind" <rh_gmane@mac.com> wrote in message news:clacr8$u01$1@sea.gmane.org...
Robert Ramey wrote:
There is a confusion here. Check the manual section titled "Class Versioning"
There should be something like:
BOOST_CLASS_VERSION(Test_c, 99)
in your code. I don't remember what the maximum class version might be
but
it could be small like 255 for binary archives.
I did ask about this in the previous e-mail. I thought non-primitive types were, by default, versioned, i.e. if no BOOST_CLASS_VERSION is specified, they have a version of 0. Is this not the case?
Anyway, the code I posted still gives odd results if I set BOOST_CLASS_VERSION(Test_c, 0). Anything but 0 works, but zero gives the effects described previously, a 3 on the way back in, which is your archive version, not the class version.
Again, specifying no version works for text archives (haven't checked binary) but not for XML.
Thanks
Russell
_______________________________________________ Unsubscribe & other changes:
http://lists.boost.org/mailman/listinfo.cgi/boost
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
---------------------------------------------------------------------------- ----
/////////1/////////2/////////3/////////4/////////5/////////6/////////7////// ///8
// test_class_info_load.cpp: test implementation level trait
// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . // Use, modification and distribution is subject to the Boost Software // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt)
// test implementation level "object_class_info" // should pass compilation and execution
#include <cstdio> #include <string> #include <fstream>
#include <boost/static_assert.hpp> #include <boost/serialization/level.hpp> #include <boost/serialization/tracking.hpp> #include <boost/serialization/version.hpp> #include <boost/serialization/nvp.hpp>
#include <boost/archive/tmpdir.hpp> #include <boost/preprocessor/stringize.hpp>
#include <boost/archive/xml_iarchive.hpp> #include <boost/archive/xml_oarchive.hpp> #include "test_tools.hpp"
class A { public: template <typename ArchiveT> void serialize(ArchiveT& ar, const unsigned int version) { if (ArchiveT::is_loading::value) { BOOST_CHECK(version == 0); } } };
BOOST_CLASS_VERSION(A, 0)
void in(const char *testfile, A& a) { { std::ofstream ofs(testfile); boost::archive::xml_oarchive xoa(ofs); xoa & BOOST_SERIALIZATION_NVP(a); }
{ std::ifstream ifs(testfile); boost::archive::xml_iarchive xia(ifs); xia & BOOST_SERIALIZATION_NVP(a); } }
int test_main( int /* argc */, char* /* argv */[] ) { A a; std::string filename; filename += boost::archive::tmpdir(); filename += '/'; filename += BOOST_PP_STRINGIZE(testfile_); filename += BOOST_PP_STRINGIZE(BOOST_ARCHIVE_TEST); // in(filename.c_str(), a, b); in("c:\\test.xml", a); return boost::exit_success; }
// EOF
---------------------------------------------------------------------------- ----
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
participants (2)
-
Robert Ramey
-
Russell Hind