Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r62168 - in sandbox/transaction: boost/transact/detail libs/transact/perf libs/transact/test
From: bob.s.walters_at_[hidden]
Date: 2010-05-23 22:18:19


Author: bobwalters
Date: 2010-05-23 22:18:17 EDT (Sun, 23 May 2010)
New Revision: 62168
URL: http://svn.boost.org/trac/boost/changeset/62168

Log:
Win32 support

Added:
   sandbox/transaction/libs/transact/perf/filewrite.cpp (contents, props changed)
Text files modified:
   sandbox/transaction/boost/transact/detail/aligning_file.hpp | 2
   sandbox/transaction/boost/transact/detail/buffering_file.hpp | 21 ++++++-
   sandbox/transaction/boost/transact/detail/file.hpp | 109 +++++++++++++++++++++++++++++++++++++++
   sandbox/transaction/boost/transact/detail/syncing_file.hpp | 69 ++++--------------------
   sandbox/transaction/libs/transact/test/Jamfile.v2 | 10 ++-
   5 files changed, 147 insertions(+), 64 deletions(-)

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 2010-05-23 22:18:17 EDT (Sun, 23 May 2010)
@@ -114,7 +114,7 @@
         static std::size_t const size=max_alignment - sector_size;
         static std::size_t const sectors = size / sector_size;
         unsigned char data[size];
- static void clear_sector(char *sec){
+ static void clear_sector(unsigned char *sec){
             sec[0]=0x80;
             sec[sector_size-1]=0x80;
         }

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 2010-05-23 22:18:17 EDT (Sun, 23 May 2010)
@@ -22,7 +22,15 @@
     typedef typename Base::size_type size_type;
     explicit buffering_seq_ofile(std::string const &name)
         : base(name)
- , size(0){}
+ , size(0){
+#ifdef _WIN32
+ // support possibility that Base is using unbuffered I/O
+ // requiring specific buffer memory alignment
+ int alignment=1; // largest power of 2 >= Capacity
+ for (std::size_t i=Capacity; (i>>=1); alignment<<=1 )
+ buffer = (char*)_aligned_malloc(Capacity, alignment);
+#endif
+ }
     template<class Size>
     void write(void const *data,Size s){
         if(this->size + s <= Capacity){
@@ -49,6 +57,9 @@
             std::cerr << "ignored exception" << std::endl;
 #endif
         }
+#ifdef _WIN32
+ _aligned_free(buffer);
+#endif
     }
 private:
     void write_overflow(void const *data,std::size_t s){
@@ -71,8 +82,12 @@
     }
 
     Base base;
- char buffer[Capacity];
- std::size_t size;
+#ifdef _WIN32
+ char *buffer;
+#else
+ char buffer[Capacity];
+#endif
+ std::size_t size;
 };
 
 

Modified: sandbox/transaction/boost/transact/detail/file.hpp
==============================================================================
--- sandbox/transaction/boost/transact/detail/file.hpp (original)
+++ sandbox/transaction/boost/transact/detail/file.hpp 2010-05-23 22:18:17 EDT (Sun, 23 May 2010)
@@ -1,6 +1,7 @@
 #ifndef BOOST_TRANSACT_DETAIL_FILE_HPP
 #define BOOST_TRANSACT_DETAIL_FILE_HPP
 
+#include <boost/filesystem.hpp>
 #include <boost/transact/exception.hpp>
 
 namespace boost{
@@ -9,9 +10,115 @@
 
 struct eof_exception : io_failure{};
 
+
+#ifdef _WIN32
+#include <Windows.h>
+#include <WinBase.h>
+
+// low-level ofile representation for WIN32
+class ofile {
+public:
+ typedef unsigned int size_type;
+
+ void* filedes;
+
+ ofile(std::string const &name) : filedes(INVALID_HANDLE_VALUE) {
+ unsigned long access = GENERIC_READ | GENERIC_WRITE;
+ unsigned long creation_flags = OPEN_ALWAYS;
+ unsigned long flags = FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH;
+ this->filedes = CreateFileA(name.c_str(), access,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ 0, creation_flags, flags, 0);
+ if (this->filedes == INVALID_HANDLE_VALUE ) {
+ throw io_failure();
+ }
+ std::cerr << "File opened" << std::endl;
+ }
+
+ ~ofile() {
+ if(this->filedes != INVALID_HANDLE_VALUE) CloseHandle(this->filedes);
+ }
+
+ void seek(size_type const &s) {
+ LARGE_INTEGER loc;
+ loc.QuadPart = s;
+ if(SetFilePointerEx(this->filedes, loc, NULL, FILE_BEGIN) == 0) {
+ std::cerr << "SetFilePointerEx == 0" << std::endl;
+ throw io_failure();
+ }
+ }
+
+ size_type write(const char *data, size_type const &size) {
+ DWORD written;
+ if(WriteFile(this->filedes, data, size, &written, 0) == 0) {
+ std::cerr << "WriteFile == 0" << std::endl;
+ throw io_failure();
+ }
+ return (size_type)written;
+ }
+
+ void sync() { }
+};
+
+#else
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#ifndef _POSIX_SYNCHRONIZED_IO
+#error no POSIX synchronized IO available
+#endif
+
+// low-level ofile for Linux/Unix
+class ofile {
+public:
+ typedef unsigned int size_type;
+
+ 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() {
+ if(this->filedes != -1) ::close(this->filedes);
+ }
+
+ void seek(size_type const &s) {
+ if(::lseek(this->filedes,s,SEEK_SET) != off_t(s)) throw io_failure();
+ }
+
+ size_type write(const char *data, size_type const &size) {
+ if(::write(this->filedes,data,size) != ssize_t(size)) throw io_failure();
+ return size;
+ }
+
+ void sync() {
+#ifdef linux
+ if(::fdatasync(this->filedes) != 0) throw io_failure();
+#else //multiple sources say fdatasync is not safe on other systems
+ if(::fsync(this->filedes) != 0) throw io_failure();
+#endif
+ }
+};
+
+#endif
+
 }
 }
 }
 
-
 #endif

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 2010-05-23 22:18:17 EDT (Sun, 23 May 2010)
@@ -14,22 +14,7 @@
 #include <boost/static_assert.hpp>
 #include <boost/assert.hpp>
 #include <boost/config.hpp>
-
-#ifdef WIN32
-
-//TODO
-
-#else
-
-#include <unistd.h>
-#include <fcntl.h>
-
-#ifndef _POSIX_SYNCHRONIZED_IO
-#error no POSIX synchronized IO available
-#endif
-
-#endif
-
+#include <boost/transact/detail/file.hpp>
 
 namespace boost{
 namespace transact{
@@ -45,25 +30,21 @@
     void sync();
 private:
     size_type pos;
-#ifdef WIN32
-#else
-public:
- ~syncing_seq_ofile(){
- if(this->filedes != -1) ::close(this->filedes);
- }
+ ofile filedes;
+
 private:
     void write_ahead(size_type const &s){
         BOOST_ASSERT(s % write_ahead_size == 0);
         if(this->pos != s){
- if(::lseek(this->filedes,s,SEEK_SET) != off_t(s)) throw io_failure();
+ filedes.seek(s);
         }
         char data[write_page_size]; memset(data,0,write_page_size);
         BOOST_STATIC_ASSERT(write_ahead_size % write_page_size == 0);
         for(std::size_t c=0;c<write_ahead_size / write_page_size;++c){
- if(::write(this->filedes,data,write_page_size) != ssize_t(write_page_size)) throw io_failure();
+ filedes.write(data,write_page_size);
         }
- if(::fsync(this->filedes) != 0) throw io_failure();
- if(::lseek(this->filedes,this->pos,SEEK_SET) != off_t(this->pos)) throw io_failure();
+ filedes.sync();
+ filedes.seek(this->pos);
     }
     void write_ahead(size_type const &start,size_type const &end){
         BOOST_ASSERT(start % write_ahead_size == 0);
@@ -73,31 +54,12 @@
 
     static std::size_t const write_ahead_size=10*1024*1024;
     static std::size_t const write_page_size=4096;
-
- int filedes;
-#endif
 };
 
-#ifdef WIN32
-#else
-
 inline syncing_seq_ofile::syncing_seq_ofile(std::string const &name)
     : pos(0)
- , 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();
- }
+ , filedes(name)
+{
     this->write_ahead(0);
 }
 
@@ -110,24 +72,19 @@
         this->write_ahead(start,end);
     }
 
- ssize_t ret=::write(this->filedes,data,size);
+ std::size_t ret= filedes.write((char const *)data,size);
     if(ret > 0) this->pos+=ret;
- if(ret != ssize_t(size)) throw io_failure();
+ if(ret != std::size_t(size)) throw io_failure();
 }
 
 
 inline void syncing_seq_ofile::flush(){}
+
 inline void syncing_seq_ofile::sync(){
-#ifdef linux
- if(::fdatasync(this->filedes) != 0) throw io_failure();
-#else //multiple sources say fdatasync is not safe on other systems
- if(::fsync(this->filedes) != 0) throw io_failure();
-#endif
+ filedes.sync();
 }
 
 
-#endif
-
 }
 }
 }

Added: sandbox/transaction/libs/transact/perf/filewrite.cpp
==============================================================================
--- (empty file)
+++ sandbox/transaction/libs/transact/perf/filewrite.cpp 2010-05-23 22:18:17 EDT (Sun, 23 May 2010)
@@ -0,0 +1,58 @@
+/*
+ * filewrite.cpp
+ * transact
+ *
+ * Copyright Bob Walters 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)
+ */
+#include <iostream>
+
+#include <boost/transact/detail/aligning_file.hpp>
+#include <boost/transact/detail/buffering_file.hpp>
+#include <boost/transact/detail/sectorizing_file.hpp>
+#include <boost/transact/detail/syncing_file.hpp>
+
+static const int num_sets=100;
+static const int txns_per_set=1000;
+static const int txn_size=3000; // typical transaction log size
+static int total_txns = 0;
+static int total_bytes = 0;
+
+static char txn_buffer[ txn_size ]; // random data set
+
+using namespace boost::transact;
+
+typedef detail::sectorizing_seq_ofile<
+ detail::aligning_seq_ofile<
+ detail::buffering_seq_ofile<
+ detail::syncing_seq_ofile,
+ 8192
+ >
+ >
+ >
+ofile_t;
+
+
+void log_a_set(ofile_t &outfile) {
+ for (int i=0; i<txns_per_set; i++) {
+ outfile.write(txn_buffer, txn_size);
+ }
+ total_txns += txns_per_set;
+ total_bytes += (txns_per_set * txn_size);
+ std::cout << "Written " << total_txns << " txns, " << total_bytes << " bytes" << std::endl;
+}
+
+void filetest1() {
+ ofile_t outfile("filetest1.out");
+ for (int i=0; i<num_sets; i++) {
+ log_a_set(outfile);
+ }
+}
+
+int main(int, const char *[]){
+ filetest1();
+ return 0;
+}

Modified: sandbox/transaction/libs/transact/test/Jamfile.v2
==============================================================================
--- sandbox/transaction/libs/transact/test/Jamfile.v2 (original)
+++ sandbox/transaction/libs/transact/test/Jamfile.v2 2010-05-23 22:18:17 EDT (Sun, 23 May 2010)
@@ -25,7 +25,7 @@
         #<library>/boost/system//boost_system/<link>static
         #<include>.
         #<include>../../..
- #<include>$BOOST_ROOT
+ <include>$(BOOST_ROOT)
         #<threading>multi
         #<variant>debug
 
@@ -49,7 +49,11 @@
         [ run transaction_stack_unwind.cpp ]
     ;
 
-
+ alias filewriteperf
+ :
+ [ run ../perf/filewrite.cpp : : : <library>/boost//date_time <library>/boost//system <link>static ]
+ ;
+
     alias all
- : tm perf
+ : tm perf filewriteperf
     ;


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk