1 /*==========================================================================
2 * Copyright (c) 2004 University of Massachusetts. All Rights Reserved.
4 * Use of the Lemur Toolkit for Language Modeling and Information Retrieval
5 * is subject to the terms of the software license set forth in the LICENSE
6 * file included with this software, and also available at
7 * http://www.lemurproject.org/license.html
9 *==========================================================================
15 // 15 November 2004 -- tds
19 #include "indri/indri-platform.h"
20 #include "indri/File.hpp"
25 #include <sys/types.h>
29 #include "lemur/Exception.hpp"
30 #include "indri/ScopedLock.hpp"
36 indri::file::File::File() :
38 _handle(INVALID_HANDLE_VALUE
)
49 indri::file::File::~File() {
57 bool indri::file::File::create( const std::string
& filename
) {
59 _handle
= ::CreateFile( filename
.c_str(),
60 GENERIC_READ
| GENERIC_WRITE
,
64 FILE_ATTRIBUTE_NORMAL
,
67 if( _handle
== INVALID_HANDLE_VALUE
)
68 LEMUR_THROW( LEMUR_IO_ERROR
, "Couldn't create: " + filename
);
72 _handle
= creat( filename
.c_str(), 0600 );
75 LEMUR_THROW( LEMUR_IO_ERROR
, "Couldn't create: " + filename
);
81 bool indri::file::File::open( const std::string
& filename
) {
83 _handle
= ::CreateFile( filename
.c_str(),
84 GENERIC_READ
| GENERIC_WRITE
,
88 FILE_ATTRIBUTE_NORMAL
,
91 if( _handle
== INVALID_HANDLE_VALUE
)
92 LEMUR_THROW( LEMUR_IO_ERROR
, "Couldn't open: " + filename
);
97 _handle
= ::open( filename
.c_str(), O_RDWR
);
99 _handle
= ::open( filename
.c_str(), O_LARGEFILE
| O_RDWR
);
103 LEMUR_THROW( LEMUR_IO_ERROR
, "Couldn't open: " + filename
);
109 bool indri::file::File::openRead( const std::string
& filename
) {
111 _handle
= ::CreateFile( filename
.c_str(),
116 FILE_ATTRIBUTE_NORMAL
,
119 if( _handle
== INVALID_HANDLE_VALUE
)
120 LEMUR_THROW( LEMUR_IO_ERROR
, "Couldn't open for reading: " + filename
);
125 _handle
= ::open( filename
.c_str(), O_RDONLY
);
127 _handle
= ::open( filename
.c_str(), O_LARGEFILE
| O_RDONLY
);
131 LEMUR_THROW( LEMUR_IO_ERROR
, "Couldn't open for reading: " + filename
);
137 bool indri::file::File::openTemporary( std::string
& fileName
) {
139 char name
[] = "/tmp/indriXXXXXX";
140 _handle
= ::mkstemp( name
);
144 LEMUR_THROW( LEMUR_IO_ERROR
, "Couldn't create temporary file." );
146 fileName
= tmpnam( NULL
);
153 size_t indri::file::File::read( void* buffer
, UINT64 position
, size_t length
) {
155 assert( _handle
!= INVALID_HANDLE_VALUE
);
157 indri::thread::ScopedLock
sl( _mutex
);
158 LARGE_INTEGER actual
;
160 LARGE_INTEGER largePosition
;
161 largePosition
.QuadPart
= position
;
163 result
= SetFilePointerEx( _handle
, largePosition
, &actual
, FILE_BEGIN
);
164 assert( largePosition
.QuadPart
== actual
.QuadPart
);
167 LEMUR_THROW( LEMUR_IO_ERROR
, "Failed to seek to some file position" );
170 result
= ::ReadFile( _handle
, buffer
, length
, &actualBytes
, NULL
);
173 LEMUR_THROW( LEMUR_IO_ERROR
, "Error when reading file" );
177 assert( _handle
> 0 );
178 ssize_t result
= ::pread( _handle
, buffer
, length
, position
);
181 LEMUR_THROW( LEMUR_IO_ERROR
, "Error when reading file" );
183 return size_t(result
);
187 size_t indri::file::File::write( const void* buffer
, UINT64 position
, size_t length
) {
192 assert( _handle
!= INVALID_HANDLE_VALUE
);
194 indri::thread::ScopedLock
sl( _mutex
);
195 LARGE_INTEGER actual
;
197 LARGE_INTEGER largePosition
;
198 largePosition
.QuadPart
= position
;
200 result
= SetFilePointerEx( _handle
, largePosition
, &actual
, FILE_BEGIN
);
201 assert( largePosition
.QuadPart
== actual
.QuadPart
);
204 LEMUR_THROW( LEMUR_IO_ERROR
, "Failed to seek to some file position" );
207 result
= ::WriteFile( _handle
, buffer
, length
, &actualBytes
, NULL
);
210 LEMUR_THROW( LEMUR_IO_ERROR
, "Error when writing file" );
214 assert( _handle
> 0 );
216 ssize_t result
= ::pwrite( _handle
, buffer
, length
, position
);
219 LEMUR_THROW( LEMUR_IO_ERROR
, "Error when writing file" );
221 return size_t(result
);
225 void indri::file::File::close() {
227 if( _handle
!= INVALID_HANDLE_VALUE
) {
228 ::CloseHandle( _handle
);
229 _handle
= INVALID_HANDLE_VALUE
;
239 UINT64
indri::file::File::size() {
241 if( _handle
== INVALID_HANDLE_VALUE
)
244 LARGE_INTEGER length
;
245 BOOL result
= ::GetFileSizeEx( _handle
, &length
);
248 LEMUR_THROW( LEMUR_IO_ERROR
, "Got an error while trying to retrieve file size" );
250 return length
.QuadPart
;
257 fstat( _handle
, &stats
);
258 return stats
.st_size
;
262 indri::file::FileMapping
* indri::file::File::mapRegion( UINT64 position
, UINT64 length
, bool readOnly
, bool wholeFile
) {
269 DWORD createFlags
= readOnly
? PAGE_READONLY
: PAGE_READWRITE
;
270 DWORD flags
= readOnly
? FILE_MAP_READ
: FILE_MAP_ALL_ACCESS
;
272 DWORD offsetHigh
= (position
>> 32);
273 DWORD offsetLow
= (position
& 0xFFffFFff);
275 // on 32-bit windows, we may ask for a region that's too big
276 SIZE_T maxSizeT
= ~( (SIZE_T
) 0 );
277 if( length
> (UINT64
)maxSizeT
)
278 LEMUR_THROW( LEMUR_IO_ERROR
, "Requested a file mapping that's too big for your operating system" );
280 UINT64 end
= position
+ length
;
281 DWORD endHigh
= (end
>> 32);
282 DWORD endLow
= (end
& 0xFFffFFff);
284 HANDLE mappingHandle
= CreateFileMapping( _handle
, NULL
, createFlags
, endHigh
, endLow
, 0 );
286 if( mappingHandle
== INVALID_HANDLE_VALUE
) {
287 LEMUR_THROW( LEMUR_IO_ERROR
, "Failed to create file mapping" );
290 void* map
= MapViewOfFileEx( mappingHandle
, flags
, offsetHigh
, offsetLow
, (SIZE_T
)length
);
293 CloseHandle(mappingHandle
);
294 LEMUR_THROW( LEMUR_IO_ERROR
, "Failed to create file mapping" );
297 return new FileMapping( mappingHandle
, map
, length
);
304 size_t maxSizeT
= ~( (size_t) 0 );
305 if( length
> (UINT64
)maxSizeT
)
308 int prot
= readOnly
? PROT_READ
: (PROT_READ
|PROT_WRITE
);
309 void* map
= mmap(0, (size_t)length
, prot
, MAP_SHARED
, _handle
, position
);
311 if( !map
|| map
== MAP_FAILED
) {
312 LEMUR_THROW( LEMUR_IO_ERROR
, "Failed to create file mapping" );
315 return new FileMapping( map
, length
);
319 indri::file::FileMapping
* indri::file::File::mapFileRead() {
320 return mapRegion( 0, 0, true, true );
323 indri::file::FileMapping
* indri::file::File::mapFile() {
324 return mapRegion( 0, 0, false, true );
327 indri::file::FileMapping
* indri::file::File::mapRegion( UINT64 position
, UINT64 length
) {
328 return mapRegion( position
, length
, false, false );
331 indri::file::FileMapping
* indri::file::File::mapRegionRead( UINT64 position
, UINT64 length
) {
332 return mapRegion( position
, length
, true, false );