|
Boost-Commit : |
From: technews_at_[hidden]
Date: 2007-12-30 17:21:25
Author: turkanis
Date: 2007-12-30 17:21:24 EST (Sun, 30 Dec 2007)
New Revision: 42380
URL: http://svn.boost.org/trac/boost/changeset/42380
Log:
added Borland 5.8.2 workaround and Cygwin optimization; factored use of mapped_file out of create_large_file() into map_large_file; added documentation
Text files modified:
branches/iostreams_dev/libs/iostreams/test/large_file_test.cpp | 107 ++++++++++++++++++++++++++++++++-------
1 files changed, 88 insertions(+), 19 deletions(-)
Modified: branches/iostreams_dev/libs/iostreams/test/large_file_test.cpp
==============================================================================
--- branches/iostreams_dev/libs/iostreams/test/large_file_test.cpp (original)
+++ branches/iostreams_dev/libs/iostreams/test/large_file_test.cpp 2007-12-30 17:21:24 EST (Sun, 30 Dec 2007)
@@ -16,6 +16,7 @@
#include <ctime>
#include <string>
#include <boost/config.hpp> // BOOST_STRINGIZE
+#include <boost/detail/workaround.hpp>
#include <boost/iostreams/detail/config/rtl.hpp>
#include <boost/iostreams/detail/config/windows_posix.hpp>
#include <boost/iostreams/detail/execute.hpp>
@@ -26,6 +27,7 @@
#include <boost/lexical_cast.hpp>
#include <boost/test/test_tools.hpp>
#include <boost/test/unit_test.hpp>
+#include <iostream>
// OS-specific headers for low-level i/o.
@@ -148,7 +150,7 @@
#endif
- // Fetch last mod date of this file
+ // Fetch last mod date of this file ("large_file_test.cpp")
string timestamp =
"$Date$";
if (timestamp.size() != 53) { // Length of auto-generated SVN timestamp
@@ -169,13 +171,47 @@
}
// If last commit was two days or more before file timestamp, existing
- // file is okay; otherwise, it must be regenerated
+ // file is okay; otherwise, it must be regenerated (the two-day window
+ // compensates for time zone differences)
return difftime(last_mod, mktime(&commit)) >= 60 * 60 * 48;
}
+//------------------Definition of map_large_file------------------------------//
+
+// Initializes the large file by mapping it in small segments. This is an
+// optimization for Win32; the straightforward implementation using WriteFile
+// and SetFilePointer (see the Borland workaropund below) is painfully slow.
+bool map_large_file()
+{
+ for (stream_offset z = 0; z <= 8; ++z) {
+ try {
+ mapped_file_params params;
+ params.path = file_name;
+ params.offset = z * gigabyte;
+ params.length = 1;
+ params.mode = BOOST_IOS::out;
+ mapped_file file(params);
+ file.begin()[0] = z + 1;
+ } catch (const std::exception&) {
+ remove_large_file();
+ return false;
+ }
+ }
+ return true;
+}
+
//------------------Definition of create_large_file---------------------------//
-// Creates and initializes the large file if it does not already exist
+// Creates and initializes the large file if it does not already exist. The file
+// looks like this:
+//
+// 0 1GB 2GB 3GB 4GB 5GB 6GB 7GB 8GB
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// 1.....2.....3.....4.....5.....6.....7.....8.....9
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//
+// where the characters 1-9 appear at offsets that are multiples of 1GB and the
+// dots represent uninitialized data.
bool create_large_file()
{
// If file exists, has correct size, and is recent, we're done
@@ -199,11 +235,12 @@
return false;
// Set file pointer
- LARGE_INTEGER length;
- length.HighPart = 0;
- length.LowPart = 0;
- length.QuadPart = file_size;
- if (!SetFilePointerEx(hnd, length, NULL, FILE_BEGIN)) {
+ LONG off_low = static_cast<LONG>(file_size & 0xffffffff);
+ LONG off_high = static_cast<LONG>(file_size >> 32);
+ if ( SetFilePointer(hnd, off_low, &off_high, FILE_BEGIN) ==
+ INVALID_SET_FILE_POINTER &&
+ GetLastError() != NO_ERROR )
+ {
CloseHandle(hnd);
remove_large_file();
return false;
@@ -216,27 +253,47 @@
return false;
}
+# if !BOOST_WORKAROUND(__BORLANDC__, == 0x582)
+
// Close handle; all further access is via mapped_file
CloseHandle(hnd);
// Initialize file data
- for (int z = 0; z <= 8; ++z) {
- try {
- mapped_file_params params;
- params.path = file_name;
- params.offset = z * gigabyte;
- params.length = 1;
- params.mode = BOOST_IOS::out;
- mapped_file file(params);
- file.begin()[0] = z + 1;
- } catch (...) {
+ return map_large_file();
+
+# else // Borland 5.8.2
+
+ // Initialize file data (very slow, even though only 9 writes are required)
+ for (stream_offset z = 0; z <= 8; ++z) {
+
+ // Seek
+ LONG off_low = static_cast<LONG>((z * gigabyte) & 0xffffffff); // == 0
+ LONG off_high = static_cast<LONG>((z * gigabyte) >> 32);
+ if ( SetFilePointer(hnd, off_low, &off_high, FILE_BEGIN) ==
+ INVALID_SET_FILE_POINTER &&
+ GetLastError() != NO_ERROR )
+ {
+ CloseHandle(hnd);
+ remove_large_file();
+ return false;
+ }
+
+ // Write a character
+ char buf[1] = { z + 1 };
+ DWORD result;
+ BOOL success = WriteFile(hnd, buf, 1, &result, NULL);
+ if (!success || result != 1) {
+ CloseHandle(hnd);
+ remove_large_file();
return false;
}
}
// Close file
+ CloseHandle(hnd);
return true;
+# endif // Borland 5.8.2 workaround
#else // #ifdef BOOST_IOSTREAMS_WINDOWS
// Create file
@@ -258,6 +315,8 @@
return false;
}
+# ifndef __CYGWIN__
+
// Initialize file data
for (int z = 0; z <= 8; ++z) {
@@ -284,6 +343,16 @@
// Close file
BOOST_IOSTREAMS_FD_CLOSE(fd);
return true;
+
+# else // Cygwin
+
+ // Close descriptor; all further access is via mapped_file
+ BOOST_IOSTREAMS_FD_CLOSE(fd);
+
+ // Initialize file data
+ return map_large_file();
+
+# endif
#endif // #ifdef BOOST_IOSTREAMS_WINDOWS
}
@@ -326,7 +395,7 @@
// Prepare file and file descriptor
large_file large;
file_descriptor_source file;
- BOOST_CHECK_MESSAGE(large.exists(), "failed creating file");
+ BOOST_REQUIRE_MESSAGE(large.exists(), "failed creating file");
BOOST_CHECK_NO_THROW(file.open(large.path(), BOOST_IOS::binary));
// Test seeking using ios_base::beg
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