9507ee6c7d
64 bit binary compatible OSGA archive reader/writer using mixed stdio/iostream calls. But during this work I learned that it can be made in much simpler way. Attached is result of this new attempt. I hope its appropriate for inclusion into OSG codebase. It was compiled and tested with latest SVN OSG, Windows XP 32 bit and Windows Vista business 64 bit. OSG was built using VS 2005 Express SP1 for 32 bit environment and VS 2005 Std for 64 bit. --- Solution description (there were two problems involved): --- Problem 1: implicit conversions beetween file positions and 32 bit int. This could be considered a MS compiler bug because this 32 bit int was additionally implicitly converted to/from 64 bit. As far as I know compiler is allowed to make only one implict conversion (but maybe this rule does not refer to simple types). Its actually possible to address OSGA files above 4 GiB range using 32 bit windows iostreams. MS Iostreams in practice offer the same level of functionality as stdio functions. There are functions fsetpos and fgetpos in stdio lib which use 64 bit file pointers (fpos_t). These functions are internally called by seekp( streampos ), seekg( streampos ), tellp(), and tellg() methods. So its also possible to change and retrieve file postions using iostream calls. But the problem lies in implicit handling of streampos type. streampos type is actually a template class used as seekp, seekg parameter and returnd from tellp, tellg. Its capable of storing 64 bit file pointers. But streampos can be also converted to/from simple type streamoff. It has proper constructor and cast operator. In Win 32 environment streamoff is defined as long (~32 bit int). So when seekp, and tellp arent used with exact streampos objects but OSGA_Archive::pos_type complier makes implicit casts to 32 bit int types loosing important bits of information. So above problem could be easily handled by making conversion calls explicit. My code defines 2 functions used to convert back and forth beetwen 64 bit OSGA_Archive::pos_type and std::streampos objects: OSGA_Archive::pos_type ARCHIVE_POS( const std::streampos & pos ); std::streampos STREAM_POS( OSGA_Archive::pos_type & pos ); Rest of the OSGA implementation code was modified to call these conversions explicitly with seekp, seekg, tellp, tellg. --- Problem 2: seekp and seekg have two variants. Only one of these variants is actually 64 bit proof. When I solved my first problem and made use of explicit streampos conversion functions, OSGA archive was able to read my example 11 GiB archive. But there were still problems with write and append. I found that the reason for this was pair of seekp( 0, std::ios_base::end ) and tellp() calls. It turned out that use of seekp, seekg( offset, direction ) function variants was setting file pos pointer to EOF when file was larger than 4GiB. But I noticed that one arg seekp, seekg ( streampos ) versions worked correctly. So the solution was to change OSGA write logic a little, and replace seekp( offset, direction ) with seekp( absolute_pos ) calls. I achieved this by modifing IndexBlock write method to record and restore file pos after IndexBlock was written. This modification has the effect that put pointer is generally kept at the end of file, so there is no need to repostion to the end before writing the files. This allowed me to get rid of those problematic seekp( 0, std::ios_base::end ) calls. There was one place where I could not easily get rid of seekp( 0, std::ios_base::end ). It was situation where existing OSGA was opened for appending. I resolved this by computing file length by finding max position from index block and file block endings. Then I replaced former seekp( 0, std::ios_base::end ) with seekp( STREAM_POS( found_file_length ). --- Description of these changes may sound bit hacky but in practice these were fairly simple and straightforward modifications. I hope they pass your review. There is one complex preprocessor condition which I based on few lines taken from boost positioning.hpp. Boost licence does allow such reproduction. In case of problems this condition may be easily simplified to windows only implementation. " |
||
---|---|---|
applications | ||
CMakeModules | ||
doc/Doxyfiles | ||
examples | ||
include | ||
packaging/pkgconfig | ||
src | ||
VisualStudio | ||
Xcode | ||
AUTHORS.txt | ||
ChangeLog | ||
CMakeLists.txt | ||
configure | ||
genwrapper.conf | ||
LICENSE.txt | ||
NEWS.txt | ||
README.txt | ||
runexamples.bat |
Welcome to the OpenSceneGraph (OSG). For up-to-date information on the project, in-depth details on how to compile and run libraries and examples, see the documentation on the OpenSceneGraph website: http://www.openscenegraph.org For the impatient, read the simplified build notes below. Robert Osfield. Project Lead. 3rd October 2007. -- How to build the OpenSceneGraph =============================== The OpenSceneGraph uses the CMake build system to generate a platform-specific build environment. CMake reads the CMakeLists.txt files that you'll find throughout the OpenSceneGraph directories, checks for installed dependenciesand then generates the appropriate build system. If you don't already have CMake installed on your system you can grab it from http://www.cmake.org, use version 2.4.6 or later. Details on the OpenSceneGraph's CMake build can be found at: http://www.openscenegraph.org/projects/osg/wiki/Build/CMake Under unices (i.e. Linux, IRIX, Solaris, Free-BSD, HP-Ux, AIX, OSX) use the cmake or ccmake command-line utils, or use the included tiny configure script that'll run cmake for you. The configure script simply runs 'cmake . -DCMAKE_BUILD_TYPE=Release' to ensure that you get the best performance from your final libraries/applications. cd OpenSceneGraph ./configure make sudo make install Alternatively, you can create an out-of-source build directory and run cmake or ccmake from there. The advantage to this approach is that the temporary files created by CMake won't clutter the OpenSceneGraph source directory, and also makes it possible to have multiple independent build targets by creating multiple build directories. In a directory alongside the OpenSceneGraph use: mkdir build cd build cmake ../OpenSceneGraph -DCMAKE_BUILD_TYPE=Release make sudo make install Under Windows use the GUI tool CMakeSetup to build your VisualStudio files. The following page on our wiki dedicated to the CMake build system should help guide you through the process: http://www.openscenegraph.org/projects/osg/wiki/Support/PlatformSpecifics/VisualStudio Under OSX you can either use the CMake build system above, or use the Xcode projects that you will find in the OpenSceneGraph/Xcode directory. For further details on compilation, installation and platform-specific information read "Getting Started" guide: http://www.openscenegraph.org/projects/osg/wiki/Support/GettingStarted