$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r83152 - in sandbox/transaction/boost/transact: . detail
From: strasser_at_[hidden]
Date: 2013-02-25 11:23:55
Author: stefans
Date: 2013-02-25 11:23:51 EST (Mon, 25 Feb 2013)
New Revision: 83152
URL: http://svn.boost.org/trac/boost/changeset/83152
Log:
updated logging subsystem
Added:
   sandbox/transaction/boost/transact/detail/file_iterator.hpp   (contents, props changed)
Removed:
   sandbox/transaction/boost/transact/char_archive.hpp
Properties modified: 
   sandbox/transaction/boost/transact/archive.hpp   (contents, props changed)
   sandbox/transaction/boost/transact/array_extension.hpp   (contents, props changed)
   sandbox/transaction/boost/transact/default_tag.hpp   (props changed)
   sandbox/transaction/boost/transact/object_access.hpp   (contents, props changed)
Text files modified: 
   sandbox/transaction/boost/transact/archive.hpp                 |    45 +-                                      
   sandbox/transaction/boost/transact/array_extension.hpp         |    64 ++-                                     
   sandbox/transaction/boost/transact/basic_transaction.hpp       |    14                                         
   sandbox/transaction/boost/transact/detail/aligning_file.hpp    |    13                                         
   sandbox/transaction/boost/transact/detail/buffering_file.hpp   |    49 ++-                                     
   sandbox/transaction/boost/transact/detail/config.hpp           |     6                                         
   sandbox/transaction/boost/transact/detail/embedded_vector.hpp  |    31 +                                       
   sandbox/transaction/boost/transact/detail/file.hpp             |    82 +++-                                    
   sandbox/transaction/boost/transact/detail/filebuf_file.hpp     |    22 +                                       
   sandbox/transaction/boost/transact/detail/sectorizing_file.hpp |    10                                         
   sandbox/transaction/boost/transact/detail/syncing_file.hpp     |    59 ++-                                     
   sandbox/transaction/boost/transact/log.hpp                     |   616 +++++++++++++++++++++++---------------- 
   sandbox/transaction/boost/transact/object_access.hpp           |    13                                         
   13 files changed, 629 insertions(+), 395 deletions(-)
Modified: sandbox/transaction/boost/transact/archive.hpp
==============================================================================
--- sandbox/transaction/boost/transact/archive.hpp	(original)
+++ sandbox/transaction/boost/transact/archive.hpp	2013-02-25 11:23:51 EST (Mon, 25 Feb 2013)
@@ -1,4 +1,4 @@
-//          Copyright Stefan Strasser 2010.
+//          Copyright Stefan Strasser 2010 - 2013.
 // Distributed under 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)
@@ -12,8 +12,6 @@
 #include <boost/ref.hpp>
 #include <boost/assert.hpp>
 #include <boost/mpl/bool.hpp>
-#include <boost/serialization/is_bitwise_serializable.hpp>
-#include <boost/serialization/wrapper.hpp>
 #include <boost/archive/archive_exception.hpp>
 #include <boost/transact/array_extension.hpp>
 #include <iterator>
@@ -27,6 +25,7 @@
 #include <boost/archive/basic_binary_oarchive.hpp>
 #include <boost/archive/impl/basic_binary_iarchive.ipp>
 #include <boost/archive/impl/basic_binary_oarchive.ipp>
+#include <boost/serialization/wrapper.hpp>
 #include <string>
 
 #endif
@@ -220,16 +219,16 @@
     explicit basic_char_oarchive(OutputIterator const &out) : out(out){}
     template<class Size>
     void save_binary(void const *vdata,Size size){
-        this->save_binary(static_cast<char const *>(vdata),size,typename array_extension<OutputIterator>::type());
+        this->save_binary(static_cast<char const *>(vdata),size,typename has_array_extension<OutputIterator>::type());
     }
 private:
     template<class Size>
     void save_binary(char const *data,Size size,mpl::true_){
-        this->out.assign(data,size);
+        this->out=this->out.insert(data,size);
     }
     template<class Size>
     void save_binary(char const *data,Size size,mpl::false_){
-        std::copy(data,data+size,this->out);
+        this->out=std::copy(data,data+size,this->out);
     }
 
     OutputIterator out;
@@ -240,34 +239,43 @@
 public:
     basic_char_iarchive(InputIterator const &begin,InputIterator const &end)
         : in(begin), end(end){
-        BOOST_ASSERT(end - begin >= 0);
     }
     template<class Size>
     void load_binary(void *vdata,Size size){
         char *data=static_cast<char *>(vdata);
+	this->load_binary(data,size,typename has_array_extension<InputIterator>::type());
+    }
+private:
+    template<class Size>
+    void load_binary(char *data,Size size,mpl::true_ arrayex){
+        this->in=this->in.extract(data,size);
+    }
+    template<class Size>
+    void load_binary(char *data,Size size,mpl::false_ arrayex){
         this->load_binary(
             data,
             size,
+	    arrayex,
             typename std::iterator_traits<InputIterator>::iterator_category(),
-            typename continuous_values<InputIterator>::type()
-        );
+            typename has_contiguous_values<InputIterator>::type()
+        );      
     }
-private:
     template<class Size>
-    void load_binary(char *data,Size size,std::random_access_iterator_tag,mpl::true_ contvals){
-        if(std::size_t(this->end - this->in) < size) throw archive::archive_exception(archive::archive_exception::stream_error);
+    void load_binary(char *data,Size size,mpl::false_ arrayex,std::random_access_iterator_tag,mpl::true_ contvals){
+        if(std::size_t(this->end - this->in) < size) throw archive::archive_exception(archive::archive_exception::input_stream_error);
         std::memcpy(data,&*this->in,size);
         this->in+=size;
     }
     template<class Size>
-    void load_binary(char *data,Size size,std::random_access_iterator_tag,mpl::false_ contvals){
-        if(std::size_t(this->end - this->in) < size) throw archive::archive_exception(archive::archive_exception::stream_error);
+    void load_binary(char *data,Size size,mpl::false_ arrayex,std::random_access_iterator_tag,mpl::false_ contvals){
+        //FIXME:
+        if(std::size_t(this->end - this->in) < size) throw archive::archive_exception(archive::archive_exception::input_stream_error);
         std::copy(data,data+size,this->in);
     }
     template<class Size,class Category>
-    void load_binary(char *data,Size size,Category,mpl::false_ contvals){
+    void load_binary(char *data,Size size,mpl::false_ arrayex,Category,mpl::false_ contvals){
         for(std::size_t c=0;c<size;++c){
-            if(this->in == this->end) throw archive::archive_exception(archive::archive_exception::stream_error);
+            if(this->in == this->end) throw archive::archive_exception(archive::archive_exception::input_stream_error);
             *data++=*this->in++;
         }
     }
@@ -331,7 +339,7 @@
             data,
             size,
             typename std::iterator_traits<InputIterator>::iterator_category(),
-            typename continuous_values<InputIterator>::type()
+            typename has_contiguous_values<InputIterator>::type()
         );
     }
     void save(std::type_info const *type){
@@ -352,7 +360,8 @@
     }
     template<class Size>
     void save_binary(char const *data,Size size,std::random_access_iterator_tag,mpl::false_ contvals){
-        if((std::size_t(this->end - this->in) < size) || (!std::equal(data,data+size,this->in))) this->equal_=false;
+        //FIXME: invalid iterator:
+        if((std::size_t(this->end - this->in) < size) || (!std::equal(data,data+size,this->in))) this->equal_=false; 
         else this->in+=size;
     }
     template<class Size,class Category>
Modified: sandbox/transaction/boost/transact/array_extension.hpp
==============================================================================
--- sandbox/transaction/boost/transact/array_extension.hpp	(original)
+++ sandbox/transaction/boost/transact/array_extension.hpp	2013-02-25 11:23:51 EST (Mon, 25 Feb 2013)
@@ -1,4 +1,4 @@
-//          Copyright Stefan Strasser 2010.
+//          Copyright Stefan Strasser 2010 - 2013.
 // Distributed under 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)
@@ -13,57 +13,65 @@
 namespace transact{
 
 template<class T>
-struct array_extension : mpl::false_{};
+struct has_array_extension : mpl::false_{};
 
 template<class T>
-struct continuous_values : mpl::false_{};
+struct has_contiguous_values : mpl::false_{};
 
 template<class T>
-struct continuous_values<T *> : mpl::true_{};
+struct has_contiguous_values<T *> : mpl::true_{};
 
 
 template<typename Vector>
 class vector_back_insert_iterator
-    : public std::iterator<std::output_iterator_tag,void,void,void,void>{
+    : public std::iterator<std::output_iterator_tag,typename Vector::value_type,typename Vector::difference_type,typename Vector::pointer_type,typename Vector::reference_type>{
 public:
     typedef Vector container_type;
-    explicit vector_back_insert_iterator(Vector &vec) : vec(vec){}
+    explicit vector_back_insert_iterator(Vector &vec) : vec(&vec){}
     vector_back_insert_iterator &operator=(typename Vector::const_reference v){
-        this->vec.push_back(v);
+        this->vec->push_back(v);
         return *this;
     }
-    template<class Size>
-    vector_back_insert_iterator &assign(typename Vector::const_pointer data,Size size){
-        this->assign(data,size,typename array_extension<Vector>::type(),typename is_pod<typename Vector::value_type>::type());
-        return *this;
+    template<class InputIterator,class Size>
+    vector_back_insert_iterator &insert(InputIterator input,Size size){
+        this->insert(input,size,typename has_array_extension<Vector>::type());
+	return *this;
     }
     vector_back_insert_iterator &operator*(){ return *this; }
     vector_back_insert_iterator &operator++(){ return *this; }
     vector_back_insert_iterator operator++(int){ return *this; }
 private:
-    template<class Size,bool Pod>
-    void assign(typename Vector::const_pointer data,Size size,mpl::true_ array,mpl::bool_<Pod>){
-        this->vec.push_back(data,size);
-    }
-    template<class Size>
-    void assign(typename Vector::const_pointer data,Size size,mpl::false_ array,mpl::true_ pod){
-        std::size_t const oldsize=this->vec.size();
-        this->vec.resize(oldsize + size);
-        std::memcpy(&this->vec[oldsize],data,size * sizeof(typename Vector::value_type));
-    }
-    template<class Size>
-    void assign(typename Vector::const_pointer data,Size size,mpl::false_ array,mpl::false_ pod){
-        std::size_t const oldsize=this->vec.size();
-        this->vec.resize(oldsize + size);
-        std::copy(data,data+size,this->vec.begin()+oldsize);
+    template<class InputIterator,class Size>
+    void insert(InputIterator input,Size size,mpl::true_ arrayex){
+        this->vec->push_back(input,size);
+    }
+    template<class InputIterator,class Size>
+    void insert(InputIterator input,Size size,mpl::false_ arrayex){
+        this->insert(input,size,arrayex,
+            mpl::bool_<has_contiguous_values<InputIterator>::value
+                       && is_pod<typename Vector::value_type>::value>());
+    }
+            
+    template<class InputIterator,class Size>
+    void insert(InputIterator input,Size size,mpl::false_ arrayex,mpl::true_ contigpod){
+        std::size_t const oldsize=this->vec->size();
+        this->vec->resize(oldsize + size);
+        std::memcpy(&(*this->vec)[oldsize],&*input,size * sizeof(typename Vector::value_type));
+    }
+    template<class InputIterator,class Size>
+    void insert(InputIterator input,Size size,mpl::false_ arrayex,mpl::false_ contigpod){
+        this->vec->reserve(this->vec->size() + size);
+	for(std::size_t c=0;c<size;++c){
+            this->vec->push_back(*input++);
+	}
     }
 
-    Vector &vec;
+    Vector *vec;
 };
 
 
 template<class Vector>
-struct array_extension<vector_back_insert_iterator<Vector> > : mpl::true_{};
+struct has_array_extension<vector_back_insert_iterator<Vector> > : mpl::true_{};
 
 
 
Modified: sandbox/transaction/boost/transact/basic_transaction.hpp
==============================================================================
--- sandbox/transaction/boost/transact/basic_transaction.hpp	(original)
+++ sandbox/transaction/boost/transact/basic_transaction.hpp	2013-02-25 11:23:51 EST (Mon, 25 Feb 2013)
@@ -1,4 +1,4 @@
-//          Copyright Stefan Strasser 2009 - 2010.
+//          Copyright Stefan Strasser 2009 - 2013.
 // Distributed under 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)
@@ -142,22 +142,29 @@
         boost::transact::basic_transaction<TXMGR> ___tx; \
         while(true){ \
             try{ \
+                // call ___tx.commit() at the end of this scope unless an exception is thrown: \
                 boost::transact::detail::commit_on_destruction<TXMGR> ___commit(___tx); \
                 try{ \
                     do{ \
-                        ___control=1; \
+		        ___control=1; \
+		        // force the following user code to be exactly one statement or {} \
                         if(false);else
 
 #define BOOST_TRANSACT_BASIC_RETRY(TXMGR) \
+                        // if this point is reached, the user code above neither used \
+                        // "break" nor "continue". exit while-loop with ___control==0 \
                         ___control=0; \
                         break; \
+                    // if this point is reached, the user code above used "continue". \
+                    // commit the transaction but record the user intent by ___control==2 \
                     }while((___control=2),false); \
+                    break; \
                 }catch(...){ \
                     ___commit.nullify(); \
                     throw; \
                 } \
-                break; \
             }catch(boost::transact::isolation_exception &___i){ \
+                // transaction must be repeated: \
                 ___i.unwind<TXMGR>(); \
                 ___tx.restart(); \
                 do{ \
@@ -172,6 +179,7 @@
             } \
         }; \
         BOOST_ASSERT(___control == 0); \
+    // force the use of a semicolon: \
     }void()
 
 #define BOOST_TRANSACT_BASIC_END_RETRY_IN_LOOP(TXMGR) \
Deleted: sandbox/transaction/boost/transact/char_archive.hpp
==============================================================================
--- sandbox/transaction/boost/transact/char_archive.hpp	2013-02-25 11:23:51 EST (Mon, 25 Feb 2013)
+++ (empty file)
@@ -1,116 +0,0 @@
-//          Copyright Stefan Strasser 2010.
-// Distributed under 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)
-
-
-#ifndef BOOST_TRANSACT_CHAR_ARCHIVE_HPP
-#define BOOST_TRANSACT_CHAR_ARCHIVE_HPP
-
-#include <boost/mpl/bool.hpp>
-#include <boost/mpl/size_t.hpp>
-#include <boost/serialization/is_bitwise_serializable.hpp>
-#include <boost/archive/archive_exception.hpp>
-#include <boost/static_assert.hpp>
-#include <boost/type_traits/is_same.hpp>
-#include <boost/transact/array_extension.hpp>
-#include <algorithm>
-#include <iterator>
-#include <typeinfo>
-#include <cstring>
-
-namespace boost{
-namespace transact{
-
-template<class OutputIterator>
-class char_oarchive{
-public:
-    typedef mpl::true_ is_saving;
-    typedef mpl::false_ is_loading;
-    explicit char_oarchive(OutputIterator const &out) : out(out){}
-    template<class Size>
-    void save_binary(void const *vdata,Size size){
-        this->save_binary(static_cast<char const *>(vdata),size,typename array_extension<OutputIterator>::type());
-    }
-    template<class T>
-    char_oarchive &operator<<(T const &t){
-        BOOST_STATIC_ASSERT(serialization::is_bitwise_serializable<T>::value);
-        this->save_binary(&t,mpl::size_t<sizeof(T)>());
-        return *this;
-    }
-    template<class T>
-    char_oarchive &operator&(T const &t){
-        return this->operator<<(t);
-    }
-private:
-    template<class Size>
-    void save_binary(char const *data,Size size,mpl::true_){
-        this->out.assign(data,size);
-    }
-    template<class Size>
-    void save_binary(char const *data,Size size,mpl::false_){
-        std::copy(data,data+size,this->out);
-    }
-
-    OutputIterator out;
-};
-
-template<class InputIterator>
-class char_iarchive{
-public:
-    typedef mpl::false_ is_saving;
-    typedef mpl::true_ is_loading;
-    //TODO optimization: array extract extension
-    char_iarchive(InputIterator const &begin,InputIterator const &end)
-        : in(begin), end(end){}
-    template<class Size>
-    void load_binary(void *vdata,Size size){
-        char *data=static_cast<char *>(vdata);
-        this->load_binary(
-            data,
-            size,
-            typename std::iterator_traits<InputIterator>::iterator_category(),
-            typename continuous_values<InputIterator>::type()
-        );
-    }
-    template<class T>
-    char_iarchive &operator >>(T &t){
-        BOOST_STATIC_ASSERT(serialization::is_bitwise_serializable<T>::value);
-        this->load_binary(&t,mpl::size_t<sizeof(T)>());
-        return *this;
-    }
-    template<class T>
-    char_iarchive &operator &(T &t){
-        return this->operator>>(t);
-    }
-private:
-    BOOST_STATIC_ASSERT((is_same<typename std::iterator_traits<InputIterator>::value_type,char>::value));
-    template<class Size>
-    void load_binary(char *data,Size size,std::random_access_iterator_tag,mpl::true_ contvals){
-        if(this->in + size > this->end) throw archive::archive_exception(archive::archive_exception::stream_error);
-        std::memcpy(data,&*this->in,size);
-        this->in+=size;
-    }
-    template<class Size>
-    void load_binary(char *data,Size size,std::random_access_iterator_tag,mpl::false_ contvals){
-        if(this->in + size > this->end) throw archive::archive_exception(archive::archive_exception::stream_error);
-        std::copy(data,data+size,this->in);
-    }
-    template<class Size,class Category>
-    void load_binary(char *data,Size size,Category,mpl::false_ contvals){
-        for(std::size_t c=0;c<size;++c){
-            if(this->in == this->end) throw archive::archive_exception(archive::archive_exception::stream_error);
-            *data++=*this->in++;
-        }
-    }
-
-    InputIterator in;
-    InputIterator end;
-};
-
-
-}
-}
-
-
-#endif
Modified: sandbox/transaction/boost/transact/detail/aligning_file.hpp
==============================================================================
--- sandbox/transaction/boost/transact/detail/aligning_file.hpp	(original)
+++ sandbox/transaction/boost/transact/detail/aligning_file.hpp	2013-02-25 11:23:51 EST (Mon, 25 Feb 2013)
@@ -1,4 +1,4 @@
-//          Copyright Stefan Strasser 2009 - 2010.
+//          Copyright Stefan Strasser 2009 - 2013.
 // Distributed under 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)
@@ -27,7 +27,7 @@
 
 //does. the inserted 1536 bytes of garbage even need to be synced.
 
-//TODO optimization: not tested on windows.
+//TODO optimization: not performance tested on windows.
 
 template<class Base>
 class aligning_seq_ofile{
@@ -51,6 +51,15 @@
         if(this->sectors <= max_sectors) return this->base.position() + this->sectors * sector_size;
         else return this->base.position();
     }
+    void close(){
+        this->flush_buffer();
+	this->sectors=0;
+        this->base.close();
+    }
+    void reopen(std::string const &name){
+        BOOST_ASSERT(this->sectors==0);
+        this->base.reopen(name);
+    }
     void flush(){
         BOOST_ASSERT(this->base.position() % sector_size == 0);
         if(this->sectors > 1 && this->sectors <= max_sectors){
Modified: sandbox/transaction/boost/transact/detail/buffering_file.hpp
==============================================================================
--- sandbox/transaction/boost/transact/detail/buffering_file.hpp	(original)
+++ sandbox/transaction/boost/transact/detail/buffering_file.hpp	2013-02-25 11:23:51 EST (Mon, 25 Feb 2013)
@@ -1,4 +1,4 @@
-//          Copyright Stefan Strasser 2009 - 2010.
+//          Copyright Stefan Strasser 2009 - 2013.
 //                Copyright Bob Walters 2010
 // Distributed under the Boost Software License, Version 1.0.
 //    (See accompanying file LICENSE_1_0.txt or copy at
@@ -52,7 +52,7 @@
 class buffering_seq_ofile{
 public:
     typedef typename Base::size_type size_type;
-	static const bool direct_io = Base::has_direct_io;
+    static const bool has_direct_io = Base::has_direct_io;
         
     explicit buffering_seq_ofile(std::string const &name)
         : base(name)
@@ -72,6 +72,14 @@
         this->flush_buffer();
         this->base.flush();
     }
+    void close(){
+        this->flush_buffer();
+	this->base.close();
+    }
+    void reopen(std::string const &name){
+        BOOST_ASSERT(this->size==0);
+        this->base.reopen(name);
+    }
     void sync(){
         //don't flush buffer! caller is responsible to call flush() inside a mutex lock.
         this->base.sync();
@@ -88,25 +96,25 @@
 private:
     void write_overflow(void const *data,std::size_t s){
         BOOST_ASSERT(this->size + s > Capacity);
-		if (direct_io) {
-			while (this->size + s > Capacity) {
-				std::size_t write=Capacity - this->size;
-				std::memcpy(this->buffer.data+this->size,data,write);
-				this->size=Capacity;
-				this->flush_buffer();
-				data = static_cast<char const *>(data)+write;
-				s-=write;
-			}
-			if (s) {
-				this->write(data,s);
-			}
-		}else if(this->size == 0){
+	if (has_direct_io) {
+		while (this->size + s > Capacity) {
+			std::size_t write=Capacity - this->size;
+			std::memcpy(this->buffer.data+this->size,data,write);
+			this->size=Capacity;
+			this->flush_full_buffer();
+			data = static_cast<char const *>(data)+write;
+			s-=write;
+		}
+		if (s) { //FIXME ???
+			this->write(data,s);
+		}
+	}else if(this->size == 0){
             this->base.write(data,s);
         }else{
             std::size_t write=Capacity - this->size;
             std::memcpy(this->buffer.data+this->size,data,write);
             this->size=Capacity;
-            this->flush_buffer();
+            this->flush_full_buffer();
             this->write(static_cast<char const *>(data)+write,s-write);
         }
     }
@@ -116,10 +124,15 @@
             this->size=0;
         }
     }
+    void flush_full_buffer(){
+        BOOST_ASSERT(this->size == Capacity);
+	this->base.write(this->buffer.data,mpl::size_t<Capacity>());
+	this->size=0;
+    }
 
     Base base;
-	ofile_buffer<Capacity,direct_io> buffer;
-	std::size_t size;
+    ofile_buffer<Capacity,has_direct_io> buffer;
+    std::size_t size;
 };
 
 
Modified: sandbox/transaction/boost/transact/detail/config.hpp
==============================================================================
--- sandbox/transaction/boost/transact/detail/config.hpp	(original)
+++ sandbox/transaction/boost/transact/detail/config.hpp	2013-02-25 11:23:51 EST (Mon, 25 Feb 2013)
@@ -1,4 +1,4 @@
-//          Copyright Stefan Strasser 2010.
+//          Copyright Stefan Strasser 2010  2013.
 // Distributed under 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)
@@ -8,6 +8,10 @@
 
 #include <boost/config.hpp>
 
+//work around a bug in MSVC that doesn't allow the template keyword
+//to be used in call to template operators.
+//see boost list thread:
+//"[boost] [config] explicit call of operator templates / msvc bugworkaround"
 #ifdef BOOST_MSVC
 #define BOOST_NESTED_OPERATOR_TEMPLATE
 #else
Modified: sandbox/transaction/boost/transact/detail/embedded_vector.hpp
==============================================================================
--- sandbox/transaction/boost/transact/detail/embedded_vector.hpp	(original)
+++ sandbox/transaction/boost/transact/detail/embedded_vector.hpp	2013-02-25 11:23:51 EST (Mon, 25 Feb 2013)
@@ -115,15 +115,15 @@
     //insert(this->end(), ...) is not the same thing. even though the end() == end()
     //comparison can be optimized away if inlined, size must be statically known to get
     //an intrinsic memcpy for PODs.
-    template<class Size>
-    void push_back(T const *src,Size size){
+    template<class InputIterator,class Size>
+    void push_back(InputIterator src,Size size){
         this->reserve_add(size);
         copy_construct_n(this->end_,src,size);
         this->end_+=size;
     }
 
     //extension to in-place construct a new element. elements of vectors with Expand==false
-    //don't need to be copyconstructible using this:
+    //don't need to be copyconstructible using this: FIXME use c++11
     template<class InPlaceFactory>
     void push_back(InPlaceFactory const &fac){
         this->reserve_add(mpl::size_t<1>());
@@ -165,20 +165,23 @@
             throw;
         }
     }
-    template<class Size>
-    static void copy_construct_n(T *dest,T const *src,Size n){
-        copy_construct_n(dest,src,n,typename is_pod<T>::type());
+    template<class InputIterator,class Size>
+    static void copy_construct_n(T *dest,InputIterator src,Size n){
+        copy_construct_n(
+            dest,src,n,
+            mpl::bool_<is_pod<T>::value && has_contiguous_values<InputIterator>::value>()
+	);
+    }
+    template<class InputIterator,class Size>
+    static void copy_construct_n(T *dest,InputIterator src,Size n,true_type pod){
+        std::memcpy(dest,&*src,sizeof(T)*std::size_t(n));
     }
-    template<class Size>
-    static void copy_construct_n(T *dest,T const *src,Size n,true_type pod){
-        std::memcpy(dest,src,sizeof(T)*std::size_t(n));
-    }
-    template<class Size>
-    static void copy_construct_n(T *dest,T const *src,Size n,false_type pod){
+    template<class InputIterator,class Size>
+    static void copy_construct_n(T *dest,InputIterator src,Size n,false_type pod){
         std::size_t c;
         try{
             for(c=0;c<n;++c){
-                new (dest+c) T(src[c]);
+                new (dest+c) T(*src++);
             }
         }catch(...){
             destruct(dest,dest+c);
@@ -243,7 +246,7 @@
 }
 
 template<class T,std::size_t EmbeddedSize,bool Expand>
-struct array_extension<detail::embedded_vector<T,EmbeddedSize,Expand> > : mpl::true_{};
+struct has_array_extension<detail::embedded_vector<T,EmbeddedSize,Expand> > : mpl::true_{};
 
 }
 }
Modified: sandbox/transaction/boost/transact/detail/file.hpp
==============================================================================
--- sandbox/transaction/boost/transact/detail/file.hpp	(original)
+++ sandbox/transaction/boost/transact/detail/file.hpp	2013-02-25 11:23:51 EST (Mon, 25 Feb 2013)
@@ -1,4 +1,4 @@
-//               Copyright Bob Walters 2010
+//               Copyright Stefan Strasser 2010 - 2013
 // Distributed under 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)
@@ -11,9 +11,11 @@
 
 namespace boost{
 namespace transact{
-namespace detail{
 
 struct eof_exception : io_failure{};
+  
+  
+namespace detail{
 
 
 #ifdef _WIN32
@@ -68,7 +70,7 @@
                         throw_io_failure("CreateFileA");
                 
                 //make sure the directory entry has reached the disk:
-		std::string dirname=filesystem::system_complete(name).parent_path().external_directory_string();
+		std::string dirname=filesystem::system_complete(name).parent_path().native();
 
                 creation_flags = OPEN_EXISTING;
                 flags = FILE_FLAG_BACKUP_SEMANTICS;
@@ -88,6 +90,9 @@
                         CloseHandle(this->filedes);
         }
         
+	void close(); //TODO
+	void reopen(std::string const &name); //TODO
+	
         void seek(size_type const &s) {
                 LARGE_INTEGER loc;
                 loc.QuadPart = s;
@@ -101,7 +106,7 @@
                         throw_io_failure("WriteFile");
                 return (size_type)written;
         }
-	
+	void flush(){}
         void sync() { 
                 if (!direct_io && FlushFileBuffers(this->filedes) == 0)
                         throw_io_failure("FlushFileBuffers");
@@ -117,6 +122,8 @@
 #error no POSIX synchronized IO available
 #endif
 
+
+
 // low-level ofile for Linux/Unix
 template <bool direct_io = false> // ignored on Posix API.
 class ofile {
@@ -124,29 +131,15 @@
         typedef unsigned int size_type;
         static const bool has_direct_io = direct_io;
 
-	int filedes;
         
-	ofile(std::string const &name) : filedes(-1) {
-		int flags=O_CREAT | O_WRONLY;
-#ifdef linux
-		flags|=O_NOATIME;
-#endif
-		this->filedes= open(name.c_str(),flags,S_IRUSR | S_IWUSR);
-		if(this->filedes==-1) throw io_failure();
-		
-		{ //make sure the directory entry has reached the disk:
-			std::string dirname=filesystem::path(name).directory_string();
-			if(dirname.empty()) dirname=".";
-			int dirfd= open(dirname.c_str(),O_RDONLY);
-			if(dirfd==-1) throw io_failure();
-			int ret=::fsync(dirfd);
-			if(::close(dirfd) != 0 || ret != 0) throw io_failure();
-		}
+	ofile(std::string const &name) : filedes(-1),name(name){
+	        this->open_();
+		this->sync_directory();
         }
         
         ~ofile() {
-        if(this->filedes != -1) ::close(this->filedes);
-    }
+            this->close();
+        }
         
         void seek(size_type const &s) {
                 if(::lseek(this->filedes,s,SEEK_SET) != off_t(s)) throw io_failure();
@@ -156,7 +149,7 @@
                 if(::write(this->filedes,data,size) != ssize_t(size)) throw io_failure();
                 return size;
         }
-	
+	void flush(){}
         void sync() {
 #ifdef linux
                 if(::fdatasync(this->filedes) != 0) throw io_failure();
@@ -164,6 +157,47 @@
                 if(::fsync(this->filedes) != 0) throw io_failure();
 #endif		
         }
+	void close(){
+            if(this->filedes != -1){
+	        if(::close(this->filedes) != 0) throw io_failure();
+	    }
+    	    this->filedes=-1;
+	}
+	void reopen(std::string const &newname){
+	    BOOST_ASSERT(this->filedes == -1);
+	    filesystem::remove(this->name);
+	    this->name=newname;
+	    this->open_();
+	    sync_directory();
+	}
+	void rename(std::string const &newname){
+	    BOOST_ASSERT(this->filedes == -1);
+	    filesystem::rename(this->name,newname);
+	    this->name=newname;
+	    this->open_(0); //do not truncate file!
+	    sync_directory();	  
+	}
+private:
+    void sync_directory(){
+        //TODO optimization: directory entries are synced even if syncing is turning off,
+        //which is not passed to ofile
+        std::string dirname=filesystem::path(this->name).parent_path().native();
+        if(dirname.empty()) dirname=".";
+        int dirfd= open(dirname.c_str(),O_RDONLY);
+        if(dirfd==-1) throw io_failure();
+        int ret=::fsync(dirfd);
+        if(::close(dirfd) != 0 || ret != 0) throw io_failure();
+    }
+    void open_(int flags=O_CREAT | O_TRUNC){
+	flags|=O_WRONLY;
+#ifdef linux
+	flags|=O_NOATIME;
+#endif
+	this->filedes=open(this->name.c_str(),flags,S_IRUSR | S_IWUSR);
+	if(this->filedes==-1) throw io_failure();
+    }
+    int filedes;
+    std::string name;
 };
 
 #endif
Added: sandbox/transaction/boost/transact/detail/file_iterator.hpp
==============================================================================
--- (empty file)
+++ sandbox/transaction/boost/transact/detail/file_iterator.hpp	2013-02-25 11:23:51 EST (Mon, 25 Feb 2013)
@@ -0,0 +1,100 @@
+//               Copyright Stefan Strasser 2013
+// Distributed under 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)
+
+#ifndef BOOST_TRANSACT_DETAIL_FILE_ITERATOR_HPP
+#define BOOST_TRANSACT_DETAIL_FILE_ITERATOR_HPP
+
+
+#include <iterator>
+#include <boost/mpl/bool.hpp>
+#include <boost/transact/array_extension.hpp>
+#include <boost/type_traits/is_pod.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/optional/optional.hpp>
+
+
+namespace boost{
+namespace transact{
+namespace detail{
+
+template<typename File>
+class file_output_iterator
+    : public std::iterator<std::output_iterator_tag,char>{
+public:
+    typedef File file_type;
+    explicit file_output_iterator(File &file) : file(&file){}
+    file_output_iterator &operator=(char v){
+        this->file->write(&v,mpl::size_t<sizeof(char)>());
+        return *this;
+    }    
+    template<class InputIterator,class Size>
+    file_output_iterator &insert(InputIterator input,Size size){
+        this->insert(input,size,typename has_contiguous_values<InputIterator>::type());
+	return *this;
+    }
+    file_output_iterator &operator*(){ return *this; }
+    file_output_iterator &operator++(){ return *this; }
+    file_output_iterator operator++(int);
+private:
+    template<class InputIterator,class Size>
+    void insert(InputIterator input,Size size,mpl::true_ contig){
+	this->file->write(&*input,size);
+    }
+    template<class InputIterator,class Size>
+    void insert(InputIterator input,Size size,mpl::false_ contig){
+	for(std::size_t c=0;c<size;++c){
+            this->file->write(&*input,mpl::size_t<sizeof(char)>());
+	    ++input;
+	}
+    }
+
+    File *file;
+};
+
+template<class File>
+class file_input_iterator
+    : std::iterator<std::forward_iterator_tag,char>{
+public:
+    typedef File file_type;
+    file_input_iterator() : file(0){} //eof iterator  
+    explicit file_input_iterator(File &file) : file(&file){}
+    char operator*() const;
+    file_input_iterator &operator++();
+    file_input_iterator operator++(int);
+    bool operator==(file_input_iterator const &other) const;
+    bool operator!=(file_input_iterator const &other) const;
+    template<class OutputIterator,class Size>
+    file_input_iterator &extract(OutputIterator output,Size size){
+        this->extract(output,size,typename has_contiguous_values<OutputIterator>::type());
+	return *this;
+    }
+private:
+    template<class OutputIterator,class Size>
+    void extract(OutputIterator output,Size size,mpl::true_ contig){
+	this->file->read(&*output,size);
+    }
+    template<class OutputIterator,class Size>
+    void extract(OutputIterator output,Size size,mpl::false_ contig){
+	for(std::size_t c=0;c<size;++c){
+            this->file->read(&*output,mpl::size_t<sizeof(char)>());
+	    ++output;
+	}
+    }
+    File *file;  
+};
+
+  
+}
+
+template<class File>
+struct has_array_extension<detail::file_output_iterator<File> > : mpl::true_{};
+template<class File>
+struct has_array_extension<detail::file_input_iterator<File> > : mpl::true_{};
+
+
+}
+}
+
+#endif
Modified: sandbox/transaction/boost/transact/detail/filebuf_file.hpp
==============================================================================
--- sandbox/transaction/boost/transact/detail/filebuf_file.hpp	(original)
+++ sandbox/transaction/boost/transact/detail/filebuf_file.hpp	2013-02-25 11:23:51 EST (Mon, 25 Feb 2013)
@@ -1,4 +1,4 @@
-//          Copyright Stefan Strasser 2009 - 2010.
+//          Copyright Stefan Strasser 2009 - 2013.
 // Distributed under 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)
@@ -10,6 +10,7 @@
 #include <fstream>
 #include <string>
 #include <boost/mpl/size_t.hpp>
+#include <boost/filesystem.hpp>
 #include <boost/transact/exception.hpp>
 #include <boost/transact/detail/file.hpp>
 
@@ -25,8 +26,9 @@
 class filebuf_seq_ofile{
 public:
     typedef unsigned int size_type;
-    explicit filebuf_seq_ofile(std::string const &name) : pos(0){
-        if(!this->buf.open(name.c_str(),std::ios::out | std::ios::binary)) throw io_failure();
+    static bool const has_direct_io=false;
+    explicit filebuf_seq_ofile(std::string const &name) : pos(0),name(name){
+        this->open();
     }
     void write(void const *data,mpl::size_t<1>){
         if(this->buf.sputc(*static_cast<char const *>(data)) == EOF) throw io_failure();
@@ -44,9 +46,23 @@
     void sync(){
         throw unsupported_operation();
     }
+    void close(){
+        if(!this->buf.close()) throw io_failure();
+    }
+    void reopen(std::string const &newname){
+        BOOST_ASSERT(!this->buf.is_open());
+	filesystem::remove(this->name);
+	this->name=newname;
+	this->open();
+    }
 private:
+    void open(){
+        if(!this->buf.open(this->name.c_str(),std::ios::out | std::ios::binary)) throw io_failure();
+        this->pos=0; 
+    }
     std::filebuf buf;
     size_type pos;
+    std::string name;
 };
 
 class filebuf_seq_ifile{
Modified: sandbox/transaction/boost/transact/detail/sectorizing_file.hpp
==============================================================================
--- sandbox/transaction/boost/transact/detail/sectorizing_file.hpp	(original)
+++ sandbox/transaction/boost/transact/detail/sectorizing_file.hpp	2013-02-25 11:23:51 EST (Mon, 25 Feb 2013)
@@ -1,4 +1,4 @@
-//          Copyright Stefan Strasser 2009 - 2010.
+//          Copyright Stefan Strasser 2009 - 2013.
 // Distributed under 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)
@@ -50,6 +50,14 @@
 #endif
         }
     }
+    void close(){
+        this->flush_buffer();
+	this->base.close();
+    }
+    void reopen(std::string const &name){
+        BOOST_ASSERT(this->size==0);
+        this->base.reopen(name); 
+    }
 private:
     static std::size_t const sector_size=512;
     static std::size_t const max_size=sector_size-2;
Modified: sandbox/transaction/boost/transact/detail/syncing_file.hpp
==============================================================================
--- sandbox/transaction/boost/transact/detail/syncing_file.hpp	(original)
+++ sandbox/transaction/boost/transact/detail/syncing_file.hpp	2013-02-25 11:23:51 EST (Mon, 25 Feb 2013)
@@ -1,4 +1,4 @@
-//          Copyright Stefan Strasser 2009 - 2010
+//          Copyright Stefan Strasser 2009 - 2013
 //                Copyright Bob Walters 2010
 // Distributed under the Boost Software License, Version 1.0.
 //    (See accompanying file LICENSE_1_0.txt or copy at
@@ -21,7 +21,10 @@
 namespace transact{
 namespace detail{
 
+static std::size_t const file_write_ahead_size=10*1024*1024;
+static std::size_t const file_page_size=4096;
 
+  
 template <class Base>
 class syncing_seq_ofile{
 public:
@@ -31,13 +34,13 @@
     explicit syncing_seq_ofile(std::string const &name)
                 : pos(0)
                 , base(name){
-			this->write_ahead(0,write_ahead_size);
+			this->write_ahead(0,file_write_ahead_size);
                 }
     void write(void const *data,std::size_t size){
-		size_type const s=this->pos % write_ahead_size;
-		if(s + size >= write_ahead_size){ //there must be at least one 0 at the and, so also write ahead if this is equal.
-			size_type start=this->pos - s + write_ahead_size;
-			size_type end=start+((s + size)/write_ahead_size) * write_ahead_size; //usually == start + write_ahead_size, but "size" can theoretically span a whole write_ahead_size
+		size_type const s=this->pos % file_write_ahead_size;
+		if(s + size >= file_write_ahead_size){ //there must be at least one 0 at the and, so also write ahead if this is equal.
+			size_type start=this->pos - s + file_write_ahead_size;
+			size_type end=start+((s + size)/file_write_ahead_size) * file_write_ahead_size; //usually == start + file_write_ahead_size, but "size" can theoretically span a whole file_write_ahead_size
                         BOOST_ASSERT(end > start);
                         this->write_ahead(start,end);
                 }
@@ -47,33 +50,47 @@
                 if(ret != std::size_t(size)) throw io_failure();
         }
     size_type position() const{ return this->pos; }
-    void flush() {}
+    void flush(){
+        base.flush();
+    }
     void sync() {
-		base.sync();
-	}
+        base.sync();
+    }
+    void close(){
+        //do not actually close, just make sure contents are on disk. no call to base.close()!
+        this->flush();
+	this->sync(); //TODO opimize sync in lock?
+	this->pos=0;
+    }
+    void reopen(std::string const &name){
+        BOOST_ASSERT(this->pos==0);
+	//file is still open, invalidate file for reuse BEFORE renaming:
+	this->write_ahead(0,file_write_ahead_size);
+	this->base.close();
+        this->base.rename(name); //rename, not reopen! by writing ahead the file is effectively truncated
+    }
 private:
     size_type pos;
         Base base;
 
     void write_ahead(size_type const &start,size_type const &end){
-        BOOST_ASSERT(start % write_ahead_size == 0);
-        BOOST_ASSERT(end % write_ahead_size == 0);
-        BOOST_STATIC_ASSERT(write_ahead_size % page_size == 0);
+        BOOST_ASSERT(start % file_write_ahead_size == 0);
+        BOOST_ASSERT(end % file_write_ahead_size == 0);
+        BOOST_STATIC_ASSERT(file_write_ahead_size % file_page_size == 0);
         base.seek(start);
-        for(size_type off=start;off < end;off+=page_size){
-            base.write(empty_page.data,page_size);
+        for(size_type off=start;off < end;off+=file_page_size){
+            base.write(empty_page.data,file_page_size);
         }
-		base.sync();
-		base.seek(this->pos);
+        this->flush();
+        this->sync();
+        base.seek(this->pos);
     }
 
-    static std::size_t const write_ahead_size=10*1024*1024;
-    static std::size_t const page_size=4096;
 
-    struct empty_page_type : public ofile_buffer<page_size,has_direct_io> {
-		typedef ofile_buffer<page_size,has_direct_io> base_buffer;
+    struct empty_page_type : public ofile_buffer<file_page_size,has_direct_io> {
+		typedef ofile_buffer<file_page_size,has_direct_io> base_buffer;
         empty_page_type() : base_buffer() {
-            std::memset(base_buffer::data,0,page_size);
+            std::memset(base_buffer::data,0,file_page_size);
         }
     };
         
Modified: sandbox/transaction/boost/transact/log.hpp
==============================================================================
--- sandbox/transaction/boost/transact/log.hpp	(original)
+++ sandbox/transaction/boost/transact/log.hpp	2013-02-25 11:23:51 EST (Mon, 25 Feb 2013)
@@ -1,39 +1,44 @@
-//          Copyright Stefan Strasser 2009 - 2010.
+//          Copyright Stefan Strasser 2009 - 2013.
 // Distributed under 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)
 
 
+
+//TODO: rolling log files are always started at .1 currently.
+//is persistent needs a header in the log file the old logs can't be deleted
+//until a new one is created, so the log needs to start at .<old+1>
+//better solution is to don't use a header for this purpose but safe this info in
+//an extra file by persistent
+
 #ifndef BOOST_TRANSACT_LOG_HEADER_HPP
 #define BOOST_TRANSACT_LOG_HEADER_HPP
 
-#include <cstring>
-#include <string>
-#include <algorithm>
+#include <vector>
 #include <iterator>
-#include <set>
-#include <boost/mpl/bool.hpp>
-#include <boost/mpl/map.hpp>
-#include <boost/mpl/fold.hpp>
-#include <boost/mpl/insert.hpp>
-#include <boost/mpl/pair.hpp>
-#include <boost/mpl/at.hpp>
-#include <boost/mpl/size_t.hpp>
-#include <boost/filesystem.hpp>
+#include <algorithm>
+#include <boost/integer.hpp>
+#include <boost/optional/optional.hpp>
 #include <boost/lexical_cast.hpp>
-#include <boost/scoped_ptr.hpp>
-#include <boost/optional.hpp>
 #include <boost/assert.hpp>
-#include <boost/static_assert.hpp>
-#include <boost/thread/locks.hpp>
-#include <boost/utility/in_place_factory.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/deref.hpp>
+#include <boost/mpl/next.hpp>
+#include <boost/mpl/begin.hpp>
+#include <boost/mpl/integral_c.hpp>
+#include <boost/mpl/at.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/type_traits/is_same.hpp>
 #include <boost/transact/detail/sectorizing_file.hpp>
 #include <boost/transact/detail/aligning_file.hpp>
 #include <boost/transact/detail/buffering_file.hpp>
 #include <boost/transact/detail/syncing_file.hpp>
 #include <boost/transact/detail/filebuf_file.hpp>
-#include <boost/transact/detail/embedded_vector.hpp>
-
+#include <boost/transact/detail/file.hpp>
+#include <boost/transact/detail/file_iterator.hpp>
+#include <boost/transact/archive.hpp>
 
 namespace boost{
 namespace transact{
@@ -45,16 +50,16 @@
 static void get_existing_log_ids(OutputIterator out,std::string const &name){
     namespace fs=boost::filesystem;
     try{
-        fs::path dir=fs::path(name).remove_filename();
-        std::string filename=fs::path(name).filename();
+        std::string filename=fs::path(name).filename().native();
+        fs::path dir=fs::path(name).parent_path();
         fs::directory_iterator it;
         if(dir.empty()) it=fs::directory_iterator(".");
         else it=fs::directory_iterator(dir);
         for(;it != fs::directory_iterator();++it){
-            std::string foundfilename=it->path().filename();
+            std::string foundfilename=it->path().filename().native();
             if(foundfilename.substr(0,filename.length()+1) != filename+".") continue;
             std::string nrstring=foundfilename.substr(filename.length()+1);
-            unsigned int nr;
+            unsigned int nr=0;
             try{ nr=lexical_cast<unsigned int>(nrstring); } catch(...){ continue; }
             *out++=nr;
         }
@@ -62,6 +67,8 @@
         throw io_failure();
     }
 }
+
+/*
 static unsigned int get_next_log_id(std::string const &name){
     std::vector<unsigned int> ids;
     get_existing_log_ids(std::back_inserter(ids),name);
@@ -70,289 +77,374 @@
 
 static std::string get_log_filename(std::string const &name,unsigned int l){
     return name+'.'+lexical_cast<std::string>(l);
-}
+}*/
 
 }
 
 
-template<bool Sync>
-class olog_files{
-public:
-    olog_files(std::string const &name,unsigned int max_log_size)
-        : log_id(detail::get_next_log_id(name))
-        , rolling_(false)
-        , max_log_size(max_log_size)
-        , header_size(0)
-        , name(name)
-        , file(new file_type(detail::get_log_filename(name,log_id))){}
+namespace detail{
+
+template<class Entries>
+struct log_id_type{
+    typedef typename boost::uint_value_t<mpl::size<Entries>::value>::least type;
+};
+  
+template<class Iterator,class Entry,class Id>
+struct log_entry_id_iterator{
+    typedef typename mpl::eval_if<
+        is_same<typename mpl::deref<Iterator>::type,Entry>,
+        Id,
+	log_entry_id_iterator<
+	    typename mpl::next<Iterator>::type,
+	    Entry,
+	    mpl::integral_c<typename Id::value_type,Id::value+1>
+	>
+    >::type type;
+};
+
+//don't use mpl::distance, so Entries can be a ForwardSequence
+template<class Entries,class Entry>
+struct log_entry_id : log_entry_id_iterator<
+        typename mpl::begin<Entries>::type,
+	Entry,
+	mpl::integral_c<typename log_id_type<Entries>::type,1>
+    >::type{};
+}
 
-    //Archive interface
+template<class Entries,class File>
+class olog{
+public:
+    typedef typename detail::log_id_type<Entries>::type id_type;
+    explicit olog(File &file) : file(file){}
     template<class T>
-    olog_files &operator<<(T const &t){
-        this->file->save(t);
+    olog &operator<<(T const &t){
+        typedef detail::file_output_iterator<File> it_type;
+        it_type it(this->file);
+        char_oarchive<it_type> archive(it);
+        archive << detail::log_entry_id<Entries,T>::type::value;
+	archive << t;
         return *this;
     }
-    template<class T>
-    olog_files &operator&(T const &t){ return this->operator<<(t); }
-    template<class Size>
-    void save_binary(void const *data,Size size){
-        this->file->save_binary(data,size);
-    }
-    typedef mpl::true_ is_saving;
-    typedef mpl::false_ is_loading;
-
+protected:
+    File &file;
+};
 
-    bool overflow() const{
-        return (!this->rolling())
-            && (this->file->position() > this->max_log_size + this->header_size);
+namespace detail{
+ 
+template<class Archive,class Entries,class F>
+class ilog_dispatcher{
+    typedef typename detail::log_id_type<Entries>::type id_type;
+public:
+    ilog_dispatcher(){
+        this->init<0>(mpl::false_());
     }
-
-    bool rolling() const{ return this->rolling_; }
-    template<class Header>
-    void begin_roll(Header header){
-        BOOST_ASSERT(!this->rolling());
-        this->rolling_=true;
-        try{
-            //first construct the new log and then replace it. if construction
-            //of new log file fails, there must still be a valid file in this->file
-            //for other threads:
-            this->file.reset(new file_type(detail::get_log_filename(this->name,this->log_id+1)));
-            ++this->log_id;
-            header();
-            this->header_size=this->file->position();
-        }catch(...){
-            this->rolling_=false;
-            throw;
-        }
+    void operator()(id_type id,Archive &ar,F const &f) const{
+        if(id <= 0 || id > mpl::size<Entries>::value) throw io_failure();
+        (*this->functions[id-1])(ar,f);
     }
-
-    void commit_roll(){
-        BOOST_ASSERT(this->rolling_);
-        this->flush();
-        this->sync(); //TODO optimization: outside of lock
-        //TODO optimization: don't remove, but invalidate and rename to the next log. increases
-        //performance of writing ahead if the file is already fully "allocated".
-
-        try{
-            filesystem::remove(detail::get_log_filename(this->name,this->log_id-1));
-        }catch(...){
-            throw io_failure();
-        }
-        this->rolling_=false;
+private:
+    template<id_type Id>
+    void init(mpl::false_){
+        this->functions[Id]=&dispatch<typename mpl::at_c<Entries,Id>::type>;
+        this->init<Id+1>(mpl::bool_<(Id+1 == mpl::size<Entries>::value)>());
     }
-
-    void flush(){
-        this->file->flush();
+    template<id_type Id>
+    void init(mpl::true_){}
+    template<class T>
+    static void dispatch(Archive &ar,F const &f){
+        T t; //FIXME requires log entries to be default constructible
+	ar >> t;
+	f(t);
     }
-    void sync(){
-        this->file->sync();
+    typedef void (*function_type)(Archive &,F const &f);
+    function_type functions[mpl::size<Entries>::value];
+};
+  
+  
+}
+
+template<class Entries,class File>
+class ilog{
+public:
+    typedef typename detail::log_id_type<Entries>::type id_type;
+    explicit ilog(File &file) : file(file){}
+    template<class F>
+    ilog &operator>>(F const &f){
+        typedef detail::file_input_iterator<File> it_type;
+        typedef char_iarchive<it_type> archive_type;
+        static detail::ilog_dispatcher<archive_type,Entries,F> const dispatch;
+        
+	it_type it(this->file);
+	archive_type archive(it,it_type());
+	id_type id=0;
+        archive >> id;
+	dispatch(id,archive,f);
+	return *this;
     }
 private:
-    typedef typename mpl::if_c<
-        Sync,
-        detail::sectorizing_seq_ofile<
-            detail::aligning_seq_ofile<
-                detail::buffering_seq_ofile<
-                    detail::syncing_seq_ofile,
-                    8192
-                >
-            >
-        >,
-        detail::buffering_seq_ofile<
-            detail::filebuf_seq_ofile,
-            8192
-        >
-    >::type file_type;
-
-    unsigned int log_id;
-    bool rolling_;
-    typename file_type::size_type max_log_size;
-    typename file_type::size_type header_size;
-    std::string const name;
-    scoped_ptr<file_type> file; //no optional. see begin_roll()
+    File &file;
 };
 
-template<bool Sync>
-class otransaction_log_files : public olog_files<Sync>{
-private:
+template<class Entries,class RollingLogfile,class Id=unsigned int>
+class transaction_olog
+    : public olog<Entries,RollingLogfile>{
+    typedef olog<Entries,RollingLogfile> base_type;
     struct detail{
-        typedef unsigned int transaction;
+        struct null_header{};
     };
 public:
-    typedef typename detail::transaction transaction;
-    otransaction_log_files(std::string const &name,std::size_t max_log_size)
-        : olog_files<Sync>(name,max_log_size)
-        , next_tx(1)
-        , open_transactions(0)
-        , rolled_transactions(0)
-        , roll_cutoff(0){}
-
+    typedef Id id_type;
+    transaction_olog(RollingLogfile &file,std::size_t max_log_size=100*1024*1024)
+        : base_type(file)
+        , max_log_size(max_log_size)
+	, next_tx(1)
+	, open_txs(0)
+	, rolled_txs(0)
+	, roll_cutoff(0){
+      
+    }
+    Id begin_transaction(){
+        return this->begin_transaction(detail::null_header()); 
+    }
     template<class Header>
-    typename detail::transaction begin_transaction(Header header){
-        transaction tx=this->next_tx++;
-        if(this->overflow()){
-            this->begin_roll(header);
-            this->roll_cutoff=tx;
-            BOOST_ASSERT(this->rolled_transactions==0);
-            this->rolled_transactions=this->open_transactions;
-            this->open_transactions=0;
-        }
-        BOOST_ASSERT(!this->rolling() || tx >= this->roll_cutoff);
-        ++this->open_transactions;
-        return tx;
+    Id begin_transaction(Header const &header){
+        Id tx=this->next_tx++;
+	if(!this->rolling() && this->file.position() >= this->max_log_size){
+	    //don't roll a second time until all transactions started in the old log
+	    //are closed, RollingLogfile only guarantees a minimum of 2 existing files
+	    this->file.roll();
+	    this->roll_cutoff=tx;
+	    BOOST_ASSERT(this->rolled_txs==0);
+	    this->rolled_txs=this->open_txs;
+	    this->open_txs=0;
+	    this->write_header(header);
+	}
+	BOOST_ASSERT(!this->rolling() || tx >= this->roll_cutoff);
+	++this->open_txs;
+	return tx;
     }
-    void end_transaction(transaction tx){
+    void end_transaction(Id tx){
         if(this->rolling() && tx < this->roll_cutoff){
-            BOOST_ASSERT(this->rolled_transactions > 0);
-            --this->rolled_transactions;
-            if(this->rolled_transactions==0){
-                //all transactions that were begun in the old, rolled, log have ended.
-                this->commit_roll();
-            }
-        }else{
-            BOOST_ASSERT(this->open_transactions > 0);
-            --this->open_transactions;
-        }
+	    BOOST_ASSERT(this->rolled_txs > 0);
+	    --this->rolled_txs;
+	    //if rolled_txs is now 0 all transactions started in the old, rolled, log have
+	    //successfully ended. rolling() now returns false, removing the old log file
+	    //and thus another log roll is safe from now on
+	}else{
+	    BOOST_ASSERT(this->open_txs > 0);
+	    --this->open_txs;
+	}
     }
+    bool rolling() const{ return this->rolled_txs > 0; }
 private:
-    transaction next_tx;
-    std::size_t open_transactions;
-    std::size_t rolled_transactions;
-    transaction roll_cutoff;
+    void write_header(detail::null_header const &){}
+    template<class Header>
+    void write_header(Header const &header){
+        typedef detail::file_output_iterator<RollingLogfile> it_type;
+        it_type it(this->file);
+        char_oarchive<it_type> archive(it);
+        archive << detail::log_entry_id<Entries,Header>::type::value;
+        archive << header;
+    }
+  
+    std::size_t const max_log_size;
+    Id next_tx;
+    std::size_t open_txs, rolled_txs;
+    Id roll_cutoff;
 };
 
+namespace detail{
+  
+  
 template<bool Sync>
-class ilog_files{
+struct ologfile_type{
+    typedef typename mpl::if_c<
+      Sync,
+      detail::sectorizing_seq_ofile<
+	  detail::aligning_seq_ofile<
+	      detail::buffering_seq_ofile<
+		  detail::syncing_seq_ofile<
+		      detail::ofile<false> //FIXME argument. why is this a parameter?
+		  >,
+		  8192
+	      >
+	  >
+      >,
+      detail::buffering_seq_ofile<
+	  detail::filebuf_seq_ofile,
+	  8192
+      >
+    >::type type;
+};
+
+template<bool Sync>
+struct ilogfile_type{
+    typedef typename mpl::if_c<
+      Sync,
+      detail::sectorizing_seq_ifile<
+	  detail::filebuf_seq_ifile
+      >,
+      detail::filebuf_seq_ifile
+    >::type type;
+};
+  
+  
+}
+
+template<bool Sync>
+class ologfile : public detail::ologfile_type<Sync>::type{
+    typedef typename detail::ologfile_type<Sync>::type base_type;
 public:
-    explicit ilog_files(std::string const &name) : name(name){
-        detail::get_existing_log_ids(std::inserter(this->log_ids,this->log_ids.begin()),name);
-        this->current=this->log_ids.begin();
-    
-        //although the current implementation of log rolling only produces a maximum of
-        //2 logs at a time, an aborted recovery may have created another log. work through all of them.
-    
-        for(log_ids_type::const_iterator next=this->log_ids.begin();next!=this->log_ids.end();){
-            log_ids_type::const_iterator it=next++;
-            if(next != this->log_ids.end() && (*it != *next-1)) throw io_failure();
-        }
-    
-        if(this->current != this->log_ids.end()){
-            this->file=in_place(detail::get_log_filename(this->name,*this->current));
-        }
-    }
-    //Archive interface
-    template<class T>
-    ilog_files &operator>>(T const &t){
-        this->file->load(t);
-        return *this;
+    explicit ologfile(std::string const &name) : base_type(name){}
+};
+
+template<bool Sync>
+class ilogfile : public detail::ilogfile_type<Sync>::type{
+    typedef typename detail::ilogfile_type<Sync>::type base_type;
+public:
+    explicit ilogfile(std::string const &name) : base_type(name){}  
+};
+
+namespace detail{
+
+template<class File>
+class rolling_ologfile_base{
+public:
+    typedef typename File::size_type size_type;
+    explicit rolling_ologfile_base(std::string const &name)
+        : name(name)
+	, logid(1){
+        this->files[0]=in_place(this->name+".1");
+	this->active_=&this->files[0];
     }
-    template<class T>
-    ilog_files &operator&(T const &t){ return this->operator>>(t); }
     template<class Size>
-    void load_binary(void *data,Size size){
-        this->file->load_binary(data,size);
+    void write(void const *data,Size s){
+        this->active()->write(data,s);
     }
-    typedef mpl::true_ is_saving;
-    typedef mpl::false_ is_loading;
-    void remove(){
-        try{
-            for(log_ids_type::const_iterator it=this->log_ids.begin();it != this->log_ids.end();++it){
-                filesystem::remove(detail::get_log_filename(this->name,*it));
-                //FIXME sync directory entry. the delete of an older log
-                //must have reached disk before a newer log is deleted.
-            }
-        }catch(...){
-            throw io_failure();
-        }
+    void flush(){
+        this->active()->flush();
     }
-private:
-    typedef std::set<unsigned int> log_ids_type;
-    log_ids_type log_ids;
-    log_ids_type::const_iterator current;
+    void sync(){
+        this->active()->sync();
+    }
+    typename File::size_type position() const{ return this->active()->position(); }
+protected:
+    optional<File> &active(){
+        return *this->active_;
+    }
+    optional<File> const &active() const{
+        return *this->active_;
+    }
+    optional<File> &inactive(){
+        return this->active_ == &this->files[0] ? this->files[1] : this->files[0];
+    }
+  
     std::string const name;
-    typedef typename mpl::if_c<
-        Sync,
-        detail::sectorizing_seq_ifile<detail::filebuf_seq_ifile>,
-        detail::filebuf_seq_ifile
-    >::type file_type;
-    optional<file_type> file;
-};
-
-namespace detail{
-
-template<class Entry,class State>
-struct make_entry_pair{
-    typedef mpl::pair<
-        Entry,
-        typename mpl::size<State>::type
-    > type;
-};
-
-template<class Vector>
-struct invert_vector{
-    typedef typename mpl::fold<
-        Vector,
-        mpl::map0<>,
-        mpl::insert<
-            mpl::_1,
-            make_entry_pair<
-                mpl::_2,
-                mpl::_1
-            >
-        >
-    >::type type;
+    unsigned int logid;
+    optional<File> files[2];
+    optional<File> *active_;
 };
 
 }
 
-template<class Entries,bool Sync>
-class olog{
-private:
-    typedef typename detail::invert_vector<Entries>::type ids;
+template<class File>
+class rolling_ologfile
+    : public detail::rolling_ologfile_base<File>{
+    typedef detail::rolling_ologfile_base<File> base_type;
 public:
-    typedef unsigned char id_type;
-    explicit olog(olog_files<Sync> &files)
-        : files(files)
-        , id_offset(0){}
-
-    template<class T>
-    id_type id() const{
-        return mpl::at<ids,T>::type::value + this->id_offset;
+    explicit rolling_ologfile(std::string const &name)
+        : base_type(name){}
+    void roll(){
+        //close old log to cause write exceptions, which would be ignored when destructing:
+        //TODO optimization close() flushes/syncs the old logfile. one could also keep the old
+        //log open until an explicit request to flush/sync the log causes all log files
+        //to flush/sync
+        this->active()->close();
+	//use 2 optional<>s because the new file must be fully constructed to replace the old one.
+        //if construction fails there must be a valid old log file in this->active, and files
+        //are not swap()able:
+        optional<File> &newlog=this->inactive();
+	BOOST_ASSERT(!newlog);
+	newlog=in_place(this->name+'.'+lexical_cast<std::string>(this->logid+1));
+	this->active_=&newlog; ++this->logid;
+	this->inactive().reset();
     }
+};
 
-    template<class T>
-    olog &operator<<(T const &t){
-        id_type const tid=this->id<T>();
-        static std::size_t const size=sizeof(tid) + sizeof(t);
-        unsigned char data[size];
-        std::memcpy(data,&tid,sizeof(tid));
-        std::memcpy(data+sizeof(tid),&t,sizeof(t));
-        this->files.save_binary(data,mpl::size_t<size>());
-        return *this;
+template<class File>
+class alternating_ologfile
+    : public detail::rolling_ologfile_base<File>{
+    typedef detail::rolling_ologfile_base<File> base_type;
+public:
+    explicit alternating_ologfile(std::string const &name)
+        : base_type(name){}
+    void roll(){
+        this->active()->close();
+        optional<File> &newlog=this->inactive();
+	std::string const newname=this->name+'.'+lexical_cast<std::string>(this->logid+1);
+	if(!newlog) newlog=in_place(newname);
+	else newlog->reopen(newname);
+	this->active_=&newlog; ++this->logid;
     }
-    struct archive{
-        explicit archive(olog &log) : log(log){}
-        template<class T>
-        archive &operator<<(T const &t){
-            this->log.files << t;
-            return *this;
-        }
-        template<class T>
-        archive &operator&(T const &t){ return this->operator<<(t); }
-        template<class Size>
-        void save_binary(void const *data,Size size){
-            this->log.files.save_binary(data,size);
+};
+
+template<class File>
+class rolling_ilogfile{
+public:
+    typedef typename File::size_type size_type;
+    explicit rolling_ilogfile(std::string const &name)
+        : name(name){
+        detail::get_existing_log_ids(std::back_inserter(this->ids),this->name);
+	std::sort(this->ids.begin(),this->ids.end());
+	
+	//must be a contiguous sequence of files:
+        for(ids_type::const_iterator next=this->ids.begin();next!=this->ids.end();){
+            ids_type::const_iterator it=next++;
+            if(next != this->log_ids.end() && (*it != *next-1)) throw io_failure();
         }
-        typedef mpl::true_ is_saving;
-        typedef mpl::false_ is_loading;
-    private:
-        olog &log;
-    };
+    	
+	this->current=this->ids.begin();
+	this->open();
+    }
+    template<class Size>
+    void read(void *data,Size s){
+        if(!this->file) throw eof_exception();
+        try{
+            this->file->read(data,s);
+	}catch(eof_exception &){
+	    //eof means nothing was read, otherwise io_exception is thrown. retry in next file
+	    ++this->current;
+	    this->open();
+	    this->read(data,s);
+	}
+    }
+    void remove(){
+        for(ids_type::const_iterator it=this->ids.begin();it!=this->ids.end();++it){
+	    filesystem::remove(this->name+'.'+lexical_cast<std::string>(*it));
+	}
+    }
 private:
-    olog_files<Sync> &files;
-    id_type id_offset;
+    void open(){
+        this->file.reset();
+	if(this->current != this->ids.end()){
+    	    this->file=in_place(this->name+'.'+lexical_cast<std::string>(*this->current));
+	}
+    }
+    std::string const name;
+    optional<File> file;
+    typedef std::vector<unsigned int> ids_type;
+    ids_type ids;
+    ids_type::const_iterator current;
 };
 
+
+
+
+/*
+ * 
+ * old class (needs rewrite) that buffers log writes so the log itself only needs to be locked
+ * on flush. useful only when 2 logs are interlaced into the same file?
+
 template<class Log,class Lockable,std::size_t Size>
 class olog_buffer{
 public:
@@ -426,7 +518,9 @@
     detail::embedded_vector<char,Size,false> buffer;
 };
 
+*/
 
+  
 }
 }
 
Modified: sandbox/transaction/boost/transact/object_access.hpp
==============================================================================
--- sandbox/transaction/boost/transact/object_access.hpp	(original)
+++ sandbox/transaction/boost/transact/object_access.hpp	2013-02-25 11:23:51 EST (Mon, 25 Feb 2013)
@@ -24,6 +24,7 @@
 
 #include <boost/serialization/serialization.hpp>
 #include <boost/serialization/version.hpp>
+#include <boost/archive/impl/archive_serializer_map.ipp>
 
 #endif
 
@@ -238,11 +239,21 @@
 
 
 template<class Archive,class T>
+void serialize(Archive &ar,T &t,mpl::true_ saving){
+    archive::save(ar.serialization_archive(),t);
+}
+template<class Archive,class T>
+void serialize(Archive &ar,T &t,mpl::false_ saving){
+    archive::load(ar.serialization_archive(),t);
+}
+
+
+template<class Archive,class T>
 void serialize(Archive &ar,T &t,constructed_tag){
 #ifdef NO_BOOST_SERIALIZATION
     sizeof(boost_serialization_required<T>);
 #else
-    serialization::serialize_adl(ar.serialization_archive(),t,serialization::version<T>::value);
+    detail::serialize(ar,t,typename Archive::is_saving());
 #endif
 }